SlideShare a Scribd company logo
How Kris Writes Symfony Apps
@kriswallsmith
father artist bowhunter hacker
president widower gamer actor
tapdancer lover hater singer
writer founder yogi consultant
archer musician architect slacker
soccer player volunteer home
owner scotch drinker pianist…
assetic
Buzz
Spork
Getting Started
composer create-project !
symfony/framework-standard-edition !
widgets-by-kris/ !
~2.4
+
+
+
+

"doctrine/orm": "~2.2,>=2.2.3",!
"doctrine/doctrine-bundle": "~1.2",!
"doctrine/mongodb-odm-bundle": "~3.0",!
"jms/di-extra-bundle": "~1.4",!
"jms/security-extra-bundle": "~1.5",!
"jms/serializer-bundle": "~1.0",
./app/console generate:bundle !
--namespace=Kris/Bundle/MainBundle
public function registerContainerConfiguration(LoaderInterface $loader)!
{!
$loader->load(__DIR__.'/config/config_'.$this->getEnvironment().'.yml');!
!
// load local_*.yml or local.yml!
if (!
file_exists($file = __DIR__.'/config/local_'.$this->getEnvironment().'.yml')!
||!
file_exists($file = __DIR__.'/config/local.yml')!
) {!
$loader->load($file);!
}!
}
Model
Treat your model like a princess.
She gets her own wing
of the palace…
doctrine_mongodb:!
auto_generate_hydrator_classes: %kernel.debug%!
auto_generate_proxy_classes:
%kernel.debug%!
connections: { default: ~ }!
document_managers:!
default:!
connection: default!
database:
kris!
mappings:!
model:!
type:
annotation!
dir:
%src%/Kris/Model!
prefix: KrisModel!
alias: Model
// repo for src/Kris/Model/Widget.php!
$repo = $this->dm->getRepository('Model:User');
…doesn't do any work…
use KrisBundleMainBundleCanonicalizer;!
!

public function setUsername($username)!
{!
$this->username = $username;!
!

$canonicalizer = Canonicalizer::instance();!
$this->usernameCanonical = $canonicalizer->canonicalize($username);!
}
use KrisBundleMainBundleCanonicalizer;!
!

public function setUsername($username, Canonicalizer $canonicalizer)!
{!
$this->username = $username;!
$this->usernameCanonical = $canonicalizer->canonicalize($username);!
}
…and is unaware of the work
being done around her.
public function setUsername($username)!
{!
// a listener will update the!
// canonical username!
$this->username = $username;!
}
Anemic domain model 

is an anti-pattern?
Anemic???
“The fundamental horror of this anti-pattern is that it's
so contrary to the basic idea of object-oriented design;
which is to combine data and process together.”	

!

Martin Fowler
$cabinet->open();
Cabinets don’t open themselves.
$asset->getLastModified();
Mapping Layers
thin
thin controller

fat model
MVC
Is Symfony an MVC framework?
HTTP
Application Land

Controller

HTTP Land
The controller is thin 

because it maps from 

HTTP-land to application-land.
What about the model?
public function registerAction()!
{!
// ...!
$user->sendWelcomeEmail();!
// ...!
}
public function registerAction()!
{!
// ...!
$mailer->sendWelcomeEmail($user);!
// ...!
}
Persistence Land

Model

Application Land
The model maps from
application-land to persistence-land.
Persistence Land

Model

Application Land

Controller

HTTP Land
Who lives in application land?
Thin controller, thin model…


Fat service layer!
Application Events
Use them.
That happened.
/** @DIObserve("user.username_change") */!
public function onUsernameChange(UserEvent $event)!
{!
$user = $event->getUser();!
$dm
= $event->getDocumentManager();!
!

$dm->getRepository('Model:Widget')!
->updateDenormalizedUsernames($user);!
}
One event class per model
•
•
•

Event name constants	

Accepts object manager and object as arguments	

