実践 Action Domain Responder

実践 Action Domain Responder

PHPカンファレンス福岡2017で発表したスライド

17d4ef53b432ebf7c566fd6a11345570?s=128

yuuki takezawa

June 10, 2017
Tweet

Transcript

  1. 3.
  2. 7.

    final class UserController extends Controller { public function show($id) {

    return view('user.profile', ['user' => User::findOrFail($id)]); } public function create(Request $request) { Validate::make(…); $this->fluent->append($request->all()); return view('user.create'); } }
  3. 9.

    final class UserReadAction { public function __construct(Responder $responder) { $this->responder

    = $responder; } public function __invoke($id) { return $this->responder->emit( ['user' => User::findOrFail($id)] ); } }
  4. 11.

    $task = new Task; echo $task->process(function () { return 1;

    }); class Invoke { public function __invoke() { return 2; } } echo $task->process(new Invoke); echo $task->process(new class { public function __invoke() { return 3; } });
  5. 12.

    final class Runner { protected $invoker; public function __construct(array $invoker

    = []) { $this->invoker = $invoker; } public function __invoke($request, $response) { $invoke = array_shift($this->invoker); if (is_null($invoke)) { return function ($request, $response) { return $response; }; } return $invoke($request, $response, $this); } }
  6. 13.

    Model, Domain • ϏδωεϩδοΫΛղܾ͢Δ૚ • υϝΠϯۦಈͷύλʔϯͰ࣮૷͢Δɺ
 ͱ͍͏ҙຯͰ͸ͳ͍ • ඞཁʹԠͯ͡ঢ়ଶ΍ӬଓԽΛ •

    ΤϯςΟςΟͳͲ͸ResponderͰར༻͢Δ͜ͱ͕͋ Δ
 (renderͳͲ) • ORMͰදݱ͢Δ΋ͷ͕υϝΠϯͰ͋Ε͹ͦΕͰ΋Մ
  7. 18.
  8. 23.
  9. 24.
  10. 25.

    $repository = new Repository(new Database()); $entity = new Entity(1, ‘testing’);

    $repository->add($entity); $repository->save(); // return Entity[] $repository->findAll();
  11. 27.
  12. 30.

    ϏδωεϩδοΫ࠶ߟ • ࣮૷ύλʔϯ͔Βߟ͑ΔͰ͸ͳ͘ɺ
 ΞϓϦέʔγϣϯΛטΈࡅ͘͜ͱ • ϏδωεϩδοΫͷొ৔ਓ෺͸Կ͔ • ར༻ऀ͸୭͔ʁ • ϏδωεϩδοΫͷओ໾͸୭͔

    • ϏδωεϩδοΫ͕࡞༻͢Δ৚݅͸ʁ • σʔλϕʔε΍ϥΠϒϥϦʹनΘΕͣʹɺ
 ࠷খ୯ҐͰϏδωεϩδοΫʹؔ࿈͢Δ΋ͷΛ
 ෼ղ͢Δ
  13. 32.

    Entity • ΞϓϦέʔγϣϯͷओ໾ • ݸମΛࣝผͰ͖Δ΋ͷ Θͨ͠ͱ͋ͳͨ • ͜Εͱ͋ΕͱͦΕ͸ಉ͡΋ͷ͔Ͳ͏͔ • 5ࡀͷࠒͷࢲͱࠓͷࢲ͸ಉ͔͡Ͳ͏͔

    • ΞϓϦέʔγϣϯʹΑͬͯҟͳΔͨΊɺ
 ॻ੶Λݟͯࣸܦͯ͠ࡁΉྖҬͰ͸͋Γ·ͤΜ • σʔλϕʔεͷΧϥϜ ΠίʔϧͰ͸͋Γ·ͤΜ
  14. 33.

    final class Person implements EntityInterface { /** @var int */

    private $id; /** @var string */ private $name; public function __construct(int $id, string $name) { $this->id = $id; $this->name = $name; } }
  15. 34.

    Value Object • ෆมͰ͋Δ͜ͱ • ೥ྸ΍Կ͔͕ҟͳ͍ͬͯΔ͕ݸ͸มΘΒͳ͍
 -> ೥ྸ΍Կ͔ Value Object

    • Entityͷ෇Ճ৘ใͰ͋Γɺຊ࣭తͳͱ͜ΖͰ ͸ͳ͍͔΋͠Εͳ͍ • ը໘্ʹදࣔ͢Δ΋ͷɺͰ͸͋Γ·ͤΜ
  16. 37.

    class ActiveUserSpecification implements SpecificationInterface { public function isSatisfiedBy(EntityInterface $entity) {

    if ($entity->getIdentifier() === '') { return false; } return true; } public function satisfyingSpecification(TokenRepository $repository) { $repository->criteria($this); $result = $repository->queryBy($this->token); if (count($result)) { if ($this->isSatisfiedBy($result[0])) { return $result[0]; } } return null; } }
  17. 38.

    class UserRepository { public function findOne(ActiveUserSpecification $specification) { return $specification->satisfyingSpecification($this);

    } public function queryBy(string $token): array { $collection = new UserCollection([ $this->criteria->retrieve($token) ]); return $collection->toArray(); } }
  18. 39.

    Domain Service • Entity΍Value ObjectͰදݱͰ͖ͳ͍ɺ
 ϏδωεϩδοΫʹج͍ͮͯॲཧΛߦ͏ • ൚༻తͳΫϥεͰ͸ͳ͍ͨΊɺxxServiceͱ͍͏໊લ͸ආ͚ ͨํ͕ྑ͍ •

    Application Service͔Βར༻͞ΕΔ͜ͱ͕ଟ͍ • υϝΠϯͷ஌͕ࣝ֎ʹᷓΕͳ͍༷ʹ஫ҙ͢Δ
 (Repository͕࿐ग़͍ͯ͠ΔͳͲ) • υϝΠϯʹ͸ؔ܎ͳ͍ϑϨʔϜϫʔΫͷػೳͳͲ΋ར༻͠ ͳ͍༷ʹ஫ҙ͢Δ
  19. 43.

    class SampleResponder { protected $response; public function __construct(Response $response) {

    $this->response = $response; } public function __invoke(array $data = []) { if(!count($data)) { $content = $this->templateRenderer->render(‘not_found’, []); return $response->setStatus(404)->setContent($content); } $content = $this->templateRenderer->render(‘show’, [‘data’ => $data]); return $response->setStatus(200)->setContent($content); } }
  20. 46.

    class Payload { private $status; private $output; public function setOutput($output)

    { $this->output = $output; } public function setStatus(int $status) { $this->status = $status; } public function getOutput() { return $this->output; } public function getStatus() { return $this->status; } }
  21. 47.

    public function read($id) { $payload = new Payload; try {

    $result = $this->repository->findOne($id); if (!$result) { return $payload->setStatus(404); } return $payload->setStatus(200)->setOutput($result); } catch (Exception $e) { return $payload->setStatus(500)->setOutput("error"); } }
  22. 52.

    final class UserController extends Controller { protected $userRegister; public function

    __construct(UserRegister $userRegister) { $this->userRegister = $userRegister; } public function show($id) { return view('user.profile', ['user' => $this->userRegister->find($id)]); } public function create(Request $request) { Validate::make(…); $this->fluent->append($request->all()); return view('user.create'); } }
  23. 53.

    final class UserReadController extends Controller { protected $userRegister; public function

    __construct(UserRegister $userRegister) { $this->userRegister = $userRegister; } public function __invoke($id) { return view('user.profile', ['user' => $this->userRegister->find($id)]); } }
  24. 60.

    try • Framework • zendframework/zend-expressive • radarphp/Radar.Project
 • Component •

    zendframework/zend-diactoros • symfony/http-foundation • nikic/fast-route • etc…