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

フレームワークを作りながらLaravelのアーキテクチャを学ぶ / Learn Laravel's architecture while creating a framework

フレームワークを作りながらLaravelのアーキテクチャを学ぶ / Learn Laravel's architecture while creating a framework

Futoshi Endo

March 30, 2019
Tweet

More Decks by Futoshi Endo

Other Decks in Technology

Transcript

  1. ൃද಺༰ͷഎܠ ͳͥ-BSBWFMͷΞʔΩςΫνϟΛֶͿͷ͔ ཧ༝ )PX खஈ Ͱ͸ͳ͘8IZ ຊ࣭ Λशಘ͔ͨͬͨ͠ 8IZ ຊ࣭

    ΛֶͿࣄ͸ࠓޙͷΤϯδχΞͱͯ͠΋ ·ͨΞϓϦέʔγϣϯ։ൃʹ͓͍ͯڧΈʹͳΔͱ൑அͨ͠ɻ
  2. 1)1Ͱࣗ࡞.7$ϑϨʔϜϫʔΫΛࣗ࡞͢Δ $MBTT-PBEFSͷ࢓૊Έ public function register() { spl_autoload_register([$this,'loadClass']); } . (লུ)

    . public function loadClass($class) { foreach ($this->dir as $dir){ $file = $dir . '/' . $class.'.php'; // Tells whether a file exists and is readable if(is_readable($file)){ require $file; return; } } } $MBTT-PBEFSQIQ Ұ෦ൈਮ
  3. 1)1Ͱࣗ࡞.7$ϑϨʔϜϫʔΫΛࣗ࡞͢Δ protected function registerRoutes() { return [ '/' => ['controller'

    => 'post', 'action' => 'home'], '/hello' => ['controller' => 'post', 'action' => 'hello'], ]; } $POUSPMMFS໊ "DUJPO໊ ࣮ߦ͢Δϝιου ϧʔςΟϯάઃఆ
  4. 1)1Ͱࣗ࡞.7$ϑϨʔϜϫʔΫΛࣗ࡞͢Δ protected function registerRoutes() { return [ '/' => ['controller'

    => 'post', 'action' => 'home'], '/hello' => ['controller' => 'post', 'action' => 'hello'], ]; } $POUSPMMFS໊ "DUJPO໊ ࣮ߦ͢Δϝιου $POUSPMMFS໊͕σΟϨΫτϦʹͳΓ ࢦఆ͕ͳ͚Ε͹"DUJPO໊͕ςϯϓϨʔτϑΝΠϧʹͳΔ ϧʔςΟϯάઃఆ
  5. 1)1Ͱࣗ࡞.7$ϑϨʔϜϫʔΫΛࣗ࡞͢Δ protected function registerRoutes() { return [ '/' => ['controller'

    => 'post', 'action' => 'home'], '/hello' => ['controller' => 'post', 'action' => 'hello'], ]; } $POUSPMMFS໊ "DUJPO໊ ࣮ߦ͢Δϝιου WJFXTDPOUSPMMFS@OBNFBDUJPO@OBNF 7JFXϑΝΠϧͷ໊લղܾϧʔϧ
  6. 1)1Ͱࣗ࡞.7$ϑϨʔϜϫʔΫΛࣗ࡞͢Δ protected function registerRoutes() { return [ '/' => ['controller'

    => 'post', 'action' => 'home'], '/hello' => ['controller' => 'post', 'action' => 'hello'], ]; } $POUSPMMFS໊ "DUJPO໊ ࣮ߦ͢Δϝιου 7JFXϑΝΠϧͷ໊લղܾϧʔϧ
  7. 1)1Ͱࣗ࡞.7$ϑϨʔϜϫʔΫΛࣗ࡞͢Δ protected function registerRoutes() { return [ '/' => ['controller'

    => 'post', 'action' => 'home'], '/hello' => ['controller' => 'post', 'action' => 'hello'], ]; } $POUSPMMFS໊ "DUJPO໊ ࣮ߦ͢Δϝιου 7JFXϑΝΠϧͷ໊લղܾϧʔϧ $POUSPMMFS໊ "DUJPO໊
  8. %C3FQPTJUPSZ 1)1Ͱࣗ࡞.7$ϑϨʔϜϫʔΫΛࣗ࡞͢Δ 3FRVFTU 3PVUFS $POUSPMMFS %C.BOBHFS 7JFX 3FTQPOTF "QQMJDBUJPO 3PVUFS

    ᶅϧʔςΟϯάॲཧ ϦΫΤετͰड͚ͬͨ63-͔Β1"5)@*/'0ΛऔΓग़ͯ͠ $POUSPMMFSͱ"DUJPOΛಛఆ͢Δ શମͷΞϓϦέʔγϣϯͷྲྀΕ
  9. %C3FQPTJUPSZ 1)1Ͱࣗ࡞.7$ϑϨʔϜϫʔΫΛࣗ࡞͢Δ 3FRVFTU 3PVUFS $POUSPMMFS %C.BOBHFS 7JFX 3FTQPOTF "QQMJDBUJPO 3PVUFS

    ᶅϧʔςΟϯάॲཧ ϦΫΤετͰड͚ͬͨ63-͔Β1"5)@*/'0ΛऔΓग़ͯ͠ $POUSPMMFSͱ"DUJPOΛಛఆ͢Δ ᶄ(&5Ͱ IUUQFYBNQMFDPNQPTUT΁ϦΫΤετ͢Δ શମͷΞϓϦέʔγϣϯͷྲྀΕ
  10. %C3FQPTJUPSZ 1)1Ͱࣗ࡞.7$ϑϨʔϜϫʔΫΛࣗ࡞͢Δ 3FRVFTU 3PVUFS $POUSPMMFS %C.BOBHFS 7JFX 3FTQPOTF "QQMJDBUJPO 3PVUFS

    ᶅϧʔςΟϯάॲཧ ϦΫΤετͰड͚ͬͨ63-͔Β1"5)@*/'0ΛऔΓग़ͯ͠ $POUSPMMFSͱ"DUJPOΛಛఆ͢Δ શମͷΞϓϦέʔγϣϯͷྲྀΕ ᶅϧʔςΟϯάॲཧ ਖ਼نදݱͷʮΩϟϓνϟʯͰϚονͨ͠஋ͱϧʔςΟϯά Λൺֱ͍ͯ͠Δ ᶄ(&5Ͱ IUUQFYBNQMFDPNQPTUT΁ϦΫΤετ͢Δ
  11. 1)1Ͱࣗ࡞.7$ϑϨʔϜϫʔΫΛࣗ࡞͢Δ /** * * PATH_INFOͷ৘ใΛड͚औΓɺϚονͨ͠৔߹ʹarray_mergeͰ$matchesͷத਎Λ$paramsʹϚʔδͯ͠ฦ͢ * * @param $path_info *

    @return array|bool */ public function resolve($path_info) { if(substr($path_info,0,1) !== '/'){ $path_info = '/'.$path_info; } foreach ($this->router as $pattern => $params) { if(preg_match('#^'.$pattern.'$#', $path_info, $matches)){ $params = array_merge($params,$matches); return $params; } } return false; } 3PVUFSQIQ
  12. %C3FQPTJUPSZ 1)1Ͱࣗ࡞.7$ϑϨʔϜϫʔΫΛࣗ࡞͢Δ 3FRVFTU 3PVUFS $POUSPMMFS %C.BOBHFS 7JFX 3FTQPOTF "QQMJDBUJPO $POUSPMMFS

    શମͷΞϓϦέʔγϣϯͷྲྀΕ '/posts' => ['controller' => 'post', 'action' => 'posts'],
  13. %C3FQPTJUPSZ 1)1Ͱࣗ࡞.7$ϑϨʔϜϫʔΫΛࣗ࡞͢Δ 3FRVFTU 3PVUFS $POUSPMMFS %C.BOBHFS 7JFX 3FTQPOTF "QQMJDBUJPO $POUSPMMFS

    ᶆ$POUSPMMFS ϧʔςΟϯάͰܾΊΒΕͯͨ1PTU$POUSPMMFSΛݺͼग़ͯ͠ QPTUT"DUJPO ϝιου Λ࣮ߦ͢Δɻ '/posts' => ['controller' => 'post', 'action' => 'posts'], શମͷΞϓϦέʔγϣϯͷྲྀΕ
  14. 1)1Ͱࣗ࡞.7$ϑϨʔϜϫʔΫΛࣗ࡞͢Δ // ౤ߘઌҰཡΛऔಘ͢Δ public function postsAction() { $posts = $this->db_manager

    ->get('Post') ->fetchAllPosts(); return $this->render( [ 'posts' => $posts ] ); } 1PTU$POUSPMMFSQIQ
  15. 1)1Ͱࣗ࡞.7$ϑϨʔϜϫʔΫΛࣗ࡞͢Δ // ౤ߘઌҰཡΛऔಘ͢Δ public function postsAction() { $posts = $this->db_manager

    ->get('Post') ->fetchAllPosts(); return $this->render( [ 'posts' => $posts ] ); } 1PTU$POUSPMMFSQIQ
  16. ݟग़͕͠ೖΓ·͢ public function renderView($_path, $_variables = [ ], $_layout =

    false) { $_file = $this->base_dir . '/' . $_path . '.php'; extract(array_merge($this->defaults, $_variables)); // Ξ΢τϓοτόοϑΝϦά։࢝ ob_start(); // όοϑΝΛ௒͑ͨ৔߹ʹࣗಈͰϑϥογϡ͢ΔઃఆΛOFFʹ͢Δ ob_implicit_flush(0); // viewϑΝΠϧಡΈࠐΉ require $_file; // $contentʹόοϑΝͨ͠஋ΛೖΕ͍ͯ͘ $content = ob_get_clean(); if ($_layout) { $content = $this->renderView($_layout, array_merge($this->layout_variables, array( '_content' => $content, ) )); } return $content; } 7JFXQIQ
  17. 1)1Ͱࣗ࡞.7$ϑϨʔϜϫʔΫΛࣗ࡞͢Δ 3FRVFTU 3PVUFS $POUSPMMFS %C.BOBHFS 7JFX 3FTQPOTF "QQMJDBUJPO %C3FQPTJUPSZ 3FTQPOTF

    ᶊΫϥΠΞϯτଆʹ ʮIUUQFYBNQMFDPNQPTUTʯͷը໘Λ Ϩεϙϯεͱͯ͠ฦ͢ શମͷΞϓϦέʔγϣϯͷྲྀΕ
  18. 1)1Ͱࣗ࡞.7$ϑϨʔϜϫʔΫΛࣗ࡞͢Δ .7$ϑϨʔϜϫʔΫΛ࡞Δ্Ͱࣄલʹ͋Δͱྑͦ͞͏஌ࣝ public function test_resolve() { $pathInfo = 'user/:id'; $params

    = $this->routes->resolve($pathInfo); assertEquals('user',$params['controller']); assertEquals('edit',$params['action']); assertEquals(':id',$params['id']); assertEquals('/user/:id',$params['0']); assertEquals('/;id',$params['1']); }
  19. %FQFOEFODZ*OKFDUJPOͱ͸ class User { protected $service; public function __construct() {

    $this->service = new Service(); } public function doSomething() { $this->service->sayHi(); } } Class Service { public function sayHi() { echo 'Hi!'; } -BSBWFMͷΞʔΩςΫνϟΛֶͼɺࣗ࡞'8ͱൺֱͯ͠ΈΔ
  20. %FQFOEFODZ*OKFDUJPOͱ͸ class User { protected $service; public function __construct() {

    $this->service = new Service(); } public function doSomething() { $this->service->sayHi(); } } Class Service { public function sayHi() { echo 'Hi!'; } 6TFSΫϥε಺Ͱ4FSWJDFΦϒδΣΫτ͕ੜ੒͞Ε͍ͯΔ -BSBWFMͷΞʔΩςΫνϟΛֶͼɺࣗ࡞'8ͱൺֱͯ͠ΈΔ
  21. %FQFOEFODZ*OKFDUJPOͱ͸ class User { protected $service; public function __construct() {

    $this->service = new Service(); } public function doSomething() { $this->service->sayHi(); } } Class Service { public function sayHi() { echo 'Hi!'; } 6TFSΫϥε಺Ͱ4FSWJDFΦϒδΣΫτ͕ੜ੒͞Ε͍ͯΔ 6TFSΫϥε͸4FSWJDFΦϒδΣΫτʹґଘ͍ͯ͠Δ -BSBWFMͷΞʔΩςΫνϟΛֶͼɺࣗ࡞'8ͱൺֱͯ͠ΈΔ
  22. %FQFOEFODZ*OKFDUJPOͱ͸ <?php class User { protected $service; public function __construct(Service

    $service) { $this->service = $service; } public function doSomething() { $this->service->sayHi(); } } Class Service { public function sayHi() { echo 'Hi!'; } } ίϯετϥΫλੜ੒࣌ʹ֎෦͔ΒඞཁͳΦϒδΣΫτΛ஫ೖ͢Δ $POTUSVDUPS*OKFDUJPO -BSBWFMͷΞʔΩςΫνϟΛֶͼɺࣗ࡞'8ͱൺֱͯ͠ΈΔ
  23. %FQFOEFODZ*OKFDUJPOͱ͸ $service = new Service(); $user = new User($service); $user->doSomething();

    ίϯετϥΫλੜ੒࣌ʹ֎෦͔ΒඞཁͳΦϒδΣΫτΛ஫ೖ͢Δ -BSBWFMͷΞʔΩςΫνϟΛֶͼɺࣗ࡞'8ͱൺֱͯ͠ΈΔ
  24. %FQFOEFODZ*OKFDUJPOͱ͸ class User { protected $service; public function __construct(ServiceInterface $service)

    { $this->service = $service; } public function doSomething() { $this->service->sayHi(); } } interface ServiceInterface { public function sayHi(); } Class HogeService implements ServiceInterface { public function sayHi() { echo 'Hi! Hoge!'; } } Class FugaService implements ServiceInterface { public function sayHi() { echo 'Hi! Fuga'; } } ڞ௨ͷ4FSWJDF*OUFSGBDFΛ࡞੒͢Δ -BSBWFMͷΞʔΩςΫνϟΛֶͼɺࣗ࡞'8ͱൺֱͯ͠ΈΔ
  25. %FQFOEFODZ*OKFDUJPOͱ͸ class User { protected $service; public function __construct(ServiceInterface $service)

    { $this->service = $service; } public function doSomething() { $this->service->sayHi(); } } interface ServiceInterface { public function sayHi(); } Class HogeService implements ServiceInterface { public function sayHi() { echo 'Hi! Hoge!'; } } Class FugaService implements ServiceInterface { public function sayHi() { echo 'Hi! Fuga'; } } ֤ΫϥεͰ4FSWJDF*OUFSGBDFΛ࣮૷͢Δ -BSBWFMͷΞʔΩςΫνϟΛֶͼɺࣗ࡞'8ͱൺֱͯ͠ΈΔ
  26. class User { protected $service; public function __construct(ServiceInterface $service) {

    $this->service = $service; } public function doSomething() { $this->service->sayHi(); } } interface ServiceInterface { public function sayHi(); } Class HogeService implements ServiceInterface { public function sayHi() { echo 'Hi! Hoge!'; } } Class FugaService implements ServiceInterface { public function sayHi() { echo 'Hi! Fuga'; } } ServiceInterfaceΛλΠϓώϯτͤͯ͞ $POTUSVDUPS*OKFDUJPOͤ͞Δ -BSBWFMͷΞʔΩςΫνϟΛֶͼɺࣗ࡞'8ͱൺֱͯ͠ΈΔ %FQFOEFODZ*OKFDUJPOͱ͸
  27. %FQFOEFODZ*OKFDUJPOͱ͸ // HogeService $service = new HogeService(); $user = new

    User($service); $user->doSomething(); #Hi! Hoge! // FugaService $service = new FugaService(); $user = new User($service); $user->doSomething(); #Hi! Fuga ֎෦͔Βґଘ͢ΔΦϒδΣΫτ஫ೖ͚ͩͰྑ͍ʂ ݩͷ6TFSΫϥεʹมߋ͸ى͖ͳ͍ -BSBWFMͷΞʔΩςΫνϟΛֶͼɺࣗ࡞'8ͱൺֱͯ͠ΈΔ
  28. %*ίϯςφͱ͸ // HogeService $service = new HogeService(); $user = new

    User($service); $user->doSomething(); ͭͱ͔ͩͬͨΒ·ͩࠔΒͳ͍ -BSBWFMͷΞʔΩςΫνϟΛֶͼɺࣗ࡞'8ͱൺֱͯ͠ΈΔ
  29. %*ίϯςφͱ͸ $service1 = new Service1(); $service2 = new Service2(); $service3

    = new Service3(); $user = new User($service1,$service2,$service3); $user->doSomething(); ֎෦͔Β஫ೖ͢ΔΦϒδΣΫτ͕ଟ͗ͯ͢ɺґଘؔ܎ ͕ෳࡶʹͳΓੜ੒͕େมʹͳͬͯ͘Δ -BSBWFMͷΞʔΩςΫνϟΛֶͼɺࣗ࡞'8ͱൺֱͯ͠ΈΔ
  30. use Pimple\Container; $container = new Container(); $container['service1'] = function($c){ return

    new Service1(); }; $container['service2'] = function ($c){ return new Service2(); }; $container['service3'] = function ($c){ return new Service3(); }; $container['user'] = function($c) { return new User($c['service1'], $c['service2'], $c['service3']); }; ࣄલʹΠϯελϯεͷੜ੒ํ๏Λొ࿥͓ͯ͘͠ -BSBWFMͷΞʔΩςΫνϟΛֶͼɺࣗ࡞'8ͱൺֱͯ͠ΈΔ
  31. use Pimple\Container; $container = new Container(); $container['service1'] = function($c){ return

    new Service1(); }; $container['service2'] = function ($c){ return new Service2(); }; $container['service3'] = function ($c){ return new Service3(); }; $container['user'] = function($c) { return new User($c['service1'], $c['service2'], $c['service3']); }; Πϯελϯεੜ੒࣌ʹґଘؔ܎Λղܾͤ͞ΔΑ͏ʹ͢Δ -BSBWFMͷΞʔΩςΫνϟΛֶͼɺࣗ࡞'8ͱൺֱͯ͠ΈΔ
  32. %*ίϯςφͱ͸ $service1 = new Service1(); $service2 = new Service2(); $service3

    = new Service3(); $user = new User($service1,$service2,$service3); $user->doSomething(); #FGPSF -BSBWFMͷΞʔΩςΫνϟΛֶͼɺࣗ࡞'8ͱൺֱͯ͠ΈΔ
  33. %*ίϯςφͱ͸ //$service1 = new Service1(); //$service2 = new Service2(); //$service3

    = new Service3(); // //$user = new User($service1,$service2,$service3); $user = $container['user']; $user->doSomething(); "GUFS -BSBWFMͷΞʔΩςΫνϟΛֶͼɺࣗ࡞'8ͱൺֱͯ͠ΈΔ
  34. αʔϏείϯςφͱ͸ ྫ TJOHMFUPOϝιου αʔϏείϯςφͰΠϯελϯεͷੜ੒ํ๏Λొ࿥͓ͯ͘͠ͱɺ͔࣍ΒΩϟογϡ ͞ΕͨΠϯελϯε͕ฦ͞Ε·͢ɻ $container->singleton('TwitterClient',function() { return new TwitterClient();

    }); $tweet1 = $container->make('TwitterClient'); $tweet2 = $container->make('TwitterClient'); if($tweet1 === $tweet2){ echo 'true'; #true } -BSBWFMͷΞʔΩςΫνϟΛֶͼɺࣗ࡞'8ͱൺֱͯ͠ΈΔ
  35. ϑΝαʔυͱ͸  $debug = \Config::get(‘app.debug’); ᶃϑΝαʔυΫϥε $POpH ͷղܾ ˣ ᶄϑΝαʔυΫϥεͷΫϥεϝιου࣮ߦ

    ˣ ᶅαʔϏείϯςφ͔ΒΠϯελϯεऔಘ ˣ ᶆΠϯελϯεϝιουͷ࣮ߦ -BSBWFMͷΞʔΩςΫνϟΛֶͼɺࣗ࡞'8ͱൺֱͯ͠ΈΔ
  36. 3FRVFTU 3PVUFS $POUSPMMFS %C.BOBHFS 7JFX 3FTQPOTF "QQMJDBUJPO %C3FQPTJUPSZ .PEFM૚ $POUSPMMFS૚

    7JFX૚ .7$ύλʔϯ Y೥ -BSBWFMͷΞʔΩςΫνϟΛֶͼɺࣗ࡞'8ͱൺֱͯ͠ΈΔ
  37. 3FRVFTU 3PVUFS $POUSPMMFS 7JFX 3FTQPOTF -BSBWFM .PEFM .PEFM૚ $POUSPMMFS૚ 7JFX૚

    -BSBWFMͷ.7$ύλʔϯ ೥ -BSBWFMͷΞʔΩςΫνϟΛֶͼɺࣗ࡞'8ͱൺֱͯ͠ΈΔ
  38. 3FRVFTU 3PVUFS $POUSPMMFS 7JFX 3FTQPOTF -BSBWFM .PEFM .PEFM૚ $POUSPMMFS૚ 7JFX૚

    -BSBWFMͷ.7$ύλʔϯ ೥ facades -BSBWFMͷΞʔΩςΫνϟΛֶͼɺࣗ࡞'8ͱൺֱͯ͠ΈΔ