【CakePHP】CakePHP4でAjaxからのPOSTが403(Forbidden)エラーになる現象の解決策

※環境:CakePHP 4.0.3

※現象:jQueryのajaxでPOSTを投げるとき、403(Forbidden)が返されました。

※原因:
「config/routes.php」に全体のCSRFチェックの処理がデフォルトで入っているため、フォーム以外からのPOSTはエラーになります。

※対策:
・「config/routes.php」の全体のCSRFチェックをコメントアウトします。
・「src/Application.php」で個別にホワイトリスト(CSRFのチェックを行わないコントローラとアクション)を設定します。

↓↓(例)

(1)「config/routes.php」の修正:4行コメントアウト

$routes->scope('/', function (RouteBuilder $builder) {

//    $builder->registerMiddleware('csrf', new CsrfProtectionMiddleware([ // ← この行をコメントアウト
//        'httpOnly' => true,                                             // ← この行をコメントアウト
//    ]));                                                                // ← この行をコメントアウト

//    $builder->applyMiddleware('csrf');                                  // ← この行をコメントアウト

    // ・・・以下省略・・・

});

(2)「src/Application.php」の修正:3ヶ所追加

use Cake\Http\Middleware\CsrfProtectionMiddleware;  // 名前空間の記述を追加


    // ・・・中略・・・
    
    
    public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue
    {
                // ↓↓ここから追加
        $csrf = new CsrfProtectionMiddleware(['httpOnly' => true]);
        $csrf->whitelistCallback(function ($request) {
            $controller = $request->getParam('controller');
            $action = $request->getParam('action');
            if (is_null($controller) || is_null($action)) {
                return false;
            }
            // ↓↓ホワイトリストの指定
            $aryOkControllersAndActions = [
                ['controller' => 'Articles', 'action' => 'add'],
                ['controller' => 'Articles', 'action' => 'edit'],
                ['controller' => 'Articles', 'action' => 'delete'],
                ['controller' => 'Users', 'action' => 'add'],
            ];
            // ↑↑ホワイトリストの指定
            foreach($aryOkControllersAndActions as $aryOkControllerAndAction) {
                if (strcmp($controller, $aryOkControllerAndAction['controller']) == 0 && strcmp($action, $aryOkControllerAndAction['action']) == 0) {
                    return true;
                }
            }
            return false;
        });
        // ↑↑ここまで追加
        
        
        $middlewareQueue
            // Catch any exceptions in the lower layers,
            // and make an error page/response
            ->add(new ErrorHandlerMiddleware(Configure::read('Error')))
            
            // Handle plugin/theme assets like CakePHP normally does.
            ->add(new AssetMiddleware([
                'cacheTime' => Configure::read('Asset.cacheTime'),
            ]))
            
            // Add routing middleware.
            // If you have a large number of routes connected, turning on routes
            // caching in production could improve performance. For that when
            // creating the middleware instance specify the cache config name by
            // using it's second constructor argument:
            // `new RoutingMiddleware($this, '_cake_routes_')`
            ->add(new RoutingMiddleware($this))
            ->add($csrf); // ← ここに「->add($csrf)」を追加(セミコロン「;」の記述に要注意)
            
        return $middlewareQueue;
    }

↑上記の例では、「Articles/add」「Articles/edit」「Articles/delete」「Users/add」に対してだけ、CSRFチェックを行いません。

【CakePHP】Warning「Declaration of App\Controller\<コントローラー名>::beforeFilter(Cake\Event\Event $event) should be compatible with Cake\Controller\Controller::beforeFilter(Cake\Event\EventInterface $event)」について

※環境:CakePHP 4.0.3

beforeFilterを呼び出すため、コントローラー「UsersController」の中に、公式ドキュメントの指示通りに、

use Cake\Event\Event;

class UsersController extends AppController
{
    public function beforeFilter(Event $event)
    {
        parent::beforeFilter($event);
    }
}

↑を書きしたが、
下記警告が表示されました。

Warning (2): Declaration of App\Controller\UsersController::beforeFilter(Cake\Event\Event $event) should be compatible with Cake\Controller\Controller::beforeFilter(Cake\Event\EventInterface $event)

解決策:
警告の内容をよく確認すれば、「Cake\Event\Event」ではなく「Cake\Event\EventInterface」であることがわかりました。

→ 下記通りに書き直せばエラーが解消されました。

//use Cake\Event\Event; //(誤)
use Cake\Event\EventInterface; //(正)

class UsersController extends AppController
{
//    public function beforeFilter(Event $event) //(誤)
    public function beforeFilter(EventInterface $event) //(正)
    {
        parent::beforeFilter($event);
    }
}

【CakePHP】The requested address ‘XXXX’ was not found on this server. — 新規コントローラ(controller)追加時のエラー

稼動中のCakePHP(1.2)アプリケーションに一個新規画面を追加します。
テスト環境では問題なく完了しましたが、
本番に移行したら、

The requested address 'XXXX' was not found on this server.

というエラーが出てきました。

※解決策:
app/config/core.phpの中の「Debug.level」を0から一時的に1に設定すれば解決しました。
CakePHPのキャッシュが効いていたせいらしいです。

※参考資料:
The requested address ” was not found on this server. – foldrrの日記