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

実践 Action Domain Responder

実践 Action Domain Responder

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

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…