お問い合わせ

ブログ

これまでに経験してきたプロジェクトで気になる技術の情報を紹介していきます。

cakephp4にバージョンアップにてActionの処理の防止について

Yamanaka Yamanaka 6 months
cakephp4にバージョンアップにてActionの処理の防止について

クライアントエンジニアもしていますが、 サーバ側の開発を行っている山中です。

今回はcakephp3を使用していたプロジェクトをcakephp4にバージョンアップしようとして躓いた部分がありましたので、 ブログにしました。

それはcakephp4のinvokeActionとbeforeRenderです。

Controllerを継承して行います。 cakephp3ではbeforeFilterでチェックして、 invokeActionでアクションを実行したくないなら

    return false;

実行したいなら

    return parent::invokeAction();

を実行し、 beforeRenderで出力を行いました。

cakephp4でも同様に出来ると思いきや、invokeActionの形が変わっています。 どうやら引数が必要となり、返却値が無いようです。

引数を追加してreturnでは何も返さなくしましたが、 beforeRenderが動作している様子がありません。

継承元をを比べてみます。 〇cakephp3時

    public function invokeAction()
    {
        $request = $this->request;
        if (!$request) {
            throw new LogicException('No Request object configured. Cannot invoke action');
        }
        if (!$this->isAction($request->getParam('action'))) {
            throw new MissingActionException([
                'controller' => $this->name . 'Controller',
                'action' => $request->getParam('action'),
                'prefix' => $request->getParam('prefix') ?: '',
                'plugin' => $request->getParam('plugin'),
            ]);
        }
        /** @var callable $callable */
        $callable = [$this, $request->getParam('action')];

        $result = $callable(...array_values($request->getParam('pass')));
        if ($result instanceof Response) {
            $this->response = $result;
        }

        return $result;
    }

〇cakephp4時

    public function invokeAction(Closure $action, array $args): void
    {
        $result = $action(...$args);
        if ($result !== null && !$result instanceof ResponseInterface) {
            throw new UnexpectedValueException(sprintf(
                'Controller actions can only return ResponseInterface instance or null. '
                . 'Got %s instead.',
                getTypeName($result)
            ));
        }
        if ($result === null && $this->isAutoRenderEnabled()) {
            $result = $this->render();
        }
        if ($result) {
            $this->response = $result;
        }
    }

気になった部分は$result = $this->render();です。 これはビューの描画のメゾットです。 cakephp4になり、ビューの描画はどうやらinvokeAction内で行われるようになったみたいです。

beforeRenderは「コントローラーのアクションロジックの後、ビューが描画される前に発動する」とありますので、 ビューの描画が行われなかった為に動かなかったと推測されます。

そこで、アクションを実行しない場合でも$this->render();を行うことでbeforeRenderが動くようになりました。

〇cakephp3時の継承コントローラーのinvokeAction

    public function invokeAction() {
        $res = null;

        if (アクションを行わないかのチェック) {
            return $res;
        }
        $res = parent::invokeAction();
        return $res;
    }

〇cakephp4時の継承コントローラーのinvokeAction

    public function invokeAction(Closure $action, array $args): void {
        if (アクションを行わないかのチェック) {
            $this->render();
            return;
        }
        parent::invokeAction($action, $args);
        return;
    }

以上 山中がお伝えしました。またお会いしましょう!

cakephp4にバージョンアップにてActionの処理の防止について 2022-03-18 13:57:22

コメントはありません。

4816

お気軽に
お問い合わせください。

お問い合わせ