Upgrade to Pro — share decks privately, control downloads, hide ads and more …

実践 Action Domain Responder

実践 Action Domain Responder

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

Avatar for yuuki takezawa

yuuki takezawa

June 10, 2017
Tweet

More Decks by yuuki takezawa

Other Decks in Technology

Transcript

  1. 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'); } }
  2. final class UserReadAction { public function __construct(Responder $responder) { $this->responder

    = $responder; } public function __invoke($id) { return $this->responder->emit( ['user' => User::findOrFail($id)] ); } }
  3. $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; } });
  4. 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); } }
  5. Model, Domain • ϏδωεϩδοΫΛղܾ͢Δ૚ • υϝΠϯۦಈͷύλʔϯͰ࣮૷͢Δɺ
 ͱ͍͏ҙຯͰ͸ͳ͍ • ඞཁʹԠͯ͡ঢ়ଶ΍ӬଓԽΛ •

    ΤϯςΟςΟͳͲ͸ResponderͰར༻͢Δ͜ͱ͕͋ Δ
 (renderͳͲ) • ORMͰදݱ͢Δ΋ͷ͕υϝΠϯͰ͋Ε͹ͦΕͰ΋Մ
  6. $repository = new Repository(new Database()); $entity = new Entity(1, ‘testing’);

    $repository->add($entity); $repository->save(); // return Entity[] $repository->findAll();
  7. ϏδωεϩδοΫ࠶ߟ • ࣮૷ύλʔϯ͔Βߟ͑ΔͰ͸ͳ͘ɺ
 ΞϓϦέʔγϣϯΛטΈࡅ͘͜ͱ • ϏδωεϩδοΫͷొ৔ਓ෺͸Կ͔ • ར༻ऀ͸୭͔ʁ • ϏδωεϩδοΫͷओ໾͸୭͔

    • ϏδωεϩδοΫ͕࡞༻͢Δ৚݅͸ʁ • σʔλϕʔε΍ϥΠϒϥϦʹनΘΕͣʹɺ
 ࠷খ୯ҐͰϏδωεϩδοΫʹؔ࿈͢Δ΋ͷΛ
 ෼ղ͢Δ
  8. Entity • ΞϓϦέʔγϣϯͷओ໾ • ݸମΛࣝผͰ͖Δ΋ͷ Θͨ͠ͱ͋ͳͨ • ͜Εͱ͋ΕͱͦΕ͸ಉ͡΋ͷ͔Ͳ͏͔ • 5ࡀͷࠒͷࢲͱࠓͷࢲ͸ಉ͔͡Ͳ͏͔

    • ΞϓϦέʔγϣϯʹΑͬͯҟͳΔͨΊɺ
 ॻ੶Λݟͯࣸܦͯ͠ࡁΉྖҬͰ͸͋Γ·ͤΜ • σʔλϕʔεͷΧϥϜ ΠίʔϧͰ͸͋Γ·ͤΜ
  9. 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; } }
  10. Value Object • ෆมͰ͋Δ͜ͱ • ೥ྸ΍Կ͔͕ҟͳ͍ͬͯΔ͕ݸ͸มΘΒͳ͍
 -> ೥ྸ΍Կ͔ Value Object

    • Entityͷ෇Ճ৘ใͰ͋Γɺຊ࣭తͳͱ͜ΖͰ ͸ͳ͍͔΋͠Εͳ͍ • ը໘্ʹදࣔ͢Δ΋ͷɺͰ͸͋Γ·ͤΜ
  11. 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; } }
  12. 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(); } }
  13. Domain Service • Entity΍Value ObjectͰදݱͰ͖ͳ͍ɺ
 ϏδωεϩδοΫʹج͍ͮͯॲཧΛߦ͏ • ൚༻తͳΫϥεͰ͸ͳ͍ͨΊɺxxServiceͱ͍͏໊લ͸ආ͚ ͨํ͕ྑ͍ •

    Application Service͔Βར༻͞ΕΔ͜ͱ͕ଟ͍ • υϝΠϯͷ஌͕ࣝ֎ʹᷓΕͳ͍༷ʹ஫ҙ͢Δ
 (Repository͕࿐ग़͍ͯ͠ΔͳͲ) • υϝΠϯʹ͸ؔ܎ͳ͍ϑϨʔϜϫʔΫͷػೳͳͲ΋ར༻͠ ͳ͍༷ʹ஫ҙ͢Δ
  14. 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); } }
  15. 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; } }
  16. 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"); } }
  17. 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'); } }
  18. 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)]); } }
  19. try • Framework • zendframework/zend-expressive • radarphp/Radar.Project
 • Component •

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