Simple accessors
$event = new UserEvent($dm, $user);!
$dispatcher->dispatch(UserEvent::CREATE, $event);
$event = new UserUserEvent($dm, $user, $otherUser);!
$dispatcher->dispatch(UserEvent::FOLLOW, $event);
preFlush
public function preFlush(ManagerEventArgs $event)!
{!
$dm = $event->getObjectManager();!
$uow = $dm->getUnitOfWork();!
!
foreach ($uow->getIdentityMap() as $class => $docs) {!
if (is_a($class, 'KrisModelUser')) {!
foreach ($docs as $doc) {!
$this->processUserFlush($dm, $doc);!
}!
} elseif (is_a($class, 'KrisModelWidget')) {!
foreach ($docs as $doc) {!
$this->processWidgetFlush($dm, $doc);!
}!
}!
}!
}
/** @DIObserve("user.create") */!
public function onUserCreate(UserEvent $event)!
{!
$user = $event->getUser();!
!

$activity = new Activity();!
$activity->setActor($user);!
$activity->setVerb('register');!
$activity->setCreatedAt($user->getCreatedAt());!
!

$this->dm->persist($activity);!
}
/** @DIObserve("user.follow_user") */!
public function onFollowUser(UserUserEvent $event)!
{!
$event->getUser()!
->getStats()!
->incrementFollowedUsers(1);!
$event->getOtherUser()!
->getStats()!
->incrementFollowers(1);!
}
Decouple your application by
delegating work to clean, concise,
single-purpose event listeners.
Contextual Configuration
Save your future self a headache
# @MainBundle/Resources/config/widget.yml!
services:!
widget_twiddler:!
class: KrisBundleMainBundleWidgetTwiddler!
arguments:!
- @event_dispatcher!
- @?logger
JMSDiExtraBundle
/** @DIService("widget_twiddler") */!
class Twiddler!
{!
/** @DIInjectParams */!
public function __construct(!
EventDispatcherInterface $dispatcher,!
LoggerInterface $logger = null)!
{!
// ...!
}!
}
services:!
# aliases for auto-wiring!
container: @service_container!
dm: @doctrine_mongodb.odm.document_manager!
doctrine: @doctrine_mongodb!
dispatcher: @event_dispatcher!
security: @security.context
require.js
<script src="{{ asset('js/lib/require.js') }}"></script>!
<script>!
require.config({!
baseUrl: "{{ asset('js') }}",!
paths: {!
"jquery": "//ajax.googleapis.com/.../jquery.min",!
"underscore": "lib/underscore",!
"backbone": "lib/backbone"!
},!
shim: {!
"jquery": { exports: "jQuery" },!
"underscore": { exports: "_" },!
"backbone": {!
deps: [ "jquery", "underscore" ],!
exports: "Backbone"!
}!
}!
})!
require([ "main" ])!
</script>
// web/js/model/user.js!
define(!
[ "underscore", "backbone" ],!
function(_, Backbone) {!
var tmpl = _.template("<%- first %> <%- last %>")!
return Backbone.Model.extend({!
name: function() {!
return tmpl({!
first: this.get("first_name"),!
last: this.get("last_name")!
})!
}!
})!
}!
)
{% block head %}!
<script>!
require(!
[ "view/user", "model/user" ],!
function(UserView, User) {!
var view = new UserView({!
model: new User({{ user|serialize|raw }}),!
el: document.getElementById("user")!
})!
}!
)!
</script>!
{% endblock %}
Dependencies
•
•
•

model: backbone, underscore	

view: backbone, jquery	

template: model, view
{% javascripts!
"js/lib/jquery.js" "js/lib/underscore.js"!
"js/lib/backbone.js" "js/model/user.js"!
"js/view/user.js"!
filter="?uglifyjs2" output="js/packed/user.js" %}!
<script src="{{ asset_url }}"></script>!
{% endjavascripts %}!
!

