SlideShare ist ein Scribd-Unternehmen logo
1 von 32
Downloaden Sie, um offline zu lesen
Application Layer
ein Vortrag von Per Bernhardt
Agenda
• Disclaimer / Credits
• Ein kleines bisschen Theorie
• Ein echtes Beispiel: Chefkoch API
Credit goes to…
• http://martinfowler.com/
• http://domainlanguage.com/
• http://alistair.cockburn.us/
• http://www.whitewashing.de/
• und viele andere..
Ein bisschen
Theorie…
Application Layer
Presentation Layer
Infrastructure Layer
Domain Layer
Application Layer
Presentation Layer
Infrastructure Layer
Domain Layer
- Controller
- Template / HTML
- Session / HTTP
Application Layer
Presentation Layer
Infrastructure Layer
Domain Layer
- Controller
- Template / HTML
- Session / HTTP
- Fasade
- Transaktionen
- Sicherheit / Zugriffsschutz
- Integration / Orchestrierung
Application Layer
Presentation Layer
Infrastructure Layer
Domain Layer
- Controller
- Template / HTML
- Session / HTTP
- Fasade
- Transaktionen
- Sicherheit / Zugriffsschutz
- Integration / Orchestrierung
- Daten
- Geschäftslogik
Application Layer
Presentation Layer
Infrastructure Layer
Domain Layer
- Controller
- Template / HTML
- Session / HTTP
- Fasade
- Transaktionen
- Sicherheit / Zugriffsschutz
- Integration / Orchestrierung
- Daten
- Geschäftslogik
- Datenbank
- Mailserver
- Logger
- …
Application Layer
Presentation Layer
Infrastructure Layer
Domain Layer
- Controller
- Template / HTML
- Session / HTTP
- Fasade
- Transaktionen
- Sicherheit / Zugriffsschutz
- Integration / Orchestrierung
- Daten
- Geschäftslogik
- Datenbank
- Mailserver
- Logger
- …
Application Layer
Presentation Layer
Infrastructure Layer
Domain Layer
- Controller
- Template / HTML
- Session / HTTP
- Fasade
- Transaktionen
- Sicherheit / Zugriffsschutz
- Integration / Orchestrierung
- Daten
- Geschäftslogik
- Datenbank
- Mailserver
- Logger
- …
Chefkoch API
POST /cookbooks/{id}/categories
<?php
!
namespace ChefkochBundleApiBundleController;
!
use SymfonyBundleFrameworkBundleControllerController;
use ChefkochDomainModelCookbookCookbookId
use SensioBundleFrameworkExtraBundleConfigurationParamConverter;
use ChefkochBundleApiBundleAnnotationApiSerialize;
use ChefkochApplicationCookbookRequest;
use ChefkochApplicationCookbookCommand;
use PixelhouseApplicationEventDispatchingService;
use PixelhouseApplicationResponse;
!
class CookbookController extends Controller
{
!
...
!
/**
* @ParamConverter("category", options={"deserialize"=true})
* @ApiSerialize
* @return Response
*/
public function saveCategoryAction(CookbookId $cookbookId, RequestCategoryRequest $category)
{
return $this->getCookbookService()->execute(
new CommandSaveCategoryCommand($cookbookId, $category)
);
}
!
...
!
/**
* @return DispatchingService
*/
private function getCookbookService()
{
return $this->get('chefkoch_api.application.cookbook_service');
}
}
<?php
!
namespace ChefkochApplicationCookbookCommand;
!
use ChefkochApplicationCookbookRequestCategoryRequest;
use ChefkochApplicationCookbookSecurityCookbookWriteAccessRequired;
use ChefkochDomainModelCookbookCookbookId;
use PixelhouseApplicationCommand;
!
class SaveCategoryCommand implements Command, CookbookWriteAccessRequired
{
!
/** @var CookbookId */
private $cookbookId;
!
/** @var CategoryRequest */
private $categoryRequest;
!
public function __construct(CookbookId $cookbookId, CategoryRequest $categoryRequest)
{
$this->cookbookId = $cookbookId;
$this->categoryRequest = $categoryRequest;
}
!
public function getCookbookId()
{
return $this->cookbookId;
}
!
public function getCategoryRequest()
{
return $this->categoryRequest;
}
}
<?php
!
namespace PixelhouseApplicationEvent;
!
use PixelhouseApplicationCommand;
use PixelhouseApplicationUseCase;
use PixelhouseEventDispatcherEventDispatcher;
!
class DispatchingService
{
!
/** @var EventDispatcher */
private $eventDispatcher;
!
/** @var UseCase[] */
private $useCases = array();
!
public function __construct(EventDispatcher $eventDispatcher)
{
$this->eventDispatcher = $eventDispatcher;
}
!
public function registerCommand($commandClass, UseCase $useCase)
{
$this->useCases[$commandClass] = $useCase;
}
!
public function execute(Command $command)
{
...
}
}
<?php
!
namespace PixelhouseApplicationEvent;
!
class Events
{
const PRE_COMMAND = 'application.pre_command';
const POST_COMMAND = 'application.post_command';
const EXCEPTION = 'application.exception';
}
<?php
!
namespace PixelhouseApplicationEvent;
!
use PixelhouseApplicationCommand;
!
class DispatchingService
{
!
...
!
public function execute(Command $command)
{
try {
$this->eventDispatcher->dispatch(
Events::PRE_COMMAND,
new CommandEvent($command)
);
$response = $this->useCases[get_class($command)]->run($command);
$this->eventDispatcher->dispatch(
Events::POST_COMMAND,
new PostCommandEvent($command, $response)
);
!
return $response;
} catch (Exception $exception) {
$event = new CommandExceptionEvent($command, $exception);
$this->eventDispatcher->dispatch(
Events::EXCEPTION,
$event
);
if ($response = $event->getResponse()) {
return $response;
} else {
throw $exception;
}
}
}
}
<?php
!
namespace ChefkochInfrastructureApplication;
!
use PixelhouseApplicationEvent;
use PixelhouseEventDispatcherSubscriber;
use DoctrineORMEntityManager;
!
class DoctrineTransactionListener implements Subscriber
{
!
/** @var EntityManager */
private $entityManager;
!
public function __construct(EntityManager $entityManager)
{
$this->entityManager = $entityManager;
}
!
public function preCommand(EventCommandEvent $event)
{
$this->entityManager->getConnection()->beginTransaction();
}
!
public function postCommand(EventPostCommandEvent $event)
{
$this->entityManager->flush();
$this->entityManager->getConnection()->commit();
}
!
public function onException(EventCommandExceptionEvent $event)
{
$this->entityManager->close();
if ($this->entityManager->getConnection()->isTransactionActive()) {
$this->entityManager->getConnection()->rollBack();
}
}
}
<?php
!
namespace PixelhouseApplicationSecurity;
!
use PixelhouseApplicationEvent;
use PixelhouseEventDispatcherSubscriber;
!
class SecurityListener implements Subscriber
{
!
/** @var Context */
private $context;
!
/** @var Policy[] */
private $policies = array();
!
public function __construct(Context $context)
{
$this->context = $context;
}
!
public function addPolicy(Policy $policy)
{
$this->policies[] = $policy;
}
!
/**
* throws Exception
*/
public function preCommand(EventCommandEvent $event)
{
foreach ($this->policies as $policy) {
$policy->check($this->securityContext, $event->getCommand());
}
}
}
<?php
!
namespace ChefkochApplicationCookbookSecurity;
!
use ChefkochDomainModelCookbookCookbookRepository;
use ChefkochUserDomainModelUserRepository;
use PixelhouseApplicationCommand;
use PixelhouseApplicationSecurityAccessDeniedException;
use PixelhouseApplicationSecurityContext;
use PixelhouseApplicationSecurityPolicy;
!
class CookbookAccessPolicy implements Policy
{
!
/** @var CookbookRepository */
private $cookbookRepository;
!
/** @var UserRepository */
private $userRepository;
!
public function __construct(CookbookRepository $cbRepo, UserRepository $uRepo)
{
$this->cookbookRepository = $cbRepo;
$this->userRepository = $uRepo;
}
!
public function check(Context $context, Command $command)
{
if ($command instanceof CookbookWriteAccessRequired) {
$cookbook = $this->cookbookRepository->findOneById($command->getCookbookId());
$user = $this->userRepository->findOneById($context->getUserId());
!
// Zugriff prüfen
...
!
throw new AccessDeniedException();
}
}
}
<?xml version="1.0" ?>
<container
xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services ...">
<services>
...
!
<service
id="chefkoch_api.application.use_case.cookbook_save_category"
class="ChefkochApplicationCookbookUseCaseSaveCategory">
<argument
type="service"
id="chefkoch_api.infrastructure.cookbook_category_repository" />
<argument
type="service"
id="chefkoch_api.infrastructure.user_repository" />
<argument
type="service"
id="chefkoch_api.application.security_context" />
<tag
name="chefkoch_api.application.use_case"
commandClass="ChefkochApplicationCookbookCommandSaveCategoryCommand"
applicationService="chefkoch_api.application.cookbook_service" />
</service>
!
...
</services>
</container>
<?php
!
namespace ChefkochApplicationCookbookUseCase;
!
use ChefkochApplicationCookbookCommandSaveCategoryCommand;
use PixelhouseApplicationSecurityContext;
use PixelhouseApplicationUseCase;
use ChefkochDomainModelCookbookCategoryRepository;
use ChefkochUserDomainModelUserRepository;
!
class SaveCategory implements UseCase
{
!
/** @var CategoryRepository */
private $categoryRepository;
!
/** @var UserRepository */
private $userRepository;
!
/** @var Context */
private $context;
!
public function __construct(CategoryRepository $cRepo, UserRepository $uRepo, Context $context)
{
$this->categoryRepository = $cRepo;
$this->userRepository = $uRepo;
$this->context = $context;
}
!
public function run(SaveCategoryCommand $command)
{
...
}
}
<?php
!
namespace ChefkochApplicationCookbookUseCase;
!
use PixelhouseApplicationUseCase;
use ChefkochApplicationCookbookCommandSaveCategoryCommand;
use ChefkochDomainModelCookbookCategory;
use ChefkochApplicationCookbookNotificationCategorySavedSuccess;
use ChefkochApplicationCookbookResponseCategoryResponse;
use PixelhouseApplicationResponse;
!
class SaveCategory implements UseCase
{
...
!
public function run(SaveCategoryCommand $command)
{
$user = $this->userRepository->findOneById($this->context->getUserId());
!
$category = new Category(
$command->getCookbookId(),
$user->getId(),
$command->getCategoryRequest()->getName(),
$command->getCategoryRequest()->getDescriptionText()
);
!
$this->categoryRepository->add($category);
!
$categoryResponse = new CategoryResponse($category, $user);
!
$response = new Response();
$response->getNotification()->addMessage(new CategorySavedSuccess($categoryResponse));
!
return $response;
}
}
HTTP/1.1 201 Created
Per Bernhardt
info@perprogramming.de
perprogramming.de
slideshare.net/perprogramming
Bilder
• Warning: https://www.flickr.com/photos/gerardstolk/
6538330609
• Show Time: https://www.flickr.com/photos/
florida_photo_guy/5212663826
• Question Marks: https://www.flickr.com/photos/
loneblackrider/315302588
• Thank You: https://www.flickr.com/photos/wwworks/
4759535950

