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

20230315のPHP勉強会(Slimをオススメしてみる)

gallu
March 15, 2023

 20230315のPHP勉強会(Slimをオススメしてみる)

gallu

March 15, 2023
Tweet

More Decks by gallu

Other Decks in Technology

Transcript

  1. Slimいいよ!!  https://www.slimframework.com/  Slim is a PHP micro framework

    that helps you quickly write simple yet powerful web applications and APIs.  Slim は、シンプルかつ強力な Web アプリケーションと API をすばやく作 成するのに役立つ PHP マイクロ フレームワークです。(Google)  Slimは、シンプルかつパワフルなWebアプリケーションやAPIを素早く作 成できるPHPマイクロフレームワークです。(DeepL)  Slimいいです!!  micro framework いいです!!  シンプルでいいです!!  っていう個人の感想と妄想を垂れ流してみます(笑
  2. 実際どんな所が好きなのか?  軽量(なので早い)  メモリは、なんだかんだ無視しにくいリソースです  手元で var_dump(memory_get_peak_usage(true)) 仕込んだ結果 

    Slim: 2,097,152 / Laravel: 16,777,216  学習コストが(とりあえず)低い  「とりあえず」(笑  「素のPHPのみ」でWebアプリ書ければ大体なんとかなる!!  柔軟性と拡張性がある(というか全部自力で書け)  「全部自分で書け」なので「実装箇所がわかりやすい」(笑  「FWが何をやっているか」が理解しやすい  FWのコードもコンパクトなので、読みやすいです  「コンパクトだから読みやすいのか?」って欺瞞は棚の上にw
  3.  まずは適当なディレクトリで最低限をinstall  composer require slim/slim  composer require slim/psr7

     公開用ディレクトリ作成  mkdir public  index.phpを書く(公式サイトのコピペ)  次のページに記載  動かしてみる  php -S 0.0.0.0:8080 -t public public/index.php  http://ドメイン名/hello/gallu
  4.  public/index.php <?php use Psr¥Http¥Message¥ResponseInterface as Response; use Psr¥Http¥Message¥ServerRequestInterface as

    Request; use Slim¥Factory¥AppFactory; require __DIR__ . '/../vendor/autoload.php'; $app = AppFactory::create(); $app->get('/hello/{name}', function (Request $request, Response $response, array $args) { $name = $args['name']; $response->getBody()->write("Hello, $name"); return $response; }); $app->run();
  5.  元のpublic/index.php <?php use Psr¥Http¥Message¥ResponseInterface as Response; use Psr¥Http¥Message¥ServerRequestInterface as

    Request; use Slim¥Factory¥AppFactory; require __DIR__ . '/../vendor/autoload.php'; $app = AppFactory::create(); $app->get('/hello/{name}', function (Request $request, Response $response, array $args) { $name = $args['name']; $response->getBody()->write("Hello, $name"); return $response; }); $app->run();
  6.  public/index.php <?php use Slim¥Factory¥AppFactory; require __DIR__ . '/../vendor/autoload.php'; $app

    = AppFactory::create(); // ルーティングの読み込み require __DIR__ . '/../config/routes.php'; $app->run();
  7.  config/routes.php <?php declare(strict_types=1); use Psr¥Http¥Message¥ResponseInterface as Response; use Psr¥Http¥Message¥ServerRequestInterface

    as Request; // 初期に書いてあるルーティング $app->get('/hello/{name}', function (Request $request, Response $response, array $args) { $name = $args['name']; $response->getBody()->write("Hello, $name"); return $response; });
  8.  元 config/routes.php <?php declare(strict_types=1); use Psr¥Http¥Message¥ResponseInterface as Response; use

    Psr¥Http¥Message¥ServerRequestInterface as Request; // 初期に書いてあるルーティング $app->get('/hello/{name}', function (Request $request, Response $response, array $args) { $name = $args['name']; $response->getBody()->write("Hello, $name"); return $response; });
  9.  config/routes.php <?php declare(strict_types=1); use Psr¥Http¥Message¥ResponseInterface as Response; use Psr¥Http¥Message¥ServerRequestInterface

    as Request; // 初期に書いてあるルーティング $app->get('/hello/{name}', function (Request $request, Response $response, array $args) { $name = $args['name']; $response->getBody()->write("Hello, $name"); return $response; }); // 追加のルーティング $app->get('/', function (Request $request, Response $response, array $args) { $response->getBody()->write("Top Page"); return $response; });
  10. Controllerを切り出してみる  普通に考えて「routingん中にコードを書く」とか、常軌を 逸脱しているので  いわゆる「Controller」的なクラスを切り出してみましょう  まず「Controllerクラスを入れる」ディレクトリを作ります。 これもまぁどこでもよいのですが、慣習も考えてこんな風 にしてみましょう

     mkdir -p app/Controller  autoloaderとかないと色々面倒なので設定しましょう  composer.jsonに追記します(コードは次のページで)  requireのバージョンとかちょっと違ってもキニシナイ!!  composer dump-autoload
  11.  元 config/routes.php <?php declare(strict_types=1); use Psr¥Http¥Message¥ResponseInterface as Response; use

    Psr¥Http¥Message¥ServerRequestInterface as Request; // 初期に書いてあるルーティング $app->get('/hello/{name}', function (Request $request, Response $response, array $args) { $name = $args['name']; $response->getBody()->write("Hello, $name"); return $response; }); // 追加のルーティング $app->get('/', function (Request $request, Response $response, array $args) { $response->getBody()->write("Top Page"); return $response; });
  12.  config/routes.php <?php declare(strict_types=1); use Psr¥Http¥Message¥ResponseInterface as Response; use Psr¥Http¥Message¥ServerRequestInterface

    as Request; // 初期に書いてあるルーティング $app->get('/hello/{name}', ¥App¥Controller¥HelloController::class . ':index'); // 追加のルーティング $app->get('/', ¥App¥Controller¥HomeController::class);
  13.  app/Controller/HelloController.php <?php declare(strict_types=1); namespace App¥Controller; use Psr¥Http¥Message¥ServerRequestInterface as Request;

    use Psr¥Http¥Message¥ResponseInterface as Response; class HelloController { // 多分「よくある」系の書き方 public function index(Request $request, Response $response, $args) { $name = $args['name']; $response->getBody()->write("Hello, $name"); return $response; } }
  14.  app/Controller/HomeController.php <?php declare(strict_types=1); namespace App¥Controller; use Psr¥Http¥Message¥ServerRequestInterface as Request;

    use Psr¥Http¥Message¥ResponseInterface as Response; class HomeController { // XXX 1クラスに「1つしかメソッドを書くつもりがない」場合、こういった書き方もできる public function __invoke(Request $request, Response $response, $args) { // 出力 $response->getBody()->write("Top Page"); return $response; } }
  15. Controllerとして許容される形式は?  https://www.slimframework.com/docs/v4/objects/routi ng.html#container-resolution 以降に大体書いてあるの ですが  $app->get('/', '¥HomeController:home'); 

    $app->get('/', ¥HomeController::class . ':home');  $app->get('/', [¥HomeController::class, 'home']);  $app->get('/', ¥HomeAction::class);  __invoke() メソッドがある場合  となります  あと実際には「関数」も通りますね
  16. その辺のコードをざっくり見てみましょう  vendor/slim/slim/Slim/CallableResolver.phpの超訳 private function resolveSlimNotation(string $toResolve): array { [$class,

    $method] = :で文字列をsplit(:なかったらmethodには null) if (containerがclassを持ってたら) { $instance = containerからclassのインスタンスをげと インスタンスがげとれなければ例外を投げて終了 } else { if (クラスが存在していなかったら) { if (メソッドがnullじゃなければ) { $class .= '::' . $method . '()'; } $classないよ~、って例外をぶん投げて終了 } $instance = new $class($this->container); } return [$instance, $method]; }
  17. で……  vendor/slim/slim/Slim/CallableResolver.php public function resolve($toResolve): callable { $toResolve =

    $this->prepareToResolve($toResolve); if (is_callable($toResolve)) { return $this->bindToContainer($toResolve); } $resolved = $toResolve; if (is_string($toResolve)) { $resolved = $this->resolveSlimNotation($toResolve); $resolved[1] ??= '__invoke'; } $callable = $this->assertCallable($resolved, $toResolve); return $this->bindToContainer($callable); }