もがき系プログラマの日常

もがき系エンジニアの勉強したこと、日常のこと、気になっている技術、備忘録などを紹介するブログです。

cakephp3でlaravelみたいにrouteファイルを分けてみた

はじめに

こんばんは。最近ちょっとずつcakephp3を触っている僕です。

まだよちよちですが、なんとなく触ってこんな感じかと確かめてます。

で、今回は、laravelみたいにrouteファイルを分けられないかなと挑戦してみました。

cakephp3は基本的にconfigフォルダ直下にroutes.phpがあり、そこで一括管理しているみたいです。

laravelみたいにデフォでrouteファイルが分かれている方が、「僕的には」スッキリしていいかなと感じたので、できるかどうかちょっとやってみました。

※あくまでルーティングファイルをわけるだけの作業です。

やってみた

cakephp3のroute管理は、RoutingMiddlewareとしてMiddleware登録されているみたいです。

デフォルトでApplication.phpに記載されていると思います。

<?php
   ...

$middlewareQueue->add(new RoutingMiddleware($this));

そして、Applicationクラスが継承している BaseApplicationクラス にroute判定する際に実行されるメソッドが存在します。

<?php
    ...

    /**
     * {@inheritDoc}
     *
     * By default this will load `config/routes.php` for ease of use and backwards compatibility.
     *
     * @param \Cake\Routing\RouteBuilder $routes A route builder to add routes into.
     * @return void
     */
    public function routes($routes)
    {
        if (!Router::$initialized) {
            // Prevent routes from being loaded again
            Router::$initialized = true;

            require $this->configDir . '/routes.php';
        }
    }

この、routes()は、Middlewareとして登録されたRoutingMiddlewareの __invoke() メソッド内で呼び出されるloadRoutes()によって実行されています。

というわけで、routesメソッドをまるっとオーバライドして、以下みたいに変えます。

<?php
    ....

    public function routes($routes)
    {
        if (!Router::$initialized) {
            require $this->configDir . '/routes.php';
            require $this->configDir . '/routes_api.php';
            // Prevent routes from being loaded again
            Router::$initialized = true;
        }
    }

requireしている箇所に一個足しているだけですね。

次にrequireしているroutes_api.phpを作成します。

<?php

use Cake\Routing\RouteBuilder;
use Cake\Routing\Router;
use Cake\Routing\Route\DashedRoute;

Router::defaultRouteClass(DashedRoute::class);

Router::prefix('api', function (RouteBuilder $routes) {
    $routes->get('/test', ['controller' => 'test', 'action' => 'index']);
});

prefixを指定することでnamespaceも App/Controller/Api にすることが出来ます。

prefix-routing

最後にroutingで設定しているコントローラを作成します。

<?php

namespace App\Controller\Api;

use App\Controller\AppController;

class TestController extends AppController
{
    public function index()
    {
        return $this->response->withType('application/json')->withStringBody(json_encode([
            'controller' => 'test',
            'action'     => 'index',
            'prefix'     => 'api',
            'url'        => '/api/test',
            'result'     => 1
        ]));
    }
}

f:id:kojirooooocks:20180415230531p:plain

出来ました。

終わりに

とまぁちょっと思いついたんでここまでやってみました。

実運用で使うかは微妙ですが。。

plugin機能使えばいいわけだし。

ただpluginはディレクトリツリーが深くなっちゃうので、そこがネックかなーと。

なんか他に方法あれば教えてください。

ではでは。