2025-06-05 2025-07-19

概要

cakePHP 2 から cakePHP 5 へのバージョンアップを行った際の覚え書き。

目次

ルーティング

基本的には従来通りのルーティングと変わらず、
以下のルールに従っていれば、個別のルーティング定義は不要となっている。

  • URI
    • /リソース名(コントローラ名)/アクション(メソッド名)
    • /リソース名(コントローラ名)/アクション(メソッド名)/{id}
  • 例)
    • /items/ -> ItemsController の index メソッドが実行される。
    • /items/update/{id}-> ItemsController の update メソッドが実行される。(メソッド引数で id が取得可能)

config/routes.php の定義の仕方によって、一般的な REST API 等で使用されるような URI 定義を行う事も可能。

use Cake\Routing\RouteBuilder;
use Cake\Routing\Router;

Router::defaultRouteClass(DashedRoute::class);

Router::scope('/', function (RouteBuilder $routes) {
    $routes->connect('/', ['controller' => 'Pages', 'action' => 'display', 'home']);
    $routes->connect('/articles/:id', ['controller' => 'Articles', 'action' => 'view'])
        ->setPass(['id'])
        ->setPatterns(['id' => '\d+']);
});

コントローラ

https://book.cakephp.org/5/ja/controllers.html

入力データの取得

// POST,PUT,DELETEリクエストの時
$name = $request->getData('name', '')

// GETリクエスト時のクエリ
$name = $request->getQuery('name', '')

コントローラの前後処理

https://github.com/cakephp/cakephp/blob/5.x/src/Controller/Controller.php#L582
※ beforeFilter, beforeRender, beforeRedirect, afterFilter など

public function beforeFilter($event){

    parent::beforeFilter($event);
        :
        // 処理
    }
}

afterFilter からコントローラ処理でセットした変数を参照する

class XxxxController extends AppController {

    public function index() {
        :
        
        $this->set("testvar", "test1234");
    }

    public function afterFilter($event) {

        parent::afterFilter($event);

        $testvar = $this->viewBuilder()->getVar("testvar");
    }
}

ページネーション

https://book.cakephp.org/5/ja/controllers/pagination.html

コントローラ側

class ItemsController extends AppController

    protected array $paginate = [
        'limit' => 20,
        'order' => ['Items.item_cd' => 'asc'],
    ];

    public function index() {
        $query = $this->Items->find()->all();
        $this->set('items', $this->paginate($query));
    }
}

ビュー側
https://book.cakephp.org/5/ja/views/helpers/paginator.html#paginatorhelper

コンポーネントのロード

public function initialize(): void
{
    parent::initialize();
    $this->loadComponent('MyComponent');
}

コンポーネントからコントローラを参照する

$this->getController()

レイアウトの選択/変更

$this->viewBuilder()->setLayout('my_layout');

自動レンダリングの無効化

$this->disableAutoRender();

レスポンスヘッダのカスタマイズ

$this->response = $this->response->withDisabledCache()
    ->withHeader('Expires', 'Mon, 26 Jul 1997 05:00:00 GMT')
    ->withHeader('Cache-Control', 'no-store, no-cache, must-revalidate')
    ->withHeader('Pragma', 'no-cache')
    ->withHeader('Keep-Alive', 'timeout=5, max=100')
    ->withHeader('Set-Cookie', 'dummy=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; Max-Age=0; path=/');

disableAutoRender を使用して header で自力設定も可能?

$this->disableAutoRender();
header('Content-Type: application/octet-stream');
header('Content-Length: '.strlen($data));
header('Content-disposition: attachment; filename="'.$filename.'"');
echo $data;

上記の実装だと警告メッセージが出力される
Unable to emit headers. Headers sent in file=/XXX/XXX/XXX

ファイルをダウンロードさせる場合は $this->response->withStringBody 等を使用した方が良さそう
https://book.cakephp.org/5/ja/controllers/request-response.html#id21

$this->response = $this->response->withStringBody($data)
    ->withType('application/octet-stream')
    ->withHeader('Content-Disposition', 'attachment; filename="' . $filename . '"');

モデル関連

テーブルに係るクラスはテーブルクラスとモデル(エンティティ)クラスにに分かれている。
※cakePHP 2 時点では、項目定義やバリデーション、更新前後の処理など、全てモデルクラスで全て行っていたが、単一責任原則に従って分離された。

データベースアクセス & ORM
https://book.cakephp.org/5/ja/orm.html

テーブルオブジェクト
https://book.cakephp.org/5/ja/orm/table-objects.html

エンティティー
https://book.cakephp.org/5/ja/orm/entities.html

以下、コントローラからの利用例を中心に記載。

主キーからfind

$item = $this->Items->get($id);

空のエンティティの作成

$item = $this->Items->newEmptyEntity();

patchEntity

$item = $this->Items->newEmptyEntity();
$item = $this->Items->patchEntity($item, $this->request->getData());

生SQLの実行

use Cake\Datasource\ConnectionManager;
:
$conn = ConnectionManager::get('default');
$results = $conn->execute($sql, $params)->fetchAll('assoc');  // assoc: 結果を連想配列で取得、num: 配列で取得

他のテーブルモデルを使用する

use Cake\ORM\TableRegistry;

class ItemsController extends AppController
{
    public function initialize(): void
    {
        parent::initialize();
        $this->Samples = TableRegistry::getTableLocator()->get('Samples');
    }
    public function sample(): void
    {
        $item = $this->Items->newEmptyEntity();
        $sample = $this->Samples->newEmptyEntity();  // 別のモデルも使用可能
        :
    }
}

ビューヘルパー

ビューヘルパーからリクエスト 及び セッションオブジェクトへのアクセス

    $request = $this->_View->getRequest();
    $queries  = $request->getQuery();
    $session_value = $request->getSession()->read('session_value');

コントローラでセットした変数をビューヘルパーから取得する

コントローラ側

    $this->set("testvar", "test1234");

ビューヘルパ側

    $testvar = $this->_View->get('testvar');

バッチ

ComponentRegistry を引数にしてインスタンス生成する事で、バッチからもコンポーネントを利用する事が可能。

namespace App\Command;

use Cake\Command\Command;
use Cake\Console\Arguments;
use Cake\Console\ConsoleIo;
use Cake\Console\ConsoleOptionParser;
use Cake\Controller\ComponentRegistry;

use App\Controller\Component\SampleComponent;

/**
* サンプルバッチ.
*/
class SampleCommand extends Command
{
    public function execute(Arguments $args, ConsoleIo $io)
    {
        // 引数の取得
        $arg1 = $args->getArgumentAt(0);

        // コンポーネントの利用
        // (空の ComponentRegistry を引数にしてコンポーネントインスタンス生成が可能)
        $registry = new ComponentRegistry();
        $component = new SampleComponent($registry);
        component->sampleMethod($arg1);
    }
}

実行

bin/cake sample バッチ引数

その他

依存性の注入(DI)

TODO:

環境の切り替え

TODO:

トップ   差分 バックアップ リロード   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2025-07-20 (日) 02:34:48 (138d)