SlideShare une entreprise Scribd logo
1  sur  75
Télécharger pour lire hors ligne
How Kris Writes Symfony Apps
Mapping Layers
thin
thin controller fat model
MVC
Is Symfony an MVC framework?
HTTP
Symfony is an HTTP framework
Application Land 
Controller 
HTTP Land
The controller is thin 
because it maps from 
HTTP-land to application-land.
What about the model?
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
Should there be managers?
Application Events
Listen
/** @DIObserve(UserEvent::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(UserEvent::USERNAME_CHANGE) */ 
public function onUsernameChange(UserEvent $event) 
{ 
$user = $event->getUser(); 
$dm = $event->getDocumentManager(); 
$dm->getRepository('Model:Widget') 
->updateDenormalizedUsernames($user); 
}
/** @DIObserve(UserEvent::FOLLOW) */ 
public function onFollow(UserUserEvent $event) 
{ 
$event->getUser() 
->getStats() 
->incrementFollowedUsers(1); 
$event->getOtherUser() 
->getStats() 
->incrementFollowers(1); 
}
Dispatch
$event = new UserEvent($dm, $user); 
$dispatcher->dispatch(UserEvent::CREATE, $event);
$event = new UserEvent($dm, $user); 
$dispatcher->dispatch(UserEvent::UPDATE, $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); 
} 
} 
} 
}
Decouple your application by 
delegating work to clean, concise, 
single-purpose event listeners.
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/User.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; 
}
Cabinets don’t open themselves.
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
{% 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 %}
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; 
}
Five more things…
When to create a new bundle 
• Anything reusable 
• A new feature 
• 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
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() 
); 
}
Only flush from the controller
public function theAction(Widget $widget) 
{ 
$this->get('widget_twiddler') 
->skeedaddle($widget); 
$this->flush(); 
}
Questions?

Contenu connexe

Tendances

jQuery 1.7 Events
jQuery 1.7 EventsjQuery 1.7 Events
jQuery 1.7 Events
dmethvin
 
Jqeury ajax plugins
Jqeury ajax pluginsJqeury ajax plugins
Jqeury ajax plugins
Inbal Geffen
 
Kick start with j query
Kick start with j queryKick start with j query
Kick start with j query
Md. Ziaul Haq
 
Mulberry: A Mobile App Development Toolkit
Mulberry: A Mobile App Development ToolkitMulberry: A Mobile App Development Toolkit
Mulberry: A Mobile App Development Toolkit
Rebecca Murphey
 
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
deimos
 

Tendances (20)

Introduction to CQRS and Event Sourcing
Introduction to CQRS and Event SourcingIntroduction to CQRS and Event Sourcing
Introduction to CQRS and Event Sourcing
 
Bacbkone js
Bacbkone jsBacbkone js
Bacbkone js
 
How I started to love design patterns
How I started to love design patternsHow I started to love design patterns
How I started to love design patterns
 
An Introduction to Jquery
An Introduction to JqueryAn Introduction to Jquery
An Introduction to Jquery
 
DOM Scripting Toolkit - jQuery
DOM Scripting Toolkit - jQueryDOM Scripting Toolkit - jQuery
DOM Scripting Toolkit - jQuery
 
Symfony CoP: Form component
Symfony CoP: Form componentSymfony CoP: Form component
Symfony CoP: Form component
 
Special Events
Special EventsSpecial Events
Special Events
 
How I started to love design patterns
How I started to love design patternsHow I started to love design patterns
How I started to love design patterns
 
Javascript and jQuery intro
Javascript and jQuery introJavascript and jQuery intro
Javascript and jQuery intro
 
jQuery 1.7 Events
jQuery 1.7 EventsjQuery 1.7 Events
jQuery 1.7 Events
 
Building Large jQuery Applications
Building Large jQuery ApplicationsBuilding Large jQuery Applications
Building Large jQuery Applications
 