<script>!
var view = new UserView({!
model: new User({{ user|serialize|raw }}),!
el: document.getElementById("user")!
})!
</script>
Unused dependencies
naturally slough off
JMSSerializerBundle
{% block head %}!
<script>!
require(!
[ "view/user", "model/user" ],!
function(UserView, User) {!
var view = new UserView({!
model: new User({{ user|serialize|raw }}),!
el: document.getElementById("user")!
})!
}!
)!
</script>!
{% endblock %}
/** @ExclusionPolicy("ALL") */!
class User!
{!
private $id;!
!

/** @Expose */!
private $firstName;!
!

/** @Expose */!
private $lastName;!
}
Miscellaneous
When to create a new bundle
•
•
•

Anything reusable	

Lots of classes relating to one feature	

Integration with a third party
{% include 'MainBundle:Account/Widget:sidebar.html.twig' %}
{% include 'AccountBundle:Widget:sidebar.html.twig' %}
Access Control
The Symfony ACL is for
arbitrary permissions
Encapsulate access logic in
custom voter classes
/** @DIService(public=false) @DITag("security.voter") */!
class WidgetVoter implements VoterInterface!
{!
public function supportsAttribute($attribute)!
{!
return 'OWNER' === $attribute;!
}!
!
public function supportsClass($class)!
{!
return is_a($class, 'KrisModelWidget');!
}!
!
public function vote(TokenInterface $token, $widget, array $attributes)!
{!
// ...!
}!
}
public function vote(TokenInterface $token, $widget, array $attributes)!
{!
$result = VoterInterface::ACCESS_ABSTAIN;!
if (!$this->supportsClass(get_class($widget))) {!
return $result;!
}!
!
foreach ($attributes as $attribute) {!
if (!$this->supportsAttribute($attribute)) {!
continue;!
}!
!
$result = VoterInterface::ACCESS_DENIED;!
if ($token->getUser() === $widget->getUser()) {!
return VoterInterface::ACCESS_GRANTED;!
}!
}!
!
return $result;!
}
JMSSecurityExtraBundle
/** @SecureParam(name="widget", permissions="OWNER") */!
public function editAction(Widget $widget)!
{!
// ...!
}
{% if is_granted('OWNER', widget) %}!
{# ... #}!
{% endif %}
No query builders
outside of repositories
class WidgetRepository extends DocumentRepository!
{!
public function findByUser(User $user)!
{!
return $this->createQueryBuilder()!
->field('userId')->equals($user->getId())!
->getQuery()!
->execute();!
}!
!
public function updateDenormalizedUsernames(User $user)!
{!
$this->createQueryBuilder()!
->update()!
->multiple()!
->field('userId')->equals($user->getId())!
->field('userName')->set($user->getUsername())!
->getQuery()!
->execute();!
}!
}
Eager ID creation
public function __construct()!
{!
$this->id = (string) new MongoId();!
}
public function __construct()!
{!
$this->id = (string) new MongoId();!
$this->createdAt = new DateTime();!
$this->widgets = new ArrayCollection();!
}
Remember your
clone constructor
$foo = new Foo();!
$bar = clone $foo;
public function __clone()!
{!
$this->id = (string) new MongoId();!
$this->createdAt = new DateTime();!
$this->widgets = new ArrayCollection(!
$this->widgets->toArray()!
);!
}
public function __construct()!
{!
$this->id = (string) new MongoId();!
$this->createdAt = new DateTime();!
$this->widgets = new ArrayCollection();!
}!
!

public function __clone()!
{!
$this->id = (string) new MongoId();!
$this->createdAt = new DateTime();!
$this->widgets = new ArrayCollection(!
$this->widgets->toArray()!
);!
}
Save space on field names
/** @ODMString(name="u") */!
private $username;!
!

/** @ODMString(name="uc") @ODMUniqueIndex */!
private $usernameCanonical;
Only flush from the controller
public function theAction(Widget $widget)!
{!
$this->get('widget_twiddler')!
->skeedaddle($widget);!
$this->flush();!
}
No proxy objects
/** @ODMReferenceOne(targetDocument="User") */!
private $user;
public function getUser()!
{!
if ($this->userId && !$this->user) {!
throw new UninitializedReferenceException('user');!
}!
!

return $this->user;!
}
Questions?
@kriswallsmith.net

https://joind.in/10371

Thank You!

More Related Content

What's hot

jQuery Best Practice
jQuery Best Practice jQuery Best Practice
jQuery Best Practice
chandrashekher786
 
Mojolicious - Perl Framework for the Real-Time Web (Lightning Talk)
Mojolicious - Perl Framework for the Real-Time Web (Lightning Talk)Mojolicious - Perl Framework for the Real-Time Web (Lightning Talk)
Mojolicious - Perl Framework for the Real-Time Web (Lightning Talk)
Dotan Dimet
 
Mojolicious: what works and what doesn't
Mojolicious: what works and what doesn'tMojolicious: what works and what doesn't
Mojolicious: what works and what doesn't
Cosimo Streppone
 
jQuery: Events, Animation, Ajax
jQuery: Events, Animation, AjaxjQuery: Events, Animation, Ajax
jQuery: Events, Animation, Ajax
Constantin Titarenko
 
Building Large jQuery Applications
Building Large jQuery ApplicationsBuilding Large jQuery Applications
Building Large jQuery Applications
Rebecca Murphey
 
Dojo Confessions
Dojo ConfessionsDojo Confessions
Dojo Confessions
Rebecca Murphey
 
Decoupling the Ulabox.com monolith. From CRUD to DDD
Decoupling the Ulabox.com monolith. From CRUD to DDDDecoupling the Ulabox.com monolith. From CRUD to DDD
Decoupling the Ulabox.com monolith. From CRUD to DDD
Aleix Vergés
 
Write Less Do More
Write Less Do MoreWrite Less Do More
Write Less Do More
Remy Sharp
 
DOM Scripting Toolkit - jQuery
DOM Scripting Toolkit - jQueryDOM Scripting Toolkit - jQuery
DOM Scripting Toolkit - jQuery
Remy Sharp
 
jQuery 1.7 Events
jQuery 1.7 EventsjQuery 1.7 Events
jQuery 1.7 Eventsdmethvin
 
jQuery
jQueryjQuery
jQuery in 15 minutes
jQuery in 15 minutesjQuery in 15 minutes
jQuery in 15 minutes
Simon Willison
 
Remy Sharp The DOM scripting toolkit jQuery
Remy Sharp The DOM scripting toolkit jQueryRemy Sharp The DOM scripting toolkit jQuery
Remy Sharp The DOM scripting toolkit jQuerydeimos
 
Mojolicious, real-time web framework
Mojolicious, real-time web frameworkMojolicious, real-time web framework
Mojolicious, real-time web frameworktaggg
 
Joe Walker Interactivewebsites Cometand Dwr
Joe Walker Interactivewebsites Cometand DwrJoe Walker Interactivewebsites Cometand Dwr
Joe Walker Interactivewebsites Cometand Dwrdeimos
 
HTML5: where flash isn't needed anymore
HTML5: where flash isn't needed anymoreHTML5: where flash isn't needed anymore
HTML5: where flash isn't needed anymore
Remy Sharp
 
Introducing Assetic: Asset Management for PHP 5.3
Introducing Assetic: Asset Management for PHP 5.3Introducing Assetic: Asset Management for PHP 5.3
Introducing Assetic: Asset Management for PHP 5.3
Kris Wallsmith
 
Mulberry: A Mobile App Development Toolkit
Mulberry: A Mobile App Development ToolkitMulberry: A Mobile App Development Toolkit
Mulberry: A Mobile App Development ToolkitRebecca Murphey
 
Symfony: Your Next Microframework (SymfonyCon 2015)
Symfony: Your Next Microframework (SymfonyCon 2015)Symfony: Your Next Microframework (SymfonyCon 2015)
Symfony: Your Next Microframework (SymfonyCon 2015)
Ryan Weaver
 

What's hot (20)

jQuery Best Practice
jQuery Best Practice jQuery Best Practice
jQuery Best Practice
 
Mojolicious - Perl Framework for the Real-Time Web (Lightning Talk)
Mojolicious - Perl Framework for the Real-Time Web (Lightning Talk)Mojolicious - Perl Framework for the Real-Time Web (Lightning Talk)
Mojolicious - Perl Framework for the Real-Time Web (Lightning Talk)
 
Mojolicious: what works and what doesn't
Mojolicious: what works and what doesn'tMojolicious: what works and what doesn't
Mojolicious: what works and what doesn't
 
jQuery: Events, Animation, Ajax
jQuery: Events, Animation, AjaxjQuery: Events, Animation, Ajax
jQuery: Events, Animation, Ajax
 
Building Large jQuery Applications
Building Large jQuery ApplicationsBuilding Large jQuery Applications
Building Large jQuery Applications
 
Dojo Confessions
Dojo ConfessionsDojo Confessions
Dojo Confessions
 
Decoupling the Ulabox.com monolith. From CRUD to DDD
Decoupling the Ulabox.com monolith. From CRUD to DDDDecoupling the Ulabox.com monolith. From CRUD to DDD
Decoupling the Ulabox.com monolith. From CRUD to DDD
 
Write Less Do More
Write Less Do MoreWrite Less Do More
Write Less Do More
 
DOM Scripting Toolkit - jQuery
DOM Scripting Toolkit - jQueryDOM Scripting Toolkit - jQuery
DOM Scripting Toolkit - jQuery
 
jQuery 1.7 Events
jQuery 1.7 EventsjQuery 1.7 Events
jQuery 1.7 Events
 
jQuery
jQueryjQuery
jQuery
 
jQuery in 15 minutes
jQuery in 15 minutesjQuery in 15 minutes
jQuery in 15 minutes
 
Mojolicious
MojoliciousMojolicious
Mojolicious
 
Remy Sharp The DOM scripting toolkit jQuery
Remy Sharp The DOM scripting toolkit jQueryRemy Sharp The DOM scripting toolkit jQuery
Remy Sharp The DOM scripting toolkit jQuery
 
Mojolicious, real-time web framework
Mojolicious, real-time web frameworkMojolicious, real-time web framework
Mojolicious, real-time web framework
 
Joe Walker Interactivewebsites Cometand Dwr
Joe Walker Interactivewebsites Cometand DwrJoe Walker Interactivewebsites Cometand Dwr
Joe Walker Interactivewebsites Cometand Dwr
 
HTML5: where flash isn't needed anymore
HTML5: where flash isn't needed anymoreHTML5: where flash isn't needed anymore
HTML5: where flash isn't needed anymore
 
Introducing Assetic: Asset Management for PHP 5.3
Introducing Assetic: Asset Management for PHP 5.3Introducing Assetic: Asset Management for PHP 5.3
Introducing Assetic: Asset Management for PHP 5.3
 
Mulberry: A Mobile App Development Toolkit
Mulberry: A Mobile App Development ToolkitMulberry: A Mobile App Development Toolkit
Mulberry: A Mobile App Development Toolkit
 
Symfony: Your Next Microframework (SymfonyCon 2015)
Symfony: Your Next Microframework (SymfonyCon 2015)Symfony: Your Next Microframework (SymfonyCon 2015)
Symfony: Your Next Microframework (SymfonyCon 2015)
 

Similar to How Kris Writes Symfony Apps

Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
Jonathan Wage
 
DrupalCon jQuery
DrupalCon jQueryDrupalCon jQuery
DrupalCon jQuery
Nathan Smith
 
Absolute Beginners Guide to Puppet Through Types - PuppetConf 2014
Absolute Beginners Guide to Puppet Through Types - PuppetConf 2014Absolute Beginners Guide to Puppet Through Types - PuppetConf 2014
Absolute Beginners Guide to Puppet Through Types - PuppetConf 2014
Puppet
 
Desymfony 2011 - Habemus Bundles
Desymfony 2011 - Habemus BundlesDesymfony 2011 - Habemus Bundles
Desymfony 2011 - Habemus BundlesAlbert Jessurum
 
Javascript is your (Auto)mate
Javascript is your (Auto)mateJavascript is your (Auto)mate
Javascript is your (Auto)mate
Codemotion
 
How kris-writes-symfony-apps-london
How kris-writes-symfony-apps-londonHow kris-writes-symfony-apps-london
How kris-writes-symfony-apps-london
Kris Wallsmith
 
Drupal 8, Where Did the Code Go? From Info Hook to Plugin
Drupal 8, Where Did the Code Go? From Info Hook to PluginDrupal 8, Where Did the Code Go? From Info Hook to Plugin
Drupal 8, Where Did the Code Go? From Info Hook to Plugin
Acquia
 
Building Your First Widget
Building Your First WidgetBuilding Your First Widget
Building Your First Widget
Chris Wilcoxson
 
KISSY 的昨天、今天与明天
KISSY 的昨天、今天与明天KISSY 的昨天、今天与明天
KISSY 的昨天、今天与明天
tblanlan
 
kissy-past-now-future
kissy-past-now-futurekissy-past-now-future
kissy-past-now-futureyiming he
 
Rails 3: Dashing to the Finish
Rails 3: Dashing to the FinishRails 3: Dashing to the Finish
Rails 3: Dashing to the FinishYehuda Katz
 
Burn down the silos! Helping dev and ops gel on high availability websites
Burn down the silos! Helping dev and ops gel on high availability websitesBurn down the silos! Helping dev and ops gel on high availability websites
Burn down the silos! Helping dev and ops gel on high availability websites
Lindsay Holmwood
 
A re introduction to webpack - reactfoo - mumbai
A re introduction to webpack - reactfoo - mumbaiA re introduction to webpack - reactfoo - mumbai
A re introduction to webpack - reactfoo - mumbai
Praveen Puglia
 
Bubbles & Trees with jQuery
Bubbles & Trees with jQueryBubbles & Trees with jQuery
Bubbles & Trees with jQuery
Bastian Feder
 
The state of your own hypertext preprocessor
The state of your own hypertext preprocessorThe state of your own hypertext preprocessor
The state of your own hypertext preprocessor
Alessandro Nadalin
 
The Beauty of Java Script
The Beauty of Java ScriptThe Beauty of Java Script
The Beauty of Java Script
Michael Girouard
 
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
Tsuyoshi Yamamoto
 
How to actually use promises - Jakob Mattsson, FishBrain
How to actually use promises - Jakob Mattsson, FishBrainHow to actually use promises - Jakob Mattsson, FishBrain
How to actually use promises - Jakob Mattsson, FishBrain
Codemotion Tel Aviv
 

Similar to How Kris Writes Symfony Apps (20)

Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
 
DrupalCon jQuery
DrupalCon jQueryDrupalCon jQuery
DrupalCon jQuery
 
Migrare da symfony 1 a Symfony2
 Migrare da symfony 1 a Symfony2  Migrare da symfony 1 a Symfony2
Migrare da symfony 1 a Symfony2
 
Absolute Beginners Guide to Puppet Through Types - PuppetConf 2014
Absolute Beginners Guide to Puppet Through Types - PuppetConf 2014Absolute Beginners Guide to Puppet Through Types - PuppetConf 2014
Absolute Beginners Guide to Puppet Through Types - PuppetConf 2014
 
Desymfony 2011 - Habemus Bundles
Desymfony 2011 - Habemus BundlesDesymfony 2011 - Habemus Bundles
Desymfony 2011 - Habemus Bundles
 
Javascript is your (Auto)mate
Javascript is your (Auto)mateJavascript is your (Auto)mate
Javascript is your (Auto)mate
 
How kris-writes-symfony-apps-london
How kris-writes-symfony-apps-londonHow kris-writes-symfony-apps-london
How kris-writes-symfony-apps-london
 
Having Fun with Play
Having Fun with PlayHaving Fun with Play
Having Fun with Play
 
Drupal 8, Where Did the Code Go? From Info Hook to Plugin
Drupal 8, Where Did the Code Go? From Info Hook to PluginDrupal 8, Where Did the Code Go? From Info Hook to Plugin
Drupal 8, Where Did the Code Go? From Info Hook to Plugin
 
Building Your First Widget
Building Your First WidgetBuilding Your First Widget
Building Your First Widget
 
KISSY 的昨天、今天与明天
KISSY 的昨天、今天与明天KISSY 的昨天、今天与明天
KISSY 的昨天、今天与明天
 
kissy-past-now-future
kissy-past-now-futurekissy-past-now-future
kissy-past-now-future
 
Rails 3: Dashing to the Finish
Rails 3: Dashing to the FinishRails 3: Dashing to the Finish
Rails 3: Dashing to the Finish
 
Burn down the silos! Helping dev and ops gel on high availability websites
Burn down the silos! Helping dev and ops gel on high availability websitesBurn down the silos! Helping dev and ops gel on high availability websites
Burn down the silos! Helping dev and ops gel on high availability websites
 
A re introduction to webpack - reactfoo - mumbai
A re introduction to webpack - reactfoo - mumbaiA re introduction to webpack - reactfoo - mumbai
A re introduction to webpack - reactfoo - mumbai
 
Bubbles & Trees with jQuery
Bubbles & Trees with jQueryBubbles & Trees with jQuery
Bubbles & Trees with jQuery
 
The state of your own hypertext preprocessor
The state of your own hypertext preprocessorThe state of your own hypertext preprocessor
The state of your own hypertext preprocessor
 
The Beauty of Java Script
The Beauty of Java ScriptThe Beauty of Java Script
The Beauty of Java Script
 
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
Grails 1.2 探検隊 -新たな聖杯をもとめて・・・-
 
How to actually use promises - Jakob Mattsson, FishBrain
How to actually use promises - Jakob Mattsson, FishBrainHow to actually use promises - Jakob Mattsson, FishBrain
How to actually use promises - Jakob Mattsson, FishBrain
 

More from Kris Wallsmith

The View From Inside
The View From InsideThe View From Inside
The View From Inside
Kris Wallsmith
 
Assetic (Zendcon)
Assetic (Zendcon)Assetic (Zendcon)
Assetic (Zendcon)
Kris Wallsmith
 
Assetic (Symfony Live Paris)
Assetic (Symfony Live Paris)Assetic (Symfony Live Paris)
Assetic (Symfony Live Paris)
Kris Wallsmith
 
Introducing Assetic (NYPHP)
Introducing Assetic (NYPHP)Introducing Assetic (NYPHP)
Introducing Assetic (NYPHP)Kris Wallsmith
 
Doctrine MongoDB ODM (PDXPHP)
Doctrine MongoDB ODM (PDXPHP)Doctrine MongoDB ODM (PDXPHP)
Doctrine MongoDB ODM (PDXPHP)
Kris Wallsmith
 
Advanced symfony Techniques
Advanced symfony TechniquesAdvanced symfony Techniques
Advanced symfony Techniques
Kris Wallsmith
 
A Practical Introduction to Symfony2
A Practical Introduction to Symfony2A Practical Introduction to Symfony2
A Practical Introduction to Symfony2
Kris Wallsmith
 
Symfony in the Cloud
Symfony in the CloudSymfony in the Cloud
Symfony in the Cloud
Kris Wallsmith
 

More from Kris Wallsmith (10)

The View From Inside
The View From InsideThe View From Inside
The View From Inside
 
Assetic (Zendcon)
Assetic (Zendcon)Assetic (Zendcon)
Assetic (Zendcon)
 
Assetic (OSCON)
Assetic (OSCON)Assetic (OSCON)
Assetic (OSCON)
 
Assetic (Symfony Live Paris)
Assetic (Symfony Live Paris)Assetic (Symfony Live Paris)
Assetic (Symfony Live Paris)
 
Introducing Assetic (NYPHP)
Introducing Assetic (NYPHP)Introducing Assetic (NYPHP)
Introducing Assetic (NYPHP)
 
Doctrine MongoDB ODM (PDXPHP)
Doctrine MongoDB ODM (PDXPHP)Doctrine MongoDB ODM (PDXPHP)
Doctrine MongoDB ODM (PDXPHP)
 
Advanced symfony Techniques
Advanced symfony TechniquesAdvanced symfony Techniques
Advanced symfony Techniques
 
A Practical Introduction to Symfony2
A Practical Introduction to Symfony2A Practical Introduction to Symfony2
A Practical Introduction to Symfony2
 
Symfony 2
Symfony 2Symfony 2
Symfony 2
 
Symfony in the Cloud
Symfony in the CloudSymfony in the Cloud
Symfony in the Cloud
 

Recently uploaded

Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
ThousandEyes
 
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
Product School
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
James Anderson
 
Connector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a buttonConnector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a button
DianaGray10
 
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
BookNet Canada
 
Essentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with ParametersEssentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with Parameters
Safe Software
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Inflectra
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance
 
Generating a custom Ruby SDK for your web service or Rails API using Smithy
Generating a custom Ruby SDK for your web service or Rails API using SmithyGenerating a custom Ruby SDK for your web service or Rails API using Smithy
Generating a custom Ruby SDK for your web service or Rails API using Smithy
g2nightmarescribd
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
Guy Korland
 
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
Sri Ambati
 
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Thierry Lestable
 
When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...
Elena Simperl
 
Elevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object CalisthenicsElevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object Calisthenics
Dorra BARTAGUIZ
 
Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !
KatiaHIMEUR1
 
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
Product School
 
The Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and SalesThe Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and Sales
Laura Byrne
 
Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*
Frank van Harmelen
 
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
DanBrown980551
 
Leading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdfLeading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdf
OnBoard
 

Recently uploaded (20)

Assuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyesAssuring Contact Center Experiences for Your Customers With ThousandEyes
Assuring Contact Center Experiences for Your Customers With ThousandEyes
 
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
 
Connector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a buttonConnector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a button
 
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...Transcript: Selling digital books in 2024: Insights from industry leaders - T...
Transcript: Selling digital books in 2024: Insights from industry leaders - T...
 
Essentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with ParametersEssentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with Parameters
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
 
Generating a custom Ruby SDK for your web service or Rails API using Smithy
Generating a custom Ruby SDK for your web service or Rails API using SmithyGenerating a custom Ruby SDK for your web service or Rails API using Smithy
Generating a custom Ruby SDK for your web service or Rails API using Smithy
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
 
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
GenAISummit 2024 May 28 Sri Ambati Keynote: AGI Belongs to The Community in O...
 
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
 
When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...
 
Elevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object CalisthenicsElevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object Calisthenics
 
Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !
 
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
 
The Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and SalesThe Art of the Pitch: WordPress Relationships and Sales
The Art of the Pitch: WordPress Relationships and Sales
 
Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*
 
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
 
Leading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdfLeading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdf
 

How Kris Writes Symfony Apps