Weitere ähnliche Inhalte

Was ist angesagt?

AnyMQ, Hippie, and the real-time web
AnyMQ, Hippie, and the real-time webAnyMQ, Hippie, and the real-time web
AnyMQ, Hippie, and the real-time webclkao
 
Cool like a Frontend Developer: Grunt, RequireJS, Bower and other Tools
Cool like a Frontend Developer: Grunt, RequireJS, Bower and other ToolsCool like a Frontend Developer: Grunt, RequireJS, Bower and other Tools
Cool like a Frontend Developer: Grunt, RequireJS, Bower and other ToolsRyan Weaver
 
Selenium sandwich-3: Being where you aren't.
Selenium sandwich-3: Being where you aren't.Selenium sandwich-3: Being where you aren't.
Selenium sandwich-3: Being where you aren't.Workhorse Computing
 
Node.js Express
Node.js  ExpressNode.js  Express
Node.js ExpressEyal Vardi
 
AnsibleFest 2014 - Role Tips and Tricks
AnsibleFest 2014 - Role Tips and TricksAnsibleFest 2014 - Role Tips and Tricks
AnsibleFest 2014 - Role Tips and Tricksjimi-c
 
Building Web Apps with Express
Building Web Apps with ExpressBuilding Web Apps with Express
Building Web Apps with ExpressAaron Stannard
 
