ブロックチェーンに詳しいフリーのエンジニアのIT備忘録

ブロックチェーンに魅了されフリーのITエンジニアに転身した元暗号理論研究者のブログです。

cakephp3 Controllerを階層化する際の方法

ちょっとした決済システムを構築しています。


販売者(merchants)と顧客(customers)がいて、
決済(orders)を通じてデータが紐付いています。


それぞれにMVC(Model,View,Controller)があるわけですが、
販売者、顧客が自身の決済を参照するために、
管理画面を用意する必要があります。


そうなると、
販売者はmerchants/merchant:id/orders/index
顧客はcustomers/customer:id/orders/index
で決済を見るようにしたいわけです。


それを実現するために、
Controllerを階層化したいのですが、
Google先生で調べながらやると、
迷走してしまいました^^;


迷走した理由は、
2つの情報が錯綜しているからなのですが、
それは後述するとして、
先に階層化する方法を書きます。

Controllerを階層化する際の方法


(1) routes.phpに以下を追記する

>|php|

Router::prefix('merchants',function($routes){
$routes->fallbacks(DashedRoute::class);
});

|


(2) Controller/Merchants/OrdersController.phpを作成する

<?php
namespace App\Controller\Merchants;

use App\Controller\AppController;

/**
 * Merchants\Orders Controller
 *
 * @property \App\Model\Table\OrdersTable $Orders
 *
 * @method \App\Model\Entity\Order[]|\Cake\Datasource\ResultSetInterface paginate($object = null, array $settings = [])
 */
class OrdersController extends AppController
{ 
...

  /**
   * Index method
   *
   * @return \Cake\Http\Response|void
   */
 public function index(){
 }

...
}


(3) Template/Merchants/Orders/index.ctpを作成する


以外と簡単な設定ですみました。


ちなみにログイン画面は、
merchants/loginでアクセスしたいと考えた場合、


上記のroutes.phpの設定では、
merchantsController.phpを探しに行くのではなく、
src/Controller/Merchants/LoginController.php
探しにいってしまいます。


MerchantsController::loginの方に
アクセスしたい場合は、
routes.php

 $routes->connect('/merchants/login', ['controller' => 'Merchants','action' => 'login', 'prefix' => null]);

と記載すればOKです。

[補足] Google検索したら迷走した理由

階層化は前述の通り比較的簡単な設定ですみましたが、
実際ここにたどり着くためには、1,2時間要してしましました。

理由は2つの情報が錯綜していたからです。


2つの情報は、それぞれ以下です。
▼1つ目(Controllerを階層化する方法)
teratail.com

▼2つ目(階層化した時にController名がかぶった場合の設定)
norm-nois.com



1つ目の情報によると、
Controllerを階層化するには、
composer.jsonを修正して、
src/Controller/Merchants/ を自動読み込みすればよい
ということが書いてあります。


2つ目の情報によると、
src/Controller/UsersController.php
src/Controller/Admins/UsersController.php
のように別階層に同じ名前のControllerを置く場合は、
bootstarp.phpに数行その旨を記述しないといけない
ということが書いてあります。


最初に見つけた情報が
1つ目の記事だったので、
書いてあるとおりに実行をしたら、
Controllerを階層化することには成功しました。


しかし、階層構造の中に
同じ名前のコントローラが出てくると
片方のコントローラが読み込みエラーになります。


そのため、
2つ目の記事にある
src/Controller/UsersController.php
src/Controller/Admins/UsersController.php
という階層構造を作る方法を実践してみたのですが、
こちらはうまくいきませんでした。


最終的に、
1つ目の設定を解除して
routes.phpで公式ドキュメントにある
プレフィックスルーティングの設定をすることで
解決したというところになります。