CakePHPで最初の1ページを作成する

ページを作成する1

以下のパスでアクセスしたときに何らかの文字を表示するページを作成します。

/test/index

ルーティング

ルーティングの設定ファイルはこれ。

cake/config/routes.php

ルーティングはアクセスパスとそのアクセスパスに紐付けられたコントローラやその振る舞いを設定します。最近何でもかんでもルーティングの設定でできてしまう(プチコントローラみたいなものも作れる)ので、便利は便利ですが何でもかんでもここでやると後で気持ち悪いので、できるだけルーティングするだけに心がけましょう。(しかしもともこもない話しですが、ルーティングを設定しなくてもCakePHPは動きます。)
ルーティングには、

  • 静的なルーティング
  • 動的なルーティング

があります。

静的なルーティング

結果から言えばscopeを使いましょう。scopeは‘routing scopes’とよばれているらしいです。

Router::scope('/', function ($routes) {
....

は/というアクセスパスにアクセスするとどんな挙動をするのかを定義しています。scopeメソッドは無名関数でその中身を定義できて、そのパスを継承します。

Router::scope('/', function ($routes) {
....
$routes->connect('/test/index', ['controller' => 'Test', 'action' => 'index']);

この設定は、/test/indexにアクセスがあった際には、TestControllerのindexメソッドが起動するという挙動を定義しています。クラスのメソッドのことをアクションと呼ぶのやめてほしいです。

コントローラをつくる

これすなわち、

cake/src/ControllerTestController.php

にあるコントローラを見にいきます。なのでここにコントローラを作成してあげます。コマンドがないのが残念です。
中身は、

<?php

namespace App\Controller;

use Cake\Core\Configure;
use Cake\Network\Exception\NotFoundException;
use Cake\View\Exception\MissingTemplateException;

class TestController extends AppController
{
public function index()
{
//何もいらない。
}
}


明示的にviewを指定したい今日この頃ですが、次項にあるようにviewも自動的に読み込みにいきます。便利といえば便利。

viewをつくる

これ、自動的に、

cake/src/Template/Test/index.ctp

をテンプレートとして見にいくような仕組みになっております。

cake/src/Template/コントローラ名/アクション名(メソッド名).ctp

このctpテンプレートには、普通にHTMLを書いてゆきます。ちなみに内部的にはwebrootにマッチングしているので、CSSや画像はwebrootに置き、webrootから呼び出します。

コントローラから値を渡す

ここまではhtmlをそのまま書いてしまうのとなんら変わりがないので、viewに動的な値を渡してみます。viewに値を渡すには、コントローラの最後で、

$this->set('foo', 'bar');

を使います。

<?php

namespace App\Controller;

use Cake\Core\Configure;
use Cake\Network\Exception\NotFoundException;
use Cake\View\Exception\MissingTemplateException;

class TestController extends AppController
{
public function index()
{
$this->set('foo', 'bar'); //値を渡す
}
}


テンプレートでは普通のPHPのように受け取ります。

<?php echo $foo; ?>

配列や連想配列も同様の方法で受け渡すことができます。ちなみにCakeは勝手にエスケープしてくれないのでh() 関数でエスケープする必要あり。

<?php echo h($foo); ?>

基本エスケープしておけば問題ないです。というか不親切。エスケープしないときだけxh()みたいな関数使うようにしてほしい。

ページを作成する2

以下のパスでアクセスしたときに何らかの文字を表示するページを作成します。

/test/*

このパスは、/test/100とか/test/120とかいうものの他にも/test/hogehogeとパスの*をパラメータとして複数のパスにマッチするようなものを想定しています。/test/2015-12-01とかもそう。

動的なルーティング

ルーティングの設定ファイルは前回説明したので割愛。動的なルーティングの方法の説明に入ります。


Router::scope('/', function ($routes) {
....
$routes->connect('/test/index', ['controller' => 'Test', 'action' => 'index']); //静的なルーティング
$routes->connect('/test/*', ['controller' => 'Test', 'action' => 'dynamic']); //動的なルーティング

アスタリスクを使っています。感のいい人なら気が付いていると思いますが正規表現が使えます。
ただアスタリスクは何でもかんでもOKなので、実践的には非常に使いづらいです。なので値が取得できるようにルーティングします。

$routes->connect('/test/:id', ['controller' => 'Test', 'action' => 'dynamic'], ['id' => '\d+']);

例として/test/以降の文字列をとりあえずは数字に限定しておきましょう。(チュートリアル通り)しかし、どんな文字列も許容する場合は、

$routes->connect('/test/:id', ['controller' => 'Test', 'action' => 'dynamic'], ['id' => '.*']);

という書き方ができます。が、ここではそれが問題ではなく、:idという部分です。/test/:idとすることで:idに相当する部分が取り出せます。コントローラ中で、

debug($this->request->params);

で取り出すことができます。
任意のアクセスパスは情報としてコントローラに渡されてそれを利用できます。/test/100とした場合にはidが100番目のDBレコードを呼び出して表示したりするわけです。

[
'plugin' => null,
'controller' => 'Test',
'action' => 'dynamic',
'_ext' => null,
'pass' => [],
'id' => 'hogehogehoge',
'isAjax' => false
]

動的なルーティングの場合のコントローラ

特に問題なく普通にかけばいいです。

public function dynamic()
{
debug($this->request->params);
$this->set('id', $this->request->params['id']);
}

各パラメータを受け取って、viewに送信できます。viewではコントローラからそのまま値を受け取ればいいだけです。

<?php echo $id; ?>

dynamic
ちなみにこの状況で、静的なページとして作成した/text/indexにアクセスすると、複数のページを処理する/test/との兼ね合いはどうなるのか?ということになるかと思いますが、静的ページとして設定したルーティングはそれはそれできちんと独立していました。なので、/test/は/test/index以外のページを受け付けるという仕組みになっているようです。(あたりまえか。)