0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

php slimで routingが正しくどうなっているかログを仕込む

Last updated at Posted at 2021-04-24

PHPでAPIサーバーを実装仕様として、slim frameworkを試すことにしました。

500エラーが出ているのだけど、ログを仕込んでもでてこない。
おそらく、routingが失敗しているのかな。。

と言うことで、routingの確認のログを仕込んでみました。

slim本体に手を入れることになるので、備忘録方々メモします

slim は v4です https://www.slimframework.com/docs/v4/

vendor/slim/Slim/Middleware.php を見る

  • $app = AppFactory::create();
  • $app->addRoutingMiddleware();

で、利用されるのが、上の Middleware.php になります

この中で、渡された urlからroutingを決めるのがこの部分

    protected function resolveRoutingResultsFromRequest(ServerRequestInterface $request): RoutingResults
    {
        return $this->routeResolver->computeRoutingResults(
            $request->getUri()->getPath(),
            $request->getMethod()
        );
    }

この routeResolver は vendor/slim/slim/Slim/interfaces/RouteResolverInterface.php なのですが、実体は

vendor/slim/slim/Slim/Routing/RouteResolver.php になります

    public function computeRoutingResults(string $uri, string $method): RoutingResults
    {
        $uri = rawurldecode($uri);
        if ($uri === '' || $uri[0] !== '/') {
            $uri = '/' . $uri;
        }
        return $this->dispatcher->dispatch($method, $uri);
    }

とたどっていくと、最終的に行き着くのが
vendor/slim/slim/Slim/Routing/FastRouteDispatcher.php

error_logを使って調べました

    private function routingResults(string $httpMethod, string $uri): array
    {
        if (isset($this->staticRouteMap[$httpMethod][$uri])) {
          error_log(" *** found in staticRouteMap "
            .$this->staticRouteMap[$httpMethod][$uri], 0);
            return [self::FOUND, $this->staticRouteMap[$httpMethod][$uri], []];
        }

        if (isset($this->variableRouteData[$httpMethod])) {
          $result = $this->dispatchVariableRoute($this->variableRouteData[$httpMethod], $uri);
          error_log(" *** found in variableRouteaData  ".print_r($result, true),
            0);
          if ($result[0] === self::FOUND) {
              return [self::FOUND, $result[1], $result[2]];
          }
        }
//        error_log("  **staticRouteMap".print_r($this->staticRouteMap,true),0);
//        error_log(" **variableRoute ".var_export($this->variableRouteData,true),0);
        return [self::NOT_FOUND, null, []];
    }

具体的に呼び出すのは
vendor/slim/slim/Slim/Routing/Route.phpの handleと言う部分

    public function handle(ServerRequestInterface $request): ResponseInterface
    {
        if ($this->callableResolver instanceof AdvancedCallableResolverInterface) {
            $callable = $this->callableResolver->resolveRoute($this->callable);
        } else {
            $callable = $this->callableResolver->resolve($this->callable);
        }
        $strategy = $this->invocationStrategy;
      error_log("** routing found3: ".print_r($callable,
          true),0);

        /** @var string[] $strategyImplements */
        $strategyImplements = class_implements($strategy);

        if (
            is_array($callable)
            && $callable[0] instanceof RequestHandlerInterface
            && !in_array(RequestHandlerInvocationStrategyInterface::class, $strategyImplements)
        ) {
            $strategy = new RequestHandler();
        }

        $response = $this->responseFactory->createResponse();
        return $strategy($callable, $request, $response, $this->arguments);
    }

今の調査だと、ここの "** routing found3: "と言うのが呼び出されていないのがわかりました。

Slimの Routerがどの様に関数を呼び出すのか?

この部分になります

vendor/slim/slim/Slim/CallableResolver.php

    private function resolveSlimNotation(string $toResolve): array
    {
        preg_match(CallableResolver::$callablePattern, $toResolve, $matches);
        [$class, $method] = $matches ? [$matches[1], $matches[2]] : [$toResolve, null];

        if ($this->container && $this->container->has($class)) {
            $instance = $this->container->get($class);
        } else {
            if (!class_exists($class)) {
                throw new RuntimeException(sprintf('Callable %s does not exist', $class));
            }
            $instance = new $class($this->container);
        }
        return [$instance, $method];
    }

こんな感じで、ログを出力する事で原因がやっとわかりました。参考までに

    private function resolveSlimNotation(string $toResolve): array
    {
        error_log( " ** ".__FUNCTION__." ".$toResolve." ".__FILE__."(".__LINE__.")",0);
        preg_match(CallableResolver::$callablePattern, $toResolve, $matches);
        [$class, $method] = $matches ? [$matches[1], $matches[2]] : [$toResolve, null];

        try {
          if ($this->container && $this->container->has($class)) {
            $instance = $this->container->get($class);
          } else {
            if (!class_exists($class)) {
              throw new RuntimeException(sprintf('Callable %s does not exist', $class));
            }
            $instance = new $class($this->container);
          }
        } catch (\Throwable $e){
          error_log( " ** ".__FUNCTION__." ".$e->getMessage()." ".__FILE__."(".__LINE__.")",0);
          throw $e;
        }
        return [$instance, $method];
    }

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?