Speed up web APIs with Expressive and Swoole (PHP Day 2018)
Speed up web APIs with Expressive and Swoole (PHP Day 2018) Speed up web APIs with Expressive and Swoole (PHP Day 2018)
Speed up web APIs with Expressive and Swoole (PHP Day 2018) Zend by Rogue Wave Software
 
A reviravolta do desenvolvimento web
A reviravolta do desenvolvimento webA reviravolta do desenvolvimento web
A reviravolta do desenvolvimento webWallace Reis
 
Nodejs first class
Nodejs first classNodejs first class
Nodejs first classFin Chen
 
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQueryRemedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQueryTatsuhiko Miyagawa
 
V2 and beyond
V2 and beyondV2 and beyond
V2 and beyondjimi-c
 
Using Sinatra to Build REST APIs in Ruby
Using Sinatra to Build REST APIs in RubyUsing Sinatra to Build REST APIs in Ruby
Using Sinatra to Build REST APIs in RubyLaunchAny
 
Building Cloud Castles
Building Cloud CastlesBuilding Cloud Castles
Building Cloud CastlesBen Scofield
 
Wykorzystanie form request przy implementacji API w Laravelu
Wykorzystanie form request przy implementacji API w LaraveluWykorzystanie form request przy implementacji API w Laravelu
Wykorzystanie form request przy implementacji API w LaraveluLaravel Poland MeetUp
 
Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2Shinya Ohyanagi
 
Puppet and the HashiStack
Puppet and the HashiStackPuppet and the HashiStack
Puppet and the HashiStackBram Vogelaar
 

Was ist angesagt? (20)

AnyMQ, Hippie, and the real-time web
AnyMQ, Hippie, and the real-time webAnyMQ, Hippie, and the real-time web
AnyMQ, Hippie, and the real-time web
 
Cool like a Frontend Developer: Grunt, RequireJS, Bower and other Tools
Cool like a Frontend Developer: Grunt, RequireJS, Bower and other ToolsCool like a Frontend Developer: Grunt, RequireJS, Bower and other Tools
Cool like a Frontend Developer: Grunt, RequireJS, Bower and other Tools
 
Selenium sandwich-3: Being where you aren't.
Selenium sandwich-3: Being where you aren't.Selenium sandwich-3: Being where you aren't.
Selenium sandwich-3: Being where you aren't.
 
Node.js Express
Node.js  ExpressNode.js  Express
Node.js Express
 
AnsibleFest 2014 - Role Tips and Tricks
AnsibleFest 2014 - Role Tips and TricksAnsibleFest 2014 - Role Tips and Tricks
AnsibleFest 2014 - Role Tips and Tricks
 
Building Web Apps with Express
Building Web Apps with ExpressBuilding Web Apps with Express
Building Web Apps with Express
 
Tatsumaki
TatsumakiTatsumaki
Tatsumaki
 
Speed up web APIs with Expressive and Swoole (PHP Day 2018)
Speed up web APIs with Expressive and Swoole (PHP Day 2018) Speed up web APIs with Expressive and Swoole (PHP Day 2018)
Speed up web APIs with Expressive and Swoole (PHP Day 2018)
 
A reviravolta do desenvolvimento web
A reviravolta do desenvolvimento webA reviravolta do desenvolvimento web
A reviravolta do desenvolvimento web
 
Composer
ComposerComposer
Composer
 
Nodejs first class
Nodejs first classNodejs first class
Nodejs first class
 
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQueryRemedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
 
V2 and beyond
V2 and beyondV2 and beyond
V2 and beyond
 
Plack - LPW 2009
Plack - LPW 2009Plack - LPW 2009
Plack - LPW 2009
 
Using Sinatra to Build REST APIs in Ruby
Using Sinatra to Build REST APIs in RubyUsing Sinatra to Build REST APIs in Ruby
Using Sinatra to Build REST APIs in Ruby
 
Building Cloud Castles
Building Cloud CastlesBuilding Cloud Castles
Building Cloud Castles
 
Wykorzystanie form request przy implementacji API w Laravelu
Wykorzystanie form request przy implementacji API w LaraveluWykorzystanie form request przy implementacji API w Laravelu
Wykorzystanie form request przy implementacji API w Laravelu
 
Phinx talk
Phinx talkPhinx talk
Phinx talk
 
Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2
 
Puppet and the HashiStack
Puppet and the HashiStackPuppet and the HashiStack
Puppet and the HashiStack
 

Andere mochten auch

Domain Driven Design
Domain Driven DesignDomain Driven Design
Domain Driven DesignÜrgo Ringo
 
Domain Driven Design Demonstrated
Domain Driven Design Demonstrated Domain Driven Design Demonstrated
Domain Driven Design Demonstrated Alan Christensen
 
Application Architecture by Lars-Erik Kindblad, Capgemini
Application Architecture by Lars-Erik Kindblad, CapgeminiApplication Architecture by Lars-Erik Kindblad, Capgemini
Application Architecture by Lars-Erik Kindblad, CapgeminiLars-Erik Kindblad
 
Application Architecture April 2014
Application Architecture April 2014Application Architecture April 2014
Application Architecture April 2014Lars-Erik Kindblad
 
Middleware PHP - A simple micro-framework
Middleware PHP - A simple micro-frameworkMiddleware PHP - A simple micro-framework
Middleware PHP - A simple micro-frameworkCorley S.r.l.
 
Rich Model And Layered Architecture in SF2 Application
Rich Model And Layered Architecture in SF2 ApplicationRich Model And Layered Architecture in SF2 Application
Rich Model And Layered Architecture in SF2 ApplicationKirill Chebunin
 
Hexagonal architecture - message-oriented software design (PHP Benelux 2016)
Hexagonal architecture - message-oriented software design (PHP Benelux 2016)Hexagonal architecture - message-oriented software design (PHP Benelux 2016)
Hexagonal architecture - message-oriented software design (PHP Benelux 2016)Matthias Noback
 
Models and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and HobgoblinsModels and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and HobgoblinsRoss Tuck
 
CQRS на практике. В поиске точки масштабирования и новых метафор
CQRS на практике. В поиске точки масштабирования и новых метафорCQRS на практике. В поиске точки масштабирования и новых метафор
CQRS на практике. В поиске точки масштабирования и новых метафорAlexander Byndyu
 
Lecture application layer
Lecture application layerLecture application layer
Lecture application layerHasam Panezai
 
Implementing DDD Concepts in PHP
Implementing DDD Concepts in PHPImplementing DDD Concepts in PHP
Implementing DDD Concepts in PHPSteve Rhoades
 
Clean architecture with ddd layering in php
Clean architecture with ddd layering in phpClean architecture with ddd layering in php
Clean architecture with ddd layering in phpLeonardo Proietti
 
Network Layer,Computer Networks
Network Layer,Computer NetworksNetwork Layer,Computer Networks
Network Layer,Computer Networksguesta81d4b
 

Andere mochten auch (15)

CQRS
CQRSCQRS
CQRS
 
Domain Driven Design
Domain Driven DesignDomain Driven Design
Domain Driven Design
 
Domain Driven Design Demonstrated
Domain Driven Design Demonstrated Domain Driven Design Demonstrated
Domain Driven Design Demonstrated
 
Application Architecture by Lars-Erik Kindblad, Capgemini
Application Architecture by Lars-Erik Kindblad, CapgeminiApplication Architecture by Lars-Erik Kindblad, Capgemini
Application Architecture by Lars-Erik Kindblad, Capgemini
 
The Fluent Interface Pattern
The Fluent Interface PatternThe Fluent Interface Pattern
The Fluent Interface Pattern
 
Application Architecture April 2014
Application Architecture April 2014Application Architecture April 2014
Application Architecture April 2014
 
Middleware PHP - A simple micro-framework
Middleware PHP - A simple micro-frameworkMiddleware PHP - A simple micro-framework
Middleware PHP - A simple micro-framework
 
Rich Model And Layered Architecture in SF2 Application
Rich Model And Layered Architecture in SF2 ApplicationRich Model And Layered Architecture in SF2 Application
Rich Model And Layered Architecture in SF2 Application
 
Hexagonal architecture - message-oriented software design (PHP Benelux 2016)
Hexagonal architecture - message-oriented software design (PHP Benelux 2016)Hexagonal architecture - message-oriented software design (PHP Benelux 2016)
Hexagonal architecture - message-oriented software design (PHP Benelux 2016)
 
Models and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and HobgoblinsModels and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and Hobgoblins
 
CQRS на практике. В поиске точки масштабирования и новых метафор
CQRS на практике. В поиске точки масштабирования и новых метафорCQRS на практике. В поиске точки масштабирования и новых метафор
CQRS на практике. В поиске точки масштабирования и новых метафор
 
Lecture application layer
Lecture application layerLecture application layer
Lecture application layer
 
Implementing DDD Concepts in PHP
Implementing DDD Concepts in PHPImplementing DDD Concepts in PHP
Implementing DDD Concepts in PHP
 
Clean architecture with ddd layering in php
Clean architecture with ddd layering in phpClean architecture with ddd layering in php
Clean architecture with ddd layering in php
 
Network Layer,Computer Networks
Network Layer,Computer NetworksNetwork Layer,Computer Networks
Network Layer,Computer Networks
 

Ähnlich wie Application Layer in PHP

関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐいHisateru Tanaka
 
What's New In Laravel 5
What's New In Laravel 5What's New In Laravel 5
What's New In Laravel 5Darren Craig
 
And the Greatest of These Is ... Rack Support
And the Greatest of These Is ... Rack SupportAnd the Greatest of These Is ... Rack Support
And the Greatest of These Is ... Rack SupportBen Scofield
 
symfony on action - WebTech 207
symfony on action - WebTech 207symfony on action - WebTech 207
symfony on action - WebTech 207patter
 
Crafting Quality PHP Applications (Bucharest Tech Week 2017)
Crafting Quality PHP Applications (Bucharest Tech Week 2017)Crafting Quality PHP Applications (Bucharest Tech Week 2017)
Crafting Quality PHP Applications (Bucharest Tech Week 2017)James Titcumb
 
Phpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsPhpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsMichael Peacock
 
Spring Web Services: SOAP vs. REST
Spring Web Services: SOAP vs. RESTSpring Web Services: SOAP vs. REST
Spring Web Services: SOAP vs. RESTSam Brannen
 
Building Lithium Apps
Building Lithium AppsBuilding Lithium Apps
Building Lithium AppsNate Abele
 
Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2Hugo Hamon
 
Crafting Quality PHP Applications (PHP Benelux 2018)
Crafting Quality PHP Applications (PHP Benelux 2018)Crafting Quality PHP Applications (PHP Benelux 2018)
Crafting Quality PHP Applications (PHP Benelux 2018)James Titcumb
 
Speed up your developments with Symfony2
Speed up your developments with Symfony2Speed up your developments with Symfony2
Speed up your developments with Symfony2Hugo Hamon
 
Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8Michelangelo van Dam
 
Crafting Quality PHP Applications (ConFoo YVR 2017)
Crafting Quality PHP Applications (ConFoo YVR 2017)Crafting Quality PHP Applications (ConFoo YVR 2017)
Crafting Quality PHP Applications (ConFoo YVR 2017)James Titcumb
 
Primefaces Confess 2012
Primefaces Confess 2012Primefaces Confess 2012
Primefaces Confess 2012cagataycivici
 
Crafting Quality PHP Applications (PHPkonf 2018)
Crafting Quality PHP Applications (PHPkonf 2018)Crafting Quality PHP Applications (PHPkonf 2018)
Crafting Quality PHP Applications (PHPkonf 2018)James Titcumb
 
Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017)
Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017)Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017)
Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017)James Titcumb
 
Primefaces Nextgen Lju
Primefaces Nextgen LjuPrimefaces Nextgen Lju
Primefaces Nextgen LjuSkills Matter
 
Primefaces Nextgen Lju
Primefaces Nextgen LjuPrimefaces Nextgen Lju
Primefaces Nextgen LjuSkills Matter
 

Ähnlich wie Application Layer in PHP (20)

関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい
 
What's New In Laravel 5
What's New In Laravel 5What's New In Laravel 5
What's New In Laravel 5
 
And the Greatest of These Is ... Rack Support
And the Greatest of These Is ... Rack SupportAnd the Greatest of These Is ... Rack Support
And the Greatest of These Is ... Rack Support
 
symfony on action - WebTech 207
symfony on action - WebTech 207symfony on action - WebTech 207
symfony on action - WebTech 207
 
Crafting Quality PHP Applications (Bucharest Tech Week 2017)
Crafting Quality PHP Applications (Bucharest Tech Week 2017)Crafting Quality PHP Applications (Bucharest Tech Week 2017)
Crafting Quality PHP Applications (Bucharest Tech Week 2017)
 
Phpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsPhpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friends
 
Spring Web Services: SOAP vs. REST
Spring Web Services: SOAP vs. RESTSpring Web Services: SOAP vs. REST
Spring Web Services: SOAP vs. REST
 
Building Lithium Apps
Building Lithium AppsBuilding Lithium Apps
Building Lithium Apps
 
Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2
 
Event Sourcing with php
Event Sourcing with phpEvent Sourcing with php
Event Sourcing with php
 
Crafting Quality PHP Applications (PHP Benelux 2018)
Crafting Quality PHP Applications (PHP Benelux 2018)Crafting Quality PHP Applications (PHP Benelux 2018)
Crafting Quality PHP Applications (PHP Benelux 2018)
 
Speed up your developments with Symfony2
Speed up your developments with Symfony2Speed up your developments with Symfony2
Speed up your developments with Symfony2
 
Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8
 
Crafting Quality PHP Applications (ConFoo YVR 2017)
Crafting Quality PHP Applications (ConFoo YVR 2017)Crafting Quality PHP Applications (ConFoo YVR 2017)
Crafting Quality PHP Applications (ConFoo YVR 2017)
 
Primefaces Confess 2012
Primefaces Confess 2012Primefaces Confess 2012
Primefaces Confess 2012
 
Crafting Quality PHP Applications (PHPkonf 2018)
Crafting Quality PHP Applications (PHPkonf 2018)Crafting Quality PHP Applications (PHPkonf 2018)
Crafting Quality PHP Applications (PHPkonf 2018)
 
Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017)
Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017)Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017)
Kicking off with Zend Expressive and Doctrine ORM (PHP UK 2017)
 
实战Ecos
实战Ecos实战Ecos
实战Ecos
 
Primefaces Nextgen Lju
Primefaces Nextgen LjuPrimefaces Nextgen Lju
Primefaces Nextgen Lju
 
Primefaces Nextgen Lju
Primefaces Nextgen LjuPrimefaces Nextgen Lju
Primefaces Nextgen Lju
 

Mehr von Per Bernhardt

Event Carried State Transfer @ LeanIX
Event Carried State Transfer @ LeanIXEvent Carried State Transfer @ LeanIX
Event Carried State Transfer @ LeanIXPer Bernhardt
 
Communication in a Microservice Architecture (Ljubljana Backend Meetup 2021)
Communication in a Microservice Architecture (Ljubljana Backend Meetup 2021)Communication in a Microservice Architecture (Ljubljana Backend Meetup 2021)
Communication in a Microservice Architecture (Ljubljana Backend Meetup 2021)Per Bernhardt
 
Microservice Test Strategy (@Bonn Code Meetup)
Microservice Test Strategy (@Bonn Code Meetup)Microservice Test Strategy (@Bonn Code Meetup)
Microservice Test Strategy (@Bonn Code Meetup)Per Bernhardt
 
Communication in a Microservice Architecture
Communication in a Microservice ArchitectureCommunication in a Microservice Architecture
Communication in a Microservice ArchitecturePer Bernhardt
 
Magazin-Relaunch bei Chefkoch
Magazin-Relaunch bei ChefkochMagazin-Relaunch bei Chefkoch
Magazin-Relaunch bei ChefkochPer Bernhardt
 
Contract Tests mit Pact
Contract Tests mit PactContract Tests mit Pact
Contract Tests mit PactPer Bernhardt
 
Chefkoch goes Drupal8
Chefkoch goes Drupal8Chefkoch goes Drupal8
Chefkoch goes Drupal8Per Bernhardt
 
Umzug eines Hochlast-Dienstes
Umzug eines Hochlast-DienstesUmzug eines Hochlast-Dienstes
Umzug eines Hochlast-DienstesPer Bernhardt
 
kubernetes @ chefkoch.de - Kubernetes Meetup Cologne
kubernetes @ chefkoch.de - Kubernetes Meetup Colognekubernetes @ chefkoch.de - Kubernetes Meetup Cologne
kubernetes @ chefkoch.de - Kubernetes Meetup ColognePer Bernhardt
 
Continiuous Integration and Delivery with Bamboo
Continiuous Integration and Delivery with BambooContiniuous Integration and Delivery with Bamboo
Continiuous Integration and Delivery with BambooPer Bernhardt
 
Anwendungsintegration mit Edge Side Includes
Anwendungsintegration mit Edge Side IncludesAnwendungsintegration mit Edge Side Includes
Anwendungsintegration mit Edge Side IncludesPer Bernhardt
 

Mehr von Per Bernhardt (12)

Die Rolle des CTO
Die Rolle des CTODie Rolle des CTO
Die Rolle des CTO
 
Event Carried State Transfer @ LeanIX
Event Carried State Transfer @ LeanIXEvent Carried State Transfer @ LeanIX
Event Carried State Transfer @ LeanIX
 
Communication in a Microservice Architecture (Ljubljana Backend Meetup 2021)
Communication in a Microservice Architecture (Ljubljana Backend Meetup 2021)Communication in a Microservice Architecture (Ljubljana Backend Meetup 2021)
Communication in a Microservice Architecture (Ljubljana Backend Meetup 2021)
 
Microservice Test Strategy (@Bonn Code Meetup)
Microservice Test Strategy (@Bonn Code Meetup)Microservice Test Strategy (@Bonn Code Meetup)
Microservice Test Strategy (@Bonn Code Meetup)
 
Communication in a Microservice Architecture
Communication in a Microservice ArchitectureCommunication in a Microservice Architecture
Communication in a Microservice Architecture
 
Magazin-Relaunch bei Chefkoch
Magazin-Relaunch bei ChefkochMagazin-Relaunch bei Chefkoch
Magazin-Relaunch bei Chefkoch
 
Contract Tests mit Pact
Contract Tests mit PactContract Tests mit Pact
Contract Tests mit Pact
 
Chefkoch goes Drupal8
Chefkoch goes Drupal8Chefkoch goes Drupal8
Chefkoch goes Drupal8
 
Umzug eines Hochlast-Dienstes
Umzug eines Hochlast-DienstesUmzug eines Hochlast-Dienstes
Umzug eines Hochlast-Dienstes
 
kubernetes @ chefkoch.de - Kubernetes Meetup Cologne
kubernetes @ chefkoch.de - Kubernetes Meetup Colognekubernetes @ chefkoch.de - Kubernetes Meetup Cologne
kubernetes @ chefkoch.de - Kubernetes Meetup Cologne
 
Continiuous Integration and Delivery with Bamboo
Continiuous Integration and Delivery with BambooContiniuous Integration and Delivery with Bamboo
Continiuous Integration and Delivery with Bamboo
 
Anwendungsintegration mit Edge Side Includes
Anwendungsintegration mit Edge Side IncludesAnwendungsintegration mit Edge Side Includes
Anwendungsintegration mit Edge Side Includes
 

Kürzlich hochgeladen

FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhisoniya singh
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
Google AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGGoogle AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGSujit Pal
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Alan Dix
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 

Kürzlich hochgeladen (20)

FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Google AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGGoogle AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAG
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 

Application Layer in PHP

  • 1. Application Layer ein Vortrag von Per Bernhardt
  • 2. Agenda • Disclaimer / Credits • Ein kleines bisschen Theorie • Ein echtes Beispiel: Chefkoch API
  • 3.
  • 4. Credit goes to… • http://martinfowler.com/ • http://domainlanguage.com/ • http://alistair.cockburn.us/ • http://www.whitewashing.de/ • und viele andere..
  • 7. Application Layer Presentation Layer Infrastructure Layer Domain Layer - Controller - Template / HTML - Session / HTTP
  • 8. Application Layer Presentation Layer Infrastructure Layer Domain Layer - Controller - Template / HTML - Session / HTTP - Fasade - Transaktionen - Sicherheit / Zugriffsschutz - Integration / Orchestrierung
  • 9. Application Layer Presentation Layer Infrastructure Layer Domain Layer - Controller - Template / HTML - Session / HTTP - Fasade - Transaktionen - Sicherheit / Zugriffsschutz - Integration / Orchestrierung - Daten - Geschäftslogik
  • 10. Application Layer Presentation Layer Infrastructure Layer Domain Layer - Controller - Template / HTML - Session / HTTP - Fasade - Transaktionen - Sicherheit / Zugriffsschutz - Integration / Orchestrierung - Daten - Geschäftslogik - Datenbank - Mailserver - Logger - …
  • 11. Application Layer Presentation Layer Infrastructure Layer Domain Layer - Controller - Template / HTML - Session / HTTP - Fasade - Transaktionen - Sicherheit / Zugriffsschutz - Integration / Orchestrierung - Daten - Geschäftslogik - Datenbank - Mailserver - Logger - …
  • 12. Application Layer Presentation Layer Infrastructure Layer Domain Layer - Controller - Template / HTML - Session / HTTP - Fasade - Transaktionen - Sicherheit / Zugriffsschutz - Integration / Orchestrierung - Daten - Geschäftslogik - Datenbank - Mailserver - Logger - …
  • 14.
  • 16. <?php ! namespace ChefkochBundleApiBundleController; ! use SymfonyBundleFrameworkBundleControllerController; use ChefkochDomainModelCookbookCookbookId use SensioBundleFrameworkExtraBundleConfigurationParamConverter; use ChefkochBundleApiBundleAnnotationApiSerialize; use ChefkochApplicationCookbookRequest; use ChefkochApplicationCookbookCommand; use PixelhouseApplicationEventDispatchingService; use PixelhouseApplicationResponse; ! class CookbookController extends Controller { ! ... ! /** * @ParamConverter("category", options={"deserialize"=true}) * @ApiSerialize * @return Response */ public function saveCategoryAction(CookbookId $cookbookId, RequestCategoryRequest $category) { return $this->getCookbookService()->execute( new CommandSaveCategoryCommand($cookbookId, $category) ); } ! ... ! /** * @return DispatchingService */ private function getCookbookService() { return $this->get('chefkoch_api.application.cookbook_service'); } }
  • 17. <?php ! namespace ChefkochApplicationCookbookCommand; ! use ChefkochApplicationCookbookRequestCategoryRequest; use ChefkochApplicationCookbookSecurityCookbookWriteAccessRequired; use ChefkochDomainModelCookbookCookbookId; use PixelhouseApplicationCommand; ! class SaveCategoryCommand implements Command, CookbookWriteAccessRequired { ! /** @var CookbookId */ private $cookbookId; ! /** @var CategoryRequest */ private $categoryRequest; ! public function __construct(CookbookId $cookbookId, CategoryRequest $categoryRequest) { $this->cookbookId = $cookbookId; $this->categoryRequest = $categoryRequest; } ! public function getCookbookId() { return $this->cookbookId; } ! public function getCategoryRequest() { return $this->categoryRequest; } }
  • 18. <?php ! namespace PixelhouseApplicationEvent; ! use PixelhouseApplicationCommand; use PixelhouseApplicationUseCase; use PixelhouseEventDispatcherEventDispatcher; ! class DispatchingService { ! /** @var EventDispatcher */ private $eventDispatcher; ! /** @var UseCase[] */ private $useCases = array(); ! public function __construct(EventDispatcher $eventDispatcher) { $this->eventDispatcher = $eventDispatcher; } ! public function registerCommand($commandClass, UseCase $useCase) { $this->useCases[$commandClass] = $useCase; } ! public function execute(Command $command) { ... } }
  • 19. <?php ! namespace PixelhouseApplicationEvent; ! class Events { const PRE_COMMAND = 'application.pre_command'; const POST_COMMAND = 'application.post_command'; const EXCEPTION = 'application.exception'; }
  • 20. <?php ! namespace PixelhouseApplicationEvent; ! use PixelhouseApplicationCommand; ! class DispatchingService { ! ... ! public function execute(Command $command) { try { $this->eventDispatcher->dispatch( Events::PRE_COMMAND, new CommandEvent($command) ); $response = $this->useCases[get_class($command)]->run($command); $this->eventDispatcher->dispatch( Events::POST_COMMAND, new PostCommandEvent($command, $response) ); ! return $response; } catch (Exception $exception) { $event = new CommandExceptionEvent($command, $exception); $this->eventDispatcher->dispatch( Events::EXCEPTION, $event ); if ($response = $event->getResponse()) { return $response; } else { throw $exception; } } } }
  • 21. <?php ! namespace ChefkochInfrastructureApplication; ! use PixelhouseApplicationEvent; use PixelhouseEventDispatcherSubscriber; use DoctrineORMEntityManager; ! class DoctrineTransactionListener implements Subscriber { ! /** @var EntityManager */ private $entityManager; ! public function __construct(EntityManager $entityManager) { $this->entityManager = $entityManager; } ! public function preCommand(EventCommandEvent $event) { $this->entityManager->getConnection()->beginTransaction(); } ! public function postCommand(EventPostCommandEvent $event) { $this->entityManager->flush(); $this->entityManager->getConnection()->commit(); } ! public function onException(EventCommandExceptionEvent $event) { $this->entityManager->close(); if ($this->entityManager->getConnection()->isTransactionActive()) { $this->entityManager->getConnection()->rollBack(); } } }
  • 22. <?php ! namespace PixelhouseApplicationSecurity; ! use PixelhouseApplicationEvent; use PixelhouseEventDispatcherSubscriber; ! class SecurityListener implements Subscriber { ! /** @var Context */ private $context; ! /** @var Policy[] */ private $policies = array(); ! public function __construct(Context $context) { $this->context = $context; } ! public function addPolicy(Policy $policy) { $this->policies[] = $policy; } ! /** * throws Exception */ public function preCommand(EventCommandEvent $event) { foreach ($this->policies as $policy) { $policy->check($this->securityContext, $event->getCommand()); } } }
  • 23. <?php ! namespace ChefkochApplicationCookbookSecurity; ! use ChefkochDomainModelCookbookCookbookRepository; use ChefkochUserDomainModelUserRepository; use PixelhouseApplicationCommand; use PixelhouseApplicationSecurityAccessDeniedException; use PixelhouseApplicationSecurityContext; use PixelhouseApplicationSecurityPolicy; ! class CookbookAccessPolicy implements Policy { ! /** @var CookbookRepository */ private $cookbookRepository; ! /** @var UserRepository */ private $userRepository; ! public function __construct(CookbookRepository $cbRepo, UserRepository $uRepo) { $this->cookbookRepository = $cbRepo; $this->userRepository = $uRepo; } ! public function check(Context $context, Command $command) { if ($command instanceof CookbookWriteAccessRequired) { $cookbook = $this->cookbookRepository->findOneById($command->getCookbookId()); $user = $this->userRepository->findOneById($context->getUserId()); ! // Zugriff prüfen ... ! throw new AccessDeniedException(); } } }
  • 24. <?xml version="1.0" ?> <container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services ..."> <services> ... ! <service id="chefkoch_api.application.use_case.cookbook_save_category" class="ChefkochApplicationCookbookUseCaseSaveCategory"> <argument type="service" id="chefkoch_api.infrastructure.cookbook_category_repository" /> <argument type="service" id="chefkoch_api.infrastructure.user_repository" /> <argument type="service" id="chefkoch_api.application.security_context" /> <tag name="chefkoch_api.application.use_case" commandClass="ChefkochApplicationCookbookCommandSaveCategoryCommand" applicationService="chefkoch_api.application.cookbook_service" /> </service> ! ... </services> </container>
  • 25. <?php ! namespace ChefkochApplicationCookbookUseCase; ! use ChefkochApplicationCookbookCommandSaveCategoryCommand; use PixelhouseApplicationSecurityContext; use PixelhouseApplicationUseCase; use ChefkochDomainModelCookbookCategoryRepository; use ChefkochUserDomainModelUserRepository; ! class SaveCategory implements UseCase { ! /** @var CategoryRepository */ private $categoryRepository; ! /** @var UserRepository */ private $userRepository; ! /** @var Context */ private $context; ! public function __construct(CategoryRepository $cRepo, UserRepository $uRepo, Context $context) { $this->categoryRepository = $cRepo; $this->userRepository = $uRepo; $this->context = $context; } ! public function run(SaveCategoryCommand $command) { ... } }
  • 26. <?php ! namespace ChefkochApplicationCookbookUseCase; ! use PixelhouseApplicationUseCase; use ChefkochApplicationCookbookCommandSaveCategoryCommand; use ChefkochDomainModelCookbookCategory; use ChefkochApplicationCookbookNotificationCategorySavedSuccess; use ChefkochApplicationCookbookResponseCategoryResponse; use PixelhouseApplicationResponse; ! class SaveCategory implements UseCase { ... ! public function run(SaveCategoryCommand $command) { $user = $this->userRepository->findOneById($this->context->getUserId()); ! $category = new Category( $command->getCookbookId(), $user->getId(), $command->getCategoryRequest()->getName(), $command->getCategoryRequest()->getDescriptionText() ); ! $this->categoryRepository->add($category); ! $categoryResponse = new CategoryResponse($category, $user); ! $response = new Response(); $response->getNotification()->addMessage(new CategorySavedSuccess($categoryResponse)); ! return $response; } }
  • 28.
  • 29.
  • 30.
  • 32. Bilder • Warning: https://www.flickr.com/photos/gerardstolk/ 6538330609 • Show Time: https://www.flickr.com/photos/ florida_photo_guy/5212663826 • Question Marks: https://www.flickr.com/photos/ loneblackrider/315302588 • Thank You: https://www.flickr.com/photos/wwworks/ 4759535950