amsterdamjs - jQuery 1.5
amsterdamjs - jQuery 1.5amsterdamjs - jQuery 1.5
amsterdamjs - jQuery 1.5
 
Advanced jQuery
Advanced jQueryAdvanced jQuery
Advanced jQuery
 
Functionality Focused Code Organization
Functionality Focused Code OrganizationFunctionality Focused Code Organization
Functionality Focused Code Organization
 
Dojo Confessions
Dojo ConfessionsDojo Confessions
Dojo Confessions
 
Jqeury ajax plugins
Jqeury ajax pluginsJqeury ajax plugins
Jqeury ajax plugins
 
Kick start with j query
Kick start with j queryKick start with j query
Kick start with j query
 
AngularJS Routing
AngularJS RoutingAngularJS Routing
AngularJS Routing
 
Mulberry: A Mobile App Development Toolkit
Mulberry: A Mobile App Development ToolkitMulberry: A Mobile App Development Toolkit
Mulberry: A Mobile App Development Toolkit
 
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
 

Similaire à How kris-writes-symfony-apps-london

Phpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsPhpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friends
Michael Peacock
 

Similaire à How kris-writes-symfony-apps-london (20)

Symfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technologySymfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technology
 
Phpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsPhpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friends
 
WordPress REST API hacking
WordPress REST API hackingWordPress REST API hacking
WordPress REST API hacking
 
Symfony components in the wild, PHPNW12
Symfony components in the wild, PHPNW12Symfony components in the wild, PHPNW12
Symfony components in the wild, PHPNW12
 
Migrare da symfony 1 a Symfony2
 Migrare da symfony 1 a Symfony2  Migrare da symfony 1 a Symfony2
Migrare da symfony 1 a Symfony2
 
Symfony2 - from the trenches
Symfony2 - from the trenchesSymfony2 - from the trenches
Symfony2 - from the trenches
 
Symfony2 your way
Symfony2   your waySymfony2   your way
Symfony2 your way
 
Crafting beautiful software
Crafting beautiful softwareCrafting beautiful software
Crafting beautiful software
 
Magento Live Australia 2016: Request Flow
Magento Live Australia 2016: Request FlowMagento Live Australia 2016: Request Flow
Magento Live Australia 2016: Request Flow
 
Bag Of Tricks From Iusethis
Bag Of Tricks From IusethisBag Of Tricks From Iusethis
Bag Of Tricks From Iusethis
 
Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5
 
Symfony2 from the Trenches
Symfony2 from the TrenchesSymfony2 from the Trenches
Symfony2 from the Trenches
 
Drupal 8 Services And Dependency Injection
Drupal 8 Services And Dependency InjectionDrupal 8 Services And Dependency Injection
Drupal 8 Services And Dependency Injection
 
Service approach for development REST API in Symfony2
Service approach for development REST API in Symfony2Service approach for development REST API in Symfony2
Service approach for development REST API in Symfony2
 
Decoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICDecoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DIC
 
Symfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il clienteSymfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il cliente
 
Refactoring using Codeception
Refactoring using CodeceptionRefactoring using Codeception
Refactoring using Codeception
 
Symfony tips and tricks
Symfony tips and tricksSymfony tips and tricks
Symfony tips and tricks
 
Unittests für Dummies
Unittests für DummiesUnittests für Dummies
Unittests für Dummies
 
Application Layer in PHP
Application Layer in PHPApplication Layer in PHP
Application Layer in PHP
 

Plus de Kris Wallsmith

Introducing Assetic (NYPHP)
Introducing Assetic (NYPHP)Introducing Assetic (NYPHP)
Introducing Assetic (NYPHP)
Kris Wallsmith
 

Plus de Kris Wallsmith (11)

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)
 
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
 
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
 

Dernier

Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Victor Rentea
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
WSO2
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 

Dernier (20)

Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering Developers
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
 
Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital Adaptability
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 

How kris-writes-symfony-apps-london