CakePHP 新規プロジェクトの動作確認
公開日:2018-05-30 更新日:2020-09-20
[CakePHP3]
1. 概要
作成した CakePHP の新規プロジェクトを使って、試行錯誤をしながら CakePHP の動作確認を行います。
2. フォルダの確認
前回 Composer で作成したプロジェクトのフォルダを確認します。
1. bin
本家のサイトに書いてありますが、
以下のコマンドを実行すると、簡易Webサーバーが起動します。
my_app専用のため、他のアプリケーションにアクセスすることはできません。
以下のコマンドを実行すると、簡易Webサーバーが起動します。
cd C:\pleiades\xampp\htdocs\my_app\bin
cake server
起動後に http://localhost:8765/ にアクセスすると、my_app の最初の画面にアクセスできます。my_app専用のため、他のアプリケーションにアクセスすることはできません。
2. config
- app.php
公開ディレクトリ、DB、文字コード、タイムゾーンなどのアプリケーションの基本となる値を設定しています。 - paths.php
各ディレクトリのパスを define で定義しています。 - requirements.php
PHPのバージョンの確認と、intl と mbstring が有効になっているかをチェックしています。
intl が反映されていない時のエラーは、ここが出していたようです。 - routes.php
URL とコントローラーの関連付けを行っています。
3. src
config/paths.php で定義されていますが、src がアプリケーション用のフォルダのようです。
中には Controller、Model、View が入っています。
但し、View の中身はほぼ空で、実際に画面に表示されているのは、src/Template 配下のファイルのようです。
src/Template 配下には、最初の画面の home.ctp や、ヘッダーとフッターを含んだレイアウトファイルが入っています。
中には Controller、Model、View が入っています。
但し、View の中身はほぼ空で、実際に画面に表示されているのは、src/Template 配下のファイルのようです。
src/Template 配下には、最初の画面の home.ctp や、ヘッダーとフッターを含んだレイアウトファイルが入っています。
4. vendor
ライブラリがたくさん入っています。
CakePHP は、様々なライブラリを使用しているようです。
CakePHP は、様々なライブラリを使用しているようです。
5. webroot
フォルダ名の通り、Web のルートになるフォルダです。
css、js、img が配置してあります。
最初に表示された画面のソースを表示して、css の読み込み部分を確認すると、
/my_app/css/style.css を見るようになっていました。
webroot がパスから消えていますが、
これは my_app/.htaccess で、webroot 配下を見るようにしています。
css、js、img が配置してあります。
最初に表示された画面のソースを表示して、css の読み込み部分を確認すると、
/my_app/css/style.css を見るようになっていました。
webroot がパスから消えていますが、
これは my_app/.htaccess で、webroot 配下を見るようにしています。
3. 最初の画面の確認
1. レイアウトとテンプレート
http://localhost/my_app/ にアクセスして表示される画面を変更してみます。
src/Template/Pages/home.ctp の先頭に、「Test」などを書いて表示してみます。
画面の先頭に「Test」と表示されました。
ソースを表示しても、先頭に出力されています。
src/Template/Layout/default.ctp にレイアウトファイルがありますが、
どうやらこのページはレイアウトを使っていないようです。
home.ctp を上から見ていくと、
試しに true にして画面を表示してみます。
以下のエラーが発生しました。
今度は正常に表示されました。
ダメ元で、$this->layout = 'default'; にしてみます。
すると、1.ctp ではなく、default.ctp が使用されました。1.ctp を削除しても表示されます。
$this->layout には、
レイアウトを使う時はレイアウトファイル名を指定して、
レイアウトを使わない時は、false を設定すれば良さそうです。
$this->layout = false; に戻して、home.ctp の続きを見てみます。
src/Template/Pages/home.ctp の先頭に、「Test」などを書いて表示してみます。
画面の先頭に「Test」と表示されました。
ソースを表示しても、先頭に出力されています。
src/Template/Layout/default.ctp にレイアウトファイルがありますが、
どうやらこのページはレイアウトを使っていないようです。
home.ctp を上から見ていくと、
$this->layout = false;
と書いてありました。これでレイアウトを未使用にしているようです。試しに true にして画面を表示してみます。
以下のエラーが発生しました。
Error: The layout file Layout\1.ctp can not be found or does not exist.
Layout\default.ctp をコピーして 1.ctp を作成し、画面を再表示します。今度は正常に表示されました。
ダメ元で、$this->layout = 'default'; にしてみます。
すると、1.ctp ではなく、default.ctp が使用されました。1.ctp を削除しても表示されます。
$this->layout には、
レイアウトを使う時はレイアウトファイル名を指定して、
レイアウトを使わない時は、false を設定すれば良さそうです。
$this->layout = false; に戻して、home.ctp の続きを見てみます。
2. ヘルパークラス
<?= $this->Html->meta('icon') ?>
<?= $this->Html->css('base.css') ?>
とありました。ブラウザでソースを確認すると、
<link href="/my_app/favicon.ico" type="image/x-icon" rel="shortcut icon"/>
<link rel="stylesheet" href="/my_app/css/base.css"/>
となっていました。css などはファイル名を指定するだけで簡単に読み込めるようです。
試しに、
<?= $this->Html->img('cake.icon.png') ?>
を追記してみます。エラーが出ました。
Warning (512): Method Cake\View\Helper\HtmlHelper::img does not exist [CORE\src\View\Helper.php, line 139]
vendor/cakephp/cakephp/src/View/Helper/HtmlHelper
を確認したところ、どうやらここで変換を行っているようです。
また、img ではなく image のようです。
<?= $this->Html->image('cake.icon.png') ?>
再表示したところ、画像が表示されました。3. コントローラー
src/Controller に、以下の3つのコントローラーが入っています。
・AppController.php
・ErrorController.php
・PagesController.php
PagesController と ErrorController は AppController を継承しています。
PagesController には display() だけ定義してあります。
ブラウザでアクセスすると、このメソッドが呼ばれるようです。
display() の先頭で、var_dump($path); を追加して画面を表示してみます。
home と言う値がどこから出て来たのかわかりませんが、とりあえず display() が呼ばれていることと、
この home が、ビューの home.ctp になることが、なんとなくわかりました。
続いて見ていくと、次のソースが見つかります。
連想配列のキーは変数名で、値は変数の元の値が入ります。
次に生成された連想配列を $this->set() に渡しています。
このメソッドは、PagesController にないため、継承元である AppController を見てみます。
しかし、こちらにもありません。
次は、AppController の継承元の Cake\Controller\Controller を見てみます。
__set() はあるのですが、set() がありません。
ちなみに、
__set() は、マジックメソッドと呼ばれ、定義していないプロパティに値を設定した時に呼ばれます。
__get() は、定義していないプロパティの値を取得した時に呼ばれます。
Controller は extends していないため、親クラスはありません。
次に、trait を使っていないか確認します。
php には trait と言う仕組みがあり、クラスを継承せずにメソッドを追加することができます。
Controller の先頭を見ると、use EventDispatcherTrait; と書いてあり、名前にも Trait と付いています。
どうやら trait を使っているようです。
確認したところ、
ソースのコメントに、テンプレート内で使用する変数を保存すると書いてあります。
set() は、コントローラーからビューに値を渡すためのメソッドのようです。
もう1度 PagesController の display() に戻ってソースを見ます。
最後に $this->render() としています。
ここでビューの表示を行っているようです。
PagesController は、アプリケーション側のフォルダに入っているため、
必要に応じて変更しても問題ありません。
試しに、PagesController を変更してみます。
implode('/', $path) の値を確認すると、home だったため、引数の値を展開して、
変数の値を展開しただけなので、問題なく表示されます。
次に、
src\Template\Pages\test.ctp が見つからないと言うエラーが出ました。
この時、エラー画面の左側の「Cake\Controller\Controller->render」をクリックすると、
エラー箇所のソースが右側に表示されます。
src/Template/Pages\home.ctp をコピーして、test.ctp を作成します。
そして再表示すると、正常に表示されました。
次に、
そして再表示すると、正常に表示されました。
render() には、src/Template/Pages からの相対パスで、拡張子なしのテンプレートファイルを渡せば良さそうです。
ソースを元に戻します。
・AppController.php
・ErrorController.php
・PagesController.php
PagesController と ErrorController は AppController を継承しています。
PagesController には display() だけ定義してあります。
ブラウザでアクセスすると、このメソッドが呼ばれるようです。
display() の先頭で、var_dump($path); を追加して画面を表示してみます。
array(1) { [0]=> string(4) "home" }
と表示されました。home と言う値がどこから出て来たのかわかりませんが、とりあえず display() が呼ばれていることと、
この home が、ビューの home.ctp になることが、なんとなくわかりました。
続いて見ていくと、次のソースが見つかります。
$this->set(compact('page', 'subpage'));
まず compact() で、$page と $subpage を連想配列に変換しています。連想配列のキーは変数名で、値は変数の元の値が入ります。
$map = ["path" => $page, "subpage" => $subpage];
としたのと同じです。次に生成された連想配列を $this->set() に渡しています。
このメソッドは、PagesController にないため、継承元である AppController を見てみます。
しかし、こちらにもありません。
次は、AppController の継承元の Cake\Controller\Controller を見てみます。
__set() はあるのですが、set() がありません。
ちなみに、
__set() は、マジックメソッドと呼ばれ、定義していないプロパティに値を設定した時に呼ばれます。
__get() は、定義していないプロパティの値を取得した時に呼ばれます。
Controller は extends していないため、親クラスはありません。
次に、trait を使っていないか確認します。
php には trait と言う仕組みがあり、クラスを継承せずにメソッドを追加することができます。
Controller の先頭を見ると、use EventDispatcherTrait; と書いてあり、名前にも Trait と付いています。
どうやら trait を使っているようです。
確認したところ、
vendor/cakephp/cakephp/src/View/ViewVarsTrait.php
で定義していました。ソースのコメントに、テンプレート内で使用する変数を保存すると書いてあります。
set() は、コントローラーからビューに値を渡すためのメソッドのようです。
もう1度 PagesController の display() に戻ってソースを見ます。
最後に $this->render() としています。
ここでビューの表示を行っているようです。
PagesController は、アプリケーション側のフォルダに入っているため、
必要に応じて変更しても問題ありません。
試しに、PagesController を変更してみます。
public function display(...$path)
{
$this->render(implode('/', $path));
}
画面を表示すると、今までと変わりなく表示されました。implode('/', $path) の値を確認すると、home だったため、引数の値を展開して、
public function display(...$path)
{
$this->render('home'));
}
として、もう一度実行してみます。変数の値を展開しただけなので、問題なく表示されます。
次に、
public function display(...$path)
{
$this->render('test'));
}
としてみます。src\Template\Pages\test.ctp が見つからないと言うエラーが出ました。
この時、エラー画面の左側の「Cake\Controller\Controller->render」をクリックすると、
エラー箇所のソースが右側に表示されます。
src/Template/Pages\home.ctp をコピーして、test.ctp を作成します。
そして再表示すると、正常に表示されました。
次に、
public function display(...$path)
{
$this->render('test/test');
}
として、Pages 配下に test フォルダを作成して、その中に先ほど作った test.ctp を移動します。そして再表示すると、正常に表示されました。
render() には、src/Template/Pages からの相対パスで、拡張子なしのテンプレートファイルを渡せば良さそうです。
ソースを元に戻します。
4. URLとコントローラーの関連付け
最初にフォルダを確認した時に、config/routes.php で URL とコントローラーの関連付けを行っていたため、もう1度確認してみます。
routes.php 抜粋
routes.php のコメントでだいたいわかりますが、
念のため $routes->connect() の引数を確認してみます。
$routes は RouteBuilder のため、
connect() は以下のようになっていました。
RouteBuilder.php 抜粋
routes.php
2番目の引数に連想配列でコントローラー名、アクション名(メソッド名)、ビュー、
3番目の引数にHTTPのメソッドなどのオプション、
を指定する。
つまり、
http://localhost/my_app/ にアクセスされたら、
Pagesコントローラー の display() を実行して、
home と言うテンプレートを使って画面を表示する、
と言うことになりそうです。
2番目の引数の home だけキーがないため、home を先頭に移動させます。
キーが指定されていない要素をビューと認識しているようです。
試しに、キーがない要素を複数指定してみます。
src/Template/Pages/test/home.ctp
のテンプレートを探しています。
どうやら、キーがない要素だけを action で指定されたメソッドの引数として渡しているようです。
PagesController() の display() の先頭で var_dump($path) をしたところ、
キーがない要素だけの連想配列が渡ってきました。
パスの結合は、display() の中で行っています。
次に、もう片方の connect() を確認します。
/pages/ に反応するようなので、
http://localhost/my_app/pages/test/
にアクセスしてみます。
src/Template/Pages/test.ctp
がないと言うエラーが出ました。
test ではなく home にすると動きそうなため、試しに、
http://localhost/my_app/pages/home/
にアクセスしてみます。
正常に表示されました。
続いて、
http://localhost/my_app/pages/abc/test1/test2/
にアクセスしてみます。
src/Template/Pages/abc/test1/test2.ctp
がないと言われました。
「/pages/*」の「*」の部分が、引数になって、display() に渡っているようです。
var_dump($path)
試しに、routes.php 側の連想配列に値を追加して、
var_dump($path)
今回は、テンプレートファイルのパスを作成するために引数を使用していますが、
データのIDの指定などにも利用できそうです。
routes.php 抜粋
$routes->connect('/', ['controller' => 'Pages', 'action' => 'display', 'home']);
$routes->connect('/pages/*', ['controller' => 'Pages', 'action' => 'display']);
最初に見た時はよくわかりませんでしたが、見覚えのある単語が出てきました。routes.php のコメントでだいたいわかりますが、
念のため $routes->connect() の引数を確認してみます。
$routes は RouteBuilder のため、
vendor/cakephp/cakephp/src/Routing/RouteBuilder.php
を確認します。connect() は以下のようになっていました。
RouteBuilder.php 抜粋
public function connect($route, $defaults = [], array $options = [])
ソースのコメントにサンプルも載っていました。routes.php
$routes->connect('/:controller/:action/*');
$routes->connect('/home-page', ['controller' => 'Pages', 'action' => 'display', 'home']);
$routes->connect(
'/:lang/:controller/:action/:id',
[],
['id' => '[0-9]+', 'lang' => '[a-z]{3}']
$routes->connect('/tasks', ['controller' => 'Tasks', 'action' => 'index', '_method' => 'GET']);
1番目の引数にURL、2番目の引数に連想配列でコントローラー名、アクション名(メソッド名)、ビュー、
3番目の引数にHTTPのメソッドなどのオプション、
を指定する。
つまり、
$routes->connect('/', ['controller' => 'Pages', 'action' => 'display', 'home']);
は、http://localhost/my_app/ にアクセスされたら、
Pagesコントローラー の display() を実行して、
home と言うテンプレートを使って画面を表示する、
と言うことになりそうです。
2番目の引数の home だけキーがないため、home を先頭に移動させます。
$routes->connect('/', ['home', 'controller' => 'Pages', 'action' => 'display']);
正常に動作します。キーが指定されていない要素をビューと認識しているようです。
試しに、キーがない要素を複数指定してみます。
$routes->connect('/', ['test', 'home', 'controller' => 'Pages', 'action' => 'display']);
エラーが出ました。src/Template/Pages/test/home.ctp
のテンプレートを探しています。
どうやら、キーがない要素だけを action で指定されたメソッドの引数として渡しているようです。
PagesController() の display() の先頭で var_dump($path) をしたところ、
キーがない要素だけの連想配列が渡ってきました。
パスの結合は、display() の中で行っています。
次に、もう片方の connect() を確認します。
$routes->connect('/pages/*', ['controller' => 'Pages', 'action' => 'display']);
こちらには home のように、ビューが指定されていません。/pages/ に反応するようなので、
http://localhost/my_app/pages/test/
にアクセスしてみます。
src/Template/Pages/test.ctp
がないと言うエラーが出ました。
test ではなく home にすると動きそうなため、試しに、
http://localhost/my_app/pages/home/
にアクセスしてみます。
正常に表示されました。
続いて、
http://localhost/my_app/pages/abc/test1/test2/
にアクセスしてみます。
src/Template/Pages/abc/test1/test2.ctp
がないと言われました。
「/pages/*」の「*」の部分が、引数になって、display() に渡っているようです。
var_dump($path)
array(3) {
[0]=>
string(3) "abc"
[1]=>
string(5) "test1"
[2]=>
string(5) "test2"
}
試しに、routes.php 側の連想配列に値を追加して、
$routes->connect('/pages/*', ['controller' => 'Pages', 'action' => 'display', 'def1', 'def2']);
もう1度 http://localhost/my_app/pages/abc/test1/test2/ にアクセスしてみます。var_dump($path)
array(5) {
[0]=>
string(4) "def1"
[1]=>
string(4) "def2"
[2]=>
string(3) "abc"
[3]=>
string(5) "test1"
[4]=>
string(5) "test2"
}
最初に定義された引数の後ろに、URLで指定した引数が追加されました。今回は、テンプレートファイルのパスを作成するために引数を使用していますが、
データのIDの指定などにも利用できそうです。
5. コントローラーからビューに値を渡す
home.ctp を見ると $this が使われているため、
var_dump() で $this を出力してみます。
大量に値が出力されました。
下の方に見覚えのある page と subpage が出てきました。
これは PagesController で $this->set(compact('page', 'subpage')); した時の値です。
var_dump($this) 抜粋
var_dump($this->viewVars["page"]);
で、一応コントローラーで設定した値を取得することができました。
しかし、ちょっと不便です。
本家のサイト を確認したところ、
set() で指定した変数は、そのままビューでも使えるそうです。
home.ctp で $page を使ったところ、正しく値が表示されました。
また、home.ctp の先頭で var_dump(get_defined_vars()); を追加して、定義された全ての変数を確認してみます。
var_dump(get_defined_vars()) 抜粋
念のため、PagesController を以下のようにして、
var_dump() で $this を出力してみます。
大量に値が出力されました。
下の方に見覚えのある page と subpage が出てきました。
これは PagesController で $this->set(compact('page', 'subpage')); した時の値です。
var_dump($this) 抜粋
["viewVars"]=>
array(2) {
["page"]=>
string(4) "home"
["subpage"]=>
NULL
}
var_dump($this->viewVars["page"]);
で、一応コントローラーで設定した値を取得することができました。
しかし、ちょっと不便です。
本家のサイト を確認したところ、
set() で指定した変数は、そのままビューでも使えるそうです。
home.ctp で $page を使ったところ、正しく値が表示されました。
また、home.ctp の先頭で var_dump(get_defined_vars()); を追加して、定義された全ての変数を確認してみます。
var_dump(get_defined_vars()) 抜粋
array(4) {
["viewFile"]=>
string(59) "C:\pleiades\xampp\htdocs\my_app\src\Template\Pages\home.ctp"
["dataForView"]=>
array(2) {
["page"]=>
string(4) "home"
["subpage"]=>
NULL
}
["page"]=>
string(4) "home"
["subpage"]=>
NULL
}
基本的には、$this と set() で渡された変数以外は見えないようです。念のため、PagesController を以下のようにして、
$test = "123";
$this->set(compact('page', 'subpage', 'test'));
home.ctp で $test を確認したところ、正常に値が渡ってきました。