SlideShare ist ein Scribd-Unternehmen logo
1 von 54
Downloaden Sie, um offline zu lesen
CODEMEAHR!
HI,IAMARNAUD!
ANEMICMODELVERSUSMODELRICH
PLAYGROUND
Business: Human resources management
Technical: Symfony / Doctrine ORM
WHATDOWEUSUALLYDO?CRUD!
Create Read Update Delete
WESTARTWITHCREATINGANEMICMODEL
namespace AlDomain;
final class Employee
{
/** @var Uuid */
private $id;
/** @var string */
private $name;
/** @var string */
private $position;
/** @var DateTimeInterface */
private $createdAt;
/** @var DateTimeInterface */
private $deletedAt;
// Getter and Setter
}
THENAFORMANDACONTROLLER
namespace AlPresenterForm;
final class EmployeeType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('name');
$builder->add('position');
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => Employee::class,
));
}
}
namespace AlPresenterController;
class EmployeeController extends Controller
{
public function indexAction(Request $request)
{
}
public function showAction(Request $request)
{
}
public function createAction(Request $request)
{
}
public function updateAction(Request $request)
{
}
public function deleteAction(Request $request)
{
}
}
namespace AlPresenterController;
class EmployeeController extends Controller
{
public function createAction(Request $request)
{
$form = $this->createForm(EmployeeType::class, new Employee());
$form->handleRequest($request);
// First, data are mapped to the model and it is validated thereafter.
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->get('doctrine.orm.entity_manager');
$em->persist($form->getData());
$em->flush();
return $this->redirectToRoute('employee_list');
}
return $this->render('employee/hire.html.twig', [
'form' => $form->createView()
]);
}
}
LET'SREFACTOROURANEMICMODEL
HOWDOESESTELLETALKABOUTHER
WORK?
namespace AlDomain;
final class Employee implements EmployeeInterface
{
public function hire(Uuid $identifier, string $name, string $forPosition)
{
}
public function promote(string $toNewPosition)
{
}
public function fire()
{
}
public function retire()
{
}
}
namespace AlDomain;
final class Employee implements EmployeeInterface
{
/** @var Uuid */
private $id;
/** @var string */
private $name;
/** @var string */
private $position;
/** @var DateTimeInterface */
private $hiredAt;
/** @var DateTimeInterface */
private $firedAt = null;
/** @var DateTimeInterface */
private $retiredAt = null;
}
namespace AlDomain;
final class Employee implements EmployeeInterface
{
private function __construct(Uuid $identifier, string $name, string $position)
{
$this->id = $identifier;
$this->name = $name;
$this->position = $position;
$this->hireAt = new DateTime();
}
public static function hire(Uuid $identifier, string $name, string $forPosition)
{
return new self($identifier, $name, $forPosition, $hiredAt);
}
public function promote(string $toNewPosition)
{
$this->position = $toNewPosition;
}
public function fire()
{
$this->firedAt = new DateTime();
}
public function retire()
{
$this->retiredAt = new DateTime();
}
}
namespace AlDomain;
final class Employee implements EmployeeInterface
{
private function __construct(Uuid $identifier, string $name, string $position)
{
if ($hiredAt < new DateTime('2013-01-01')) {
throw new OutOfRangeException(
'The company did not exist before 2013-01-01'
);
}
$this->id = $identifier;
$this->name = $name;
$this->position = $position;
$this->hireAt = new DateTime();
}
public function retire()
{
if (null !== $this->fired) {
throw new Exception(
sprint('%s employee has been fired!', $this->name)
);
}
$this->retiredAt = new DateTime();
}
}
HOWCANWEUSEITINOURAPPLICATION?
FIRSTPROBLEM:HOWDOWEUSE
DOCTRINE?
We use them as query repositories
interface EmployeeRepository
{
public function findByNameAndPositionWithoutFiredPeople(
string $name,
string $position
);
}
WHATISAREPOSITORY?
«A repository behaves like a collection of unique entities
without taking care about the storage»
WHATDOESITLOOKLIKE?
namespace AlInfrastructure;
final class EmployeeRepository implements EmployeeRepositoryInterface
{
public function get(Uuid $identifier)
{
}
public function add(EmployeeInterface $employee)
{
}
public function remove(EmployeeInterface $employee)
{
}
}
namespace AlInfrastructure;
final class EmployeeRepository implements EmployeeRepositoryInterface
{
/** @var EntityManagerInterface */
private $entityManager;
public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}
}
namespace AlInfrastructure;
final class EmployeeRepository implements EmployeeRepositoryInterface
{
public function get(Uuid $identifier)
{
$employee = $this->entityManager->find(
Employee::class,
$identifier->toString()
);
if (null === $employee) {
throw new NonExistingEmployee($identifier->toString());
}
return $employee;
}
public function add(EmployeeInterface $employee)
{
$this->entityManager->persist($employee);
$this->entityManager->flush($employee);
}
public function remove(EmployeeInterface $employee)
{
$this->entityManager->remove($employee);
$this->entityManager->flush($employee);
}
}
ISITMANDATORYTOUSESETTER?NO!
Doctrine uses the re ection to map data
Doctrine does not instantiate objects (Ocramius/Instantiator)
SECONDPROBLEM:FORMCOMPONENT
PropertyAccessor is used to map data, it needs public properties or setter.
COMMANDTOTHERESCUE!
« A Command is an object that represents all the information
needed to call a method.»
LET’SCREATEACOMMAND
namespace AlApplication;
final class HireEmployeeCommand
{
/** @var string */
public $name = '';
/** @var string */
public $position = '';
}
LET’SUPDATEOURCONTROLLER
namespace AlPresenterController;
class EmployeeController extends Controller
{
public function hireAction(Request $request)
{
$form = $this->createForm(EmployeeType::class, new HireEmployeeCommand());
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$employeeCommand = $form->getData();
$employee = Employee::hire(
Uuid::uuid4(),
$employeeCommand->getName(),
$employeeCommand->getPosition()
);
$this->get('employee.repository')->add($employee);
return $this->redirectToRoute('employee_list');
}
return $this->render('employee/hire.html.twig', [
'form' => $form->createView()
]);
}
}
NOW,ESTELLEWANTSTOIMPORT
EMPLOYEES!
COMMANDBUSTOTHERESCUE
«A Command Bus accepts a Command object and delegates it
to a Command Handler.»
LET’SUPDATEOURCONTROLLER
Here, we are going to use simple-bus/message-bus
namespace AlPresenterController;
class EmployeeController extends Controller
{
public function hireAction(Request $request)
{
$form = $this->createForm(EmployeeType::class, new HireEmployeeCommand());
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$employeeCommand = $form->getData();
try {
$this->get('command_bus')->handle($employeeCommand);
} catch (Exception $e) {
$this->addFlash('error', 'An error occurs!');
}
return $this->redirectToRoute('employee_list');
}
return $this->render('employee/hire.html.twig', [
'form' => $form->createView()
]);
}
}
LET’SCREATEACOMMANDHANDLER
namespace AlApplicationHandler;
final class HireEmployeeHandler
{
/** @var EmployeeRepositoryInterface */
private $employeeRepository;
public function __construct(EmployeeRepositoryInterface $employeeRepository)
{
$this->employeeRepository = $employeeRepository;
}
public function handle(HireEmployee $command)
{
$employee = Employee::hire(
Uuid::uuid4(),
$command->getName(),
$command->getPosition()
);
$this->employeeRepository->add($employee);
}
}
ESTELLEWON'TUSEPHPMYADMINTOREAD
DATA!
DOOURMODELSNEEDGETTER?NOT
NECESSARILY!
DTO(DATATRANSFEROBJECT)TOTHE
RESCUE!
«A Data Transfer Object is an object that is used to
encapsulate data, and to send it from one subsystem of an
application to another.»
DOCTRINE(>=2.4):OPERATORNEW
namespace AlApplication;
final class EmployeeDTO
{
/** string */
private $id;
/** string */
private $name;
/** string */
private $position;
public function __construct(string $id, string $name, string $position)
{
$this->id = $id;
$this->name = $name;
$this->position = $position;
}
// Define an accessor for each property
}}
namespace AlInfrastructure;
final class EmployeeSearcher
{
private $entityManager;
public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}
public function findAll()
{
$queryBuilder = $this->entityManager->createQueryBuilder()
->from(Employee::class, 'e')
->select(
sprintf('NEW %s(e.id, e.name, e.position)', EmployeeDTO::class)
);
// NEW AlApplicationEmployeeDTO(e.id, e.name, e.position)
return $queryBuilder->getQuery()->getResult();
}
}
WECANSEARCHANDDISPLAYEMPLOYEE
DATA!
MISREADINGOFDOCTRINE/DDD/CQRS
Domain Driven Design
Command Query Responsibility Segregation
WHATISTHEBESTSOLUTION?
It depends on what you want!
THAT'STHEEND!
https://joind.in/talk/6c974
THANKYOU!QUESTIONS?
aRn0D _aRn0D
https://joind.in/talk/6c974

Weitere ähnliche Inhalte

Was ist angesagt?

Crafting beautiful software
Crafting beautiful softwareCrafting beautiful software
Crafting beautiful softwareJorn Oomen
 
Writing Sensible Code
Writing Sensible CodeWriting Sensible Code
Writing Sensible CodeAnis Ahmad
 
Pim Elshoff "Technically DDD"
Pim Elshoff "Technically DDD"Pim Elshoff "Technically DDD"
Pim Elshoff "Technically DDD"Fwdays
 
11. CodeIgniter vederea unei singure inregistrari
11. CodeIgniter vederea unei singure inregistrari11. CodeIgniter vederea unei singure inregistrari
11. CodeIgniter vederea unei singure inregistrariRazvan Raducanu, PhD
 
購物車程式架構簡介
購物車程式架構簡介購物車程式架構簡介
購物車程式架構簡介Jace Ju
 
R57shell
R57shellR57shell
R57shellady36
 
Hacking Your Way To Better Security - Dutch PHP Conference 2016
Hacking Your Way To Better Security - Dutch PHP Conference 2016Hacking Your Way To Better Security - Dutch PHP Conference 2016
Hacking Your Way To Better Security - Dutch PHP Conference 2016Colin O'Dell
 
50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 Minutes50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 MinutesAzim Kurt
 
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonfRafael Dohms
 
Object Calisthenics Applied to PHP
Object Calisthenics Applied to PHPObject Calisthenics Applied to PHP
Object Calisthenics Applied to PHPGuilherme Blanco
 
Doctrine fixtures
Doctrine fixturesDoctrine fixtures
Doctrine fixturesBill Chang
 
PhpUnit - The most unknown Parts
PhpUnit - The most unknown PartsPhpUnit - The most unknown Parts
PhpUnit - The most unknown PartsBastian Feder
 
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...Rafael Dohms
 
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.5Leonardo Proietti
 
The command dispatcher pattern
The command dispatcher patternThe command dispatcher pattern
The command dispatcher patternolvlvl
 
Be pragmatic, be SOLID (at Boiling Frogs, Wrocław)
Be pragmatic, be SOLID (at Boiling Frogs, Wrocław)Be pragmatic, be SOLID (at Boiling Frogs, Wrocław)
Be pragmatic, be SOLID (at Boiling Frogs, Wrocław)Krzysztof Menżyk
 

Was ist angesagt? (20)

Crafting beautiful software
Crafting beautiful softwareCrafting beautiful software
Crafting beautiful software
 
Writing Sensible Code
Writing Sensible CodeWriting Sensible Code
Writing Sensible Code
 
Pim Elshoff "Technically DDD"
Pim Elshoff "Technically DDD"Pim Elshoff "Technically DDD"
Pim Elshoff "Technically DDD"
 
11. CodeIgniter vederea unei singure inregistrari
11. CodeIgniter vederea unei singure inregistrari11. CodeIgniter vederea unei singure inregistrari
11. CodeIgniter vederea unei singure inregistrari
 
Min-Maxing Software Costs
Min-Maxing Software CostsMin-Maxing Software Costs
Min-Maxing Software Costs
 
購物車程式架構簡介
購物車程式架構簡介購物車程式架構簡介
購物車程式架構簡介
 
Mocking Demystified
Mocking DemystifiedMocking Demystified
Mocking Demystified
 
R57shell
R57shellR57shell
R57shell
 
Hacking Your Way To Better Security - Dutch PHP Conference 2016
Hacking Your Way To Better Security - Dutch PHP Conference 2016Hacking Your Way To Better Security - Dutch PHP Conference 2016
Hacking Your Way To Better Security - Dutch PHP Conference 2016
 
Taming Command Bus
Taming Command BusTaming Command Bus
Taming Command Bus
 
50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 Minutes50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 Minutes
 
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
 
Object Calisthenics Applied to PHP
Object Calisthenics Applied to PHPObject Calisthenics Applied to PHP
Object Calisthenics Applied to PHP
 
Doctrine fixtures
Doctrine fixturesDoctrine fixtures
Doctrine fixtures
 
PhpUnit - The most unknown Parts
PhpUnit - The most unknown PartsPhpUnit - The most unknown Parts
PhpUnit - The most unknown Parts
 
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...
 
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
 
画像Hacks
画像Hacks画像Hacks
画像Hacks
 
The command dispatcher pattern
The command dispatcher patternThe command dispatcher pattern
The command dispatcher pattern
 
Be pragmatic, be SOLID (at Boiling Frogs, Wrocław)
Be pragmatic, be SOLID (at Boiling Frogs, Wrocław)Be pragmatic, be SOLID (at Boiling Frogs, Wrocław)
Be pragmatic, be SOLID (at Boiling Frogs, Wrocław)
 

Ähnlich wie Code moi une RH! (PHP tour 2017)

Et si on en finissait avec CRUD ?
Et si on en finissait avec CRUD ?Et si on en finissait avec CRUD ?
Et si on en finissait avec CRUD ?Julien Vinber
 
How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony AppsKris Wallsmith
 
Tidy Up Your Code
Tidy Up Your CodeTidy Up Your Code
Tidy Up Your CodeAbbas Ali
 
WordPress REST API hacking
WordPress REST API hackingWordPress REST API hacking
WordPress REST API hackingJeroen van Dijk
 
Drupal csu-open atriumname
Drupal csu-open atriumnameDrupal csu-open atriumname
Drupal csu-open atriumnameEmanuele Quinto
 
Symfony CoP: Form component
Symfony CoP: Form componentSymfony CoP: Form component
Symfony CoP: Form componentSamuel ROZE
 
14. CodeIgniter adaugarea inregistrarilor
14. CodeIgniter adaugarea inregistrarilor14. CodeIgniter adaugarea inregistrarilor
14. CodeIgniter adaugarea inregistrarilorRazvan Raducanu, PhD
 
Command Bus To Awesome Town
Command Bus To Awesome TownCommand Bus To Awesome Town
Command Bus To Awesome TownRoss Tuck
 
laravel tricks in 50minutes
laravel tricks in 50minuteslaravel tricks in 50minutes
laravel tricks in 50minutesBarang CK
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For BeginnersJonathan Wage
 
PHPUnit elevato alla Symfony2
PHPUnit elevato alla Symfony2PHPUnit elevato alla Symfony2
PHPUnit elevato alla Symfony2eugenio pombi
 
Drupal Development (Part 2)
Drupal Development (Part 2)Drupal Development (Part 2)
Drupal Development (Part 2)Jeff Eaton
 
Advanced php testing in action
Advanced php testing in actionAdvanced php testing in action
Advanced php testing in actionJace Ju
 
Михаил Крайнюк - Form API + Drupal 8: Form and AJAX
Михаил Крайнюк - Form API + Drupal 8: Form and AJAXМихаил Крайнюк - Form API + Drupal 8: Form and AJAX
Михаил Крайнюк - Form API + Drupal 8: Form and AJAXDrupalSib
 
Drupal 8: Forms
Drupal 8: FormsDrupal 8: Forms
Drupal 8: Formsdrubb
 
Introduction to Zend Framework web services
Introduction to Zend Framework web servicesIntroduction to Zend Framework web services
Introduction to Zend Framework web servicesMichelangelo van Dam
 

Ähnlich wie Code moi une RH! (PHP tour 2017) (20)

Et si on en finissait avec CRUD ?
Et si on en finissait avec CRUD ?Et si on en finissait avec CRUD ?
Et si on en finissait avec CRUD ?
 
How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony Apps
 
Tidy Up Your Code
Tidy Up Your CodeTidy Up Your Code
Tidy Up Your Code
 
WordPress REST API hacking
WordPress REST API hackingWordPress REST API hacking
WordPress REST API hacking
 
Drupal csu-open atriumname
Drupal csu-open atriumnameDrupal csu-open atriumname
Drupal csu-open atriumname
 
Symfony CoP: Form component
Symfony CoP: Form componentSymfony CoP: Form component
Symfony CoP: Form component
 
14. CodeIgniter adaugarea inregistrarilor
14. CodeIgniter adaugarea inregistrarilor14. CodeIgniter adaugarea inregistrarilor
14. CodeIgniter adaugarea inregistrarilor
 
Command Bus To Awesome Town
Command Bus To Awesome TownCommand Bus To Awesome Town
Command Bus To Awesome Town
 
laravel tricks in 50minutes
laravel tricks in 50minuteslaravel tricks in 50minutes
laravel tricks in 50minutes
 
Unittests für Dummies
Unittests für DummiesUnittests für Dummies
Unittests für Dummies
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
 
PHPUnit elevato alla Symfony2
PHPUnit elevato alla Symfony2PHPUnit elevato alla Symfony2
PHPUnit elevato alla Symfony2
 
Drupal Development (Part 2)
Drupal Development (Part 2)Drupal Development (Part 2)
Drupal Development (Part 2)
 
Advanced php testing in action
Advanced php testing in actionAdvanced php testing in action
Advanced php testing in action
 
Михаил Крайнюк - Form API + Drupal 8: Form and AJAX
Михаил Крайнюк - Form API + Drupal 8: Form and AJAXМихаил Крайнюк - Form API + Drupal 8: Form and AJAX
Михаил Крайнюк - Form API + Drupal 8: Form and AJAX
 
Oops in php
Oops in phpOops in php
Oops in php
 
BEAR DI
BEAR DIBEAR DI
BEAR DI
 
Drupal 8: Forms
Drupal 8: FormsDrupal 8: Forms
Drupal 8: Forms
 
Migrare da symfony 1 a Symfony2
 Migrare da symfony 1 a Symfony2  Migrare da symfony 1 a Symfony2
Migrare da symfony 1 a Symfony2
 
Introduction to Zend Framework web services
Introduction to Zend Framework web servicesIntroduction to Zend Framework web services
Introduction to Zend Framework web services
 

Mehr von Arnaud Langlade

What is the difference between a good and a bad repository? (Forum PHP 2018)
What is the difference between a good and a bad repository? (Forum PHP 2018)What is the difference between a good and a bad repository? (Forum PHP 2018)
What is the difference between a good and a bad repository? (Forum PHP 2018)Arnaud Langlade
 
Php trollons mais trollons bien (Bdx.io 2015)
Php trollons mais trollons bien (Bdx.io 2015)Php trollons mais trollons bien (Bdx.io 2015)
Php trollons mais trollons bien (Bdx.io 2015)Arnaud Langlade
 
Programmation STUPID vs SOLID (PHP Meetup)
Programmation STUPID vs SOLID (PHP Meetup)Programmation STUPID vs SOLID (PHP Meetup)
Programmation STUPID vs SOLID (PHP Meetup)Arnaud Langlade
 
Développer avec le sylius resourcebundle (Symfony live Paris 2015)
Développer avec le sylius resourcebundle (Symfony live Paris 2015) Développer avec le sylius resourcebundle (Symfony live Paris 2015)
Développer avec le sylius resourcebundle (Symfony live Paris 2015) Arnaud Langlade
 

Mehr von Arnaud Langlade (6)

What is the difference between a good and a bad repository? (Forum PHP 2018)
What is the difference between a good and a bad repository? (Forum PHP 2018)What is the difference between a good and a bad repository? (Forum PHP 2018)
What is the difference between a good and a bad repository? (Forum PHP 2018)
 
Php trollons mais trollons bien (Bdx.io 2015)
Php trollons mais trollons bien (Bdx.io 2015)Php trollons mais trollons bien (Bdx.io 2015)
Php trollons mais trollons bien (Bdx.io 2015)
 
Programmation STUPID vs SOLID (PHP Meetup)
Programmation STUPID vs SOLID (PHP Meetup)Programmation STUPID vs SOLID (PHP Meetup)
Programmation STUPID vs SOLID (PHP Meetup)
 
Php spec en 5 minutes
Php spec en 5 minutesPhp spec en 5 minutes
Php spec en 5 minutes
 
Sylius en 5 minutes
Sylius en 5 minutesSylius en 5 minutes
Sylius en 5 minutes
 
Développer avec le sylius resourcebundle (Symfony live Paris 2015)
Développer avec le sylius resourcebundle (Symfony live Paris 2015) Développer avec le sylius resourcebundle (Symfony live Paris 2015)
Développer avec le sylius resourcebundle (Symfony live Paris 2015)
 

Kürzlich hochgeladen

TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...kellynguyen01
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️anilsa9823
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionSolGuruz
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxbodapatigopi8531
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Steffen Staab
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto González Trastoy
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfkalichargn70th171
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerThousandEyes
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsArshad QA
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...panagenda
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️Delhi Call girls
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...Health
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...MyIntelliSource, Inc.
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsAndolasoft Inc
 
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female serviceCALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female serviceanilsa9823
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsJhone kinadey
 

Kürzlich hochgeladen (20)

TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
 
Diamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with PrecisionDiamond Application Development Crafting Solutions with Precision
Diamond Application Development Crafting Solutions with Precision
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptx
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.js
 
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS LiveVip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
 
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female serviceCALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
CALL ON ➥8923113531 🔝Call Girls Badshah Nagar Lucknow best Female service
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 

Code moi une RH! (PHP tour 2017)

  • 3.
  • 5. PLAYGROUND Business: Human resources management Technical: Symfony / Doctrine ORM
  • 8. namespace AlDomain; final class Employee { /** @var Uuid */ private $id; /** @var string */ private $name; /** @var string */ private $position; /** @var DateTimeInterface */ private $createdAt; /** @var DateTimeInterface */ private $deletedAt; // Getter and Setter }
  • 10. namespace AlPresenterForm; final class EmployeeType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder->add('name'); $builder->add('position'); } public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults(array( 'data_class' => Employee::class, )); } }
  • 11. namespace AlPresenterController; class EmployeeController extends Controller { public function indexAction(Request $request) { } public function showAction(Request $request) { } public function createAction(Request $request) { } public function updateAction(Request $request) { } public function deleteAction(Request $request) { } }
  • 12. namespace AlPresenterController; class EmployeeController extends Controller { public function createAction(Request $request) { $form = $this->createForm(EmployeeType::class, new Employee()); $form->handleRequest($request); // First, data are mapped to the model and it is validated thereafter. if ($form->isSubmitted() && $form->isValid()) { $em = $this->get('doctrine.orm.entity_manager'); $em->persist($form->getData()); $em->flush(); return $this->redirectToRoute('employee_list'); } return $this->render('employee/hire.html.twig', [ 'form' => $form->createView() ]); } }
  • 13.
  • 16.
  • 17. namespace AlDomain; final class Employee implements EmployeeInterface { public function hire(Uuid $identifier, string $name, string $forPosition) { } public function promote(string $toNewPosition) { } public function fire() { } public function retire() { } }
  • 18. namespace AlDomain; final class Employee implements EmployeeInterface { /** @var Uuid */ private $id; /** @var string */ private $name; /** @var string */ private $position; /** @var DateTimeInterface */ private $hiredAt; /** @var DateTimeInterface */ private $firedAt = null; /** @var DateTimeInterface */ private $retiredAt = null; }
  • 19. namespace AlDomain; final class Employee implements EmployeeInterface { private function __construct(Uuid $identifier, string $name, string $position) { $this->id = $identifier; $this->name = $name; $this->position = $position; $this->hireAt = new DateTime(); } public static function hire(Uuid $identifier, string $name, string $forPosition) { return new self($identifier, $name, $forPosition, $hiredAt); } public function promote(string $toNewPosition) { $this->position = $toNewPosition; } public function fire() { $this->firedAt = new DateTime(); } public function retire() { $this->retiredAt = new DateTime(); } }
  • 20. namespace AlDomain; final class Employee implements EmployeeInterface { private function __construct(Uuid $identifier, string $name, string $position) { if ($hiredAt < new DateTime('2013-01-01')) { throw new OutOfRangeException( 'The company did not exist before 2013-01-01' ); } $this->id = $identifier; $this->name = $name; $this->position = $position; $this->hireAt = new DateTime(); } public function retire() { if (null !== $this->fired) { throw new Exception( sprint('%s employee has been fired!', $this->name) ); } $this->retiredAt = new DateTime(); } }
  • 22. FIRSTPROBLEM:HOWDOWEUSE DOCTRINE? We use them as query repositories interface EmployeeRepository { public function findByNameAndPositionWithoutFiredPeople( string $name, string $position ); }
  • 23. WHATISAREPOSITORY? «A repository behaves like a collection of unique entities without taking care about the storage»
  • 25. namespace AlInfrastructure; final class EmployeeRepository implements EmployeeRepositoryInterface { public function get(Uuid $identifier) { } public function add(EmployeeInterface $employee) { } public function remove(EmployeeInterface $employee) { } }
  • 26. namespace AlInfrastructure; final class EmployeeRepository implements EmployeeRepositoryInterface { /** @var EntityManagerInterface */ private $entityManager; public function __construct(EntityManagerInterface $entityManager) { $this->entityManager = $entityManager; } }
  • 27. namespace AlInfrastructure; final class EmployeeRepository implements EmployeeRepositoryInterface { public function get(Uuid $identifier) { $employee = $this->entityManager->find( Employee::class, $identifier->toString() ); if (null === $employee) { throw new NonExistingEmployee($identifier->toString()); } return $employee; } public function add(EmployeeInterface $employee) { $this->entityManager->persist($employee); $this->entityManager->flush($employee); } public function remove(EmployeeInterface $employee) { $this->entityManager->remove($employee); $this->entityManager->flush($employee); } }
  • 28. ISITMANDATORYTOUSESETTER?NO! Doctrine uses the re ection to map data Doctrine does not instantiate objects (Ocramius/Instantiator)
  • 29. SECONDPROBLEM:FORMCOMPONENT PropertyAccessor is used to map data, it needs public properties or setter.
  • 30. COMMANDTOTHERESCUE! « A Command is an object that represents all the information needed to call a method.»
  • 32. namespace AlApplication; final class HireEmployeeCommand { /** @var string */ public $name = ''; /** @var string */ public $position = ''; }
  • 34. namespace AlPresenterController; class EmployeeController extends Controller { public function hireAction(Request $request) { $form = $this->createForm(EmployeeType::class, new HireEmployeeCommand()); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { $employeeCommand = $form->getData(); $employee = Employee::hire( Uuid::uuid4(), $employeeCommand->getName(), $employeeCommand->getPosition() ); $this->get('employee.repository')->add($employee); return $this->redirectToRoute('employee_list'); } return $this->render('employee/hire.html.twig', [ 'form' => $form->createView() ]); } }
  • 35.
  • 37. COMMANDBUSTOTHERESCUE «A Command Bus accepts a Command object and delegates it to a Command Handler.»
  • 38. LET’SUPDATEOURCONTROLLER Here, we are going to use simple-bus/message-bus
  • 39. namespace AlPresenterController; class EmployeeController extends Controller { public function hireAction(Request $request) { $form = $this->createForm(EmployeeType::class, new HireEmployeeCommand()); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { $employeeCommand = $form->getData(); try { $this->get('command_bus')->handle($employeeCommand); } catch (Exception $e) { $this->addFlash('error', 'An error occurs!'); } return $this->redirectToRoute('employee_list'); } return $this->render('employee/hire.html.twig', [ 'form' => $form->createView() ]); } }
  • 41. namespace AlApplicationHandler; final class HireEmployeeHandler { /** @var EmployeeRepositoryInterface */ private $employeeRepository; public function __construct(EmployeeRepositoryInterface $employeeRepository) { $this->employeeRepository = $employeeRepository; } public function handle(HireEmployee $command) { $employee = Employee::hire( Uuid::uuid4(), $command->getName(), $command->getPosition() ); $this->employeeRepository->add($employee); } }
  • 42.
  • 45. DTO(DATATRANSFEROBJECT)TOTHE RESCUE! «A Data Transfer Object is an object that is used to encapsulate data, and to send it from one subsystem of an application to another.»
  • 47. namespace AlApplication; final class EmployeeDTO { /** string */ private $id; /** string */ private $name; /** string */ private $position; public function __construct(string $id, string $name, string $position) { $this->id = $id; $this->name = $name; $this->position = $position; } // Define an accessor for each property }}
  • 48. namespace AlInfrastructure; final class EmployeeSearcher { private $entityManager; public function __construct(EntityManagerInterface $entityManager) { $this->entityManager = $entityManager; } public function findAll() { $queryBuilder = $this->entityManager->createQueryBuilder() ->from(Employee::class, 'e') ->select( sprintf('NEW %s(e.id, e.name, e.position)', EmployeeDTO::class) ); // NEW AlApplicationEmployeeDTO(e.id, e.name, e.position) return $queryBuilder->getQuery()->getResult(); } }
  • 50.