Edited at

CakePHP3ハンズオン用

More than 1 year has passed since last update.


はじめに

このハンズオンは、次の宿題をやった人を前提にしています。

ひよこソン宿題 - Qiita

上記宿題をしていなくても問題ありませんが、次の点は注意してください。



  • XAMPPがインストールされ、Apache, MySQLが起動している前提で説明する。


  • fuga/index.phpと記述した時は、XAMPPインストールフォルダ配下のhtdocsフォルダの中のという前提で説明する。

  • 確認は、ブラウザでhttp://localhost/fuga/index.phpのようにアクセスして確認する前提で説明する。

  • 最後の方で、Bootstrapを使う。

  • 最後の方で、jQueryを使う。


PHPの基本、参考サイト

なんといってもまずは本家を参照すべし。

PHP マニュアル

ある程度感じがつかめたら、

PHP: The Right Way で正しいとされるやり方を知っておく。

参考:CakePHPのコーディング規約

以下、本家サイトからの引用で主な書き方を紹介。


絶対マスターしよう


コメント

echo 'テストです'; // C++型の単一行用のコメント

/* 複数行用のコメント
もう一行分のコメント */

echo 'もうひとつのテストです';
echo '最後のテストです'; # シェル型の単一行用のコメント


文字列(結合と式展開)

var $result = "foo" . "bar";

echo "Result is {$result}"; // Result is foobar


出力

echo "Hello";

echo $result;
$a = array('apple', 'orange', 'grape');// 配列
print_r($a);
$results = print_r($a, true);// 変数に入れられる
var_dump($a);


シングルクォート内の文字列

シングルクォートで囲まれた文字列では式展開されない

$str = "123";

echo "$str"; // 123
echo '$str'; // $str
echo "\n"; // 改行
echo '\n'; // \n


演習

hello/index.phpを作成し、Hello, PHPと表示される画面を作成する。

できたら、上記を参考に色々試してみる。


関数

function makecoffee($type = "cappuccino") {

return "Making a cup of $type.\n";
}
echo makecoffee("espresso");


配列とハッシュ

$array = array(

"foo" => "bar",
"bar" => "foo",
);

// PHP 5.4 ではこのようにも書けます
$array = [
"foo" => "bar",
"bar" => "foo",
];

// 数値添字配列でキーを省略した書き方
$array = array("foo", "bar", "hello", "world");

$array = ["foo", "bar", "hello", "world"];

配列からリストに。

$info = array('コーヒー', '茶色', 'カフェイン');

list($drink, $color, $power) = $info;

範囲指定で配列に。

// array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)

foreach (range(0, 12) as $number) {
echo $number;
}

配列をカンマで連結して文字列に。

$array = array('lastname', 'email', 'phone');

$comma_separated = implode(",", $array);
echo $comma_separated; // lastname,email,phone


演習

fizzbuzz/index.phpを作成し、1から100まででFizzBuzzが表示される画面を作成する。

ループや分岐は以下参考。

http://php.net/manual/ja/language.control-structures.php

できたら、関数、配列、ハッシュをあえて使ってやってみる。

ちなみに、CakePHPでは配列、ハッシュとforeachを頻繁に使うので、慣れておくこと。


理解はしておこう


クラス

class SimpleClass {

// プロパティの宣言
public $var = 'a default value';

// メソッドの宣言
public function displayVar() {
echo $this->var;
}
}


コンストラクタ

class BaseClass {

function __construct() {
print "In BaseClass constructor\n";
}
}

class SubClass extends BaseClass {
function __construct() {
parent::__construct();
print "In SubClass constructor\n";
}
}

class OtherSubClass extends BaseClass {
// BaseClass のコンストラクタを継承します
}

// In BaseClass constructor
$obj = new BaseClass();

// In BaseClass constructor
// In SubClass constructor
$obj = new SubClass();

// In BaseClass constructor
$obj = new OtherSubClass();


クラス継承

class ExtendClass extends SimpleClass {

// 親クラスのメソッドを再定義
function displayVar() {
echo "Extending class\n";
parent::displayVar();
}
}

$extended = new ExtendClass();
$extended->displayVar();


CakePHP3インストールと設定

参照:http://book.cakephp.org/3.0/en/installation.html

最初にcomposer(phpのライブラリ管理システム)をインストールする。

curl -s https://getcomposer.org/installer | php

composerのインストールといっても、上記コマンドで、今いるディレクトリにcomposer.pharというファイルが落ちてくるだけ。

これを使って、通常は自分がインストールしたいライブラリ情報を記入したcomposer.jsonファイルを同じ階層において、

php composer.phar install

とすることでライブラリをインストールする。

composer.jsonの例。

{

"require": {
"monolog/monolog": "1.2.*"
}
}

composerについて詳しく知りたい方はこちらから。composer

*注)Macの人はmv composer.phar /usr/local/bin/composerとしておけば、php composer.phar部分をcomposerに変えられるし、パスを意識しないでいいので、おすすめ。

OAuthエラー対応参考URL

http://qiita.com/fivestar/items/fc15e0bb379c791ff6b2

が、ここでは

php composer.phar create-project --prefer-dist -s dev cakephp/app [app_name]

とする。[app_name]のところは自分で考えた名前を入れる。

上記コマンドを実行すると[app_name]ディレクトリが作られて、その中にCakePHPが設置されている。

5分くらい時間がかかるので注意。

注)PHP Fatal error: Allowed memory size of XXXXXX bytes exhausted <...>のようなエラーがでたら、

次のコマンドにする(詳細)。

bash

php -d memory_limit=-1 composer.phar create-project --prefer-dist -s dev cakephp/app [app_name]



*注)ここで、OSXユーザーの場合は、logsとtmpフォルダーに書き込み権限を与えておくのを忘れずに。

chmod -R 777 tmp

chmod -R 777 logs

続いて

 bin/cake server

として開発用サーバーを起動する。

Welcome to CakePHP v3.0.0-beta3 Console

---------------------------------------------------------------
App : src
Path: C:\Users\yourname\project\src\
DocumentRoot: C:\Users\yourname\project\webroot
---------------------------------------------------------------
built-in server is running in http://localhost:8765/
You can exit with `CTRL-C`

というようなメッセージが出るので、ブラウザから

http://localhost:8765/

に接続して、

cakephp3.png

というような画面になればOKである。この画面になにがしかのエラーが出ている場合はそれを修正する。

サーバーを停止するときはコントロールキーを押しながらCを押す。

恐らくは以下のメッセージがでていると思うので、DBの設定を行う。

CakePHP is NOT able to connect to the database.

vim config/app.php

として、エディタを起動し、以下のデータベース接続情報を編集する。

testを書く人はテスト用データベース接続情報も入れておくとよい。


config/app.php

    'Datasources' => [

'default' => [
'className' => 'Cake\Database\Connection',
'driver' => 'Cake\Database\Driver\Mysql',
'persistent' => false,
'host' => 'localhost',
/*
* CakePHP will use the default DB port based on the driver selected
* MySQL on MAMP uses port 8889, MAMP users will want to uncomment
* the following line and set the port accordingly
*/

//'port' => 'nonstandard_port_number',
'username' => 'my_app',
'password' => 'secret',
'database' => 'my_app',
'encoding' => 'utf8',
'timezone' => 'UTC',
'cacheMetadata' => true,

/*
* Set identifier quoting to true if you are using reserved words or
* special characters in your table or column names. Enabling this
* setting will result in queries built using the Query Builder having
* identifiers quoted when creating SQL. It should be noted that this
* decreases performance because each query needs to be traversed and
* manipulated before being executed.
*/

'quoteIdentifiers' => false,

/*
* During development, if using MySQL < 5.6, uncommenting the
* following line could boost the speed at which schema metadata is
* fetched from the database. It can also be set directly with the
* mysql configuration directive 'innodb_stats_on_metadata = 0'
* which is the recommended value in production environments
*/

//'init' => ['SET GLOBAL innodb_stats_on_metadata = 0'],
],



MySQL

データベースの操作にはphpMyAdminを使う方法があるが、動作が重いので、推奨しない。

XAMPPでインストールした場合は C:\xampp\mysql\bin 以下にある実行ファイルが実体なので、ここにパスを通しておけばよい。

(システム→システムの詳細設定→環境変数→Path→編集)

コマンドラインから

mysql -u root -p

パスワードを設定してない場合は、

mysql -u root

でDBに入れるので

データベース作成

CREATE DATABASE sample_db DEFAULT CHARACTER SET utf8;

ユーザー設定

GRANT ALL ON sample_db.* TO myuser@localhost IDENTIFIED BY 'password';

使用するデータベースを指定

use sample_db

あとは使いたいsqlを流せばよい。

参考:http://xref.jp/database

終了するときは

\q

もしくは

quit


演習

演習用のデータベースを作成し、接続用のユーザーを設定し、CakePHPの設定に記述して、CakePHPから接続できることを確認してみましょう。


テーブル作成

例えばブログの記事を保存するテーブルは以下のようなsqlになる。

CREATE TABLE articles (

id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(50),
body TEXT,
created DATETIME DEFAULT NULL,
modified DATETIME DEFAULT NULL
);

命名規約:http://book.cakephp.org/3.0/en/intro/conventions.html


  • テーブル名は英単語の複数形で、アンダースコアを用いる。

  • テーブルには必ずidという名前のプライマリーキーを持たせる。

  • 2つ以上の単語を使うフィールド名はアンダースコアで連結:first_name。


  • 外部キーはその関連する「テーブル名の単数形_id」とする。


  • created と modified はお約束で、登録日時と更新日時が自動でインサート(アップデート)される。



演習

CREATE TABLE文を作成し、演習用のデータベースにテーブルを作成してみましょう。

ブログの記事とコメントなど、思いついたものをテーブルにしてみます。


BakeとMVC

bakeコマンドを使って自動で、MVC(モデル、ビュー、コントローラ)を作成します。

今回articlesテーブルが作ってあるので、それについて操作する。

コマンドラインから、

bin/cake bake model Articles

と打つ。

Welcome to CakePHP v3.0.0-beta3 Console

---------------------------------------------------------------
App : src
Path: C:\Users\yourname\project\src\
---------------------------------------------------------------
One moment while associations are detected.

Baking table class for Articles...
Baking entity class for Article...
Baking test fixture for Articles...
Baking test case for App\Model\Table\ArticlesTable ...

というような表示が出て、モデルに必要なファイルが自動生成される。

アソシエーションについては現時点のbakeではuser_idなどの命名規則に従ったフィールド名を元に自動で生成されるので、モデル作成後必ずソースを確認すること。

続いて、コントローラを作成する。

bin/cake bake controller Articles

Welcome to CakePHP v3.0.0-beta3 Console

---------------------------------------------------------------
App : src
Path: C:\Users\yourname\project\src\
---------------------------------------------------------------

Baking controller class for Articles...
Baking test case for App\Controller\ArticlesController ...

コントローラが作られる。続いてビューも同様に。

bin/cake bake view Articles

ブラウザから生成物を確認する。

http://localhost:8765/articles/

登録、編集、削除、一覧ができるようになっている。

この自動生成されたファイルを元に作っていくので、ざっくり中身を確認しておく。


演習

前項で作成したテーブルに関して、bakeコマンドでモデル、コントローラ、ビューを作成し、ブラウザから確認してみましょう。


デバッグ

http://localhost:8765/articles/add

登録画面(New Article)からなにかデータを登録した後、一覧画面からViewをクリックし、画面右下にあるCakePHPアイコンをクリックしてみる。

cakephp3-2.png

ブラウザの最下部に黄色のメニューバーが表示されるので、クリックして内容を確認する。

Sql Logではこのページで実行されたクエリーを確認できる。

変数に何が入っているのか手っ取り早く確認したい時は、

debug($article);

のように書けばよい。

debug($query = $this->Articles->find());

のように書けばこのfindメソッドで生成されるSQLも確認できる。

デバッグログ(ファイル)に出力したい時は、

以下を追加しておいて、

use Cake\Log\Log;

出力したい場所で以下のように書く。

Log::write('debug', print_r($article, true));

例えば以下のようにコントローラのviewメソッドにデバッグログ書き出しを仕込んでみると、


src/Controller/ArticlesController.php

    public function view($id = null) {

$article = $this->Articles->get($id, [
'contain' => []
]);
Log::write('debug', print_r($article, true));
$this->set('article', $article);
}

ビューにsetされている$articleはオブジェクトになっていることが分かる。


演習

前項で自動生成されたソースを見て、変数をdebugしてみましょう。


select

ここでCakePHP3のモデルについての説明。

$query = $this->Articles->find();

こういう書き方でクエリーオブジェクトなるものが作られる。

(まだSQLは実行されない)

で、

$query->all();

と書けばSQLが実行される。

つまりこれでワンセット。

$query = $this->Articles->find();

$query->all();

で、以下のように書けば

$results = $query->all();

foreach ($results as $result) {
echo $result->id;
echo $result->created;
}

とすれば取り出せる。$resultsがビューに渡されて、ビュー側でにforeach以下で値を取り出しているということ。

$query = $this->Reports->find();

foreach ($query as $result) {
echo $result->id;
echo $result->created;
}

こう書いても結果はおんなじ。all()は省略可能ってことです。

その他、クエリーのコンディション等はメソッドチェーンで記述する。以下を参照のこと。

参考:http://book.cakephp.org/3.0/en/orm/query-builder.html#selecting-data


演習

参考ページをみながら、独自のクエリーを実行するメソッドを作ってみましょう。


insert delete update

Bakeで作成したコントローラのメソッドadd, delete, edit を参考にしてください。


Form

フォームヘルパーは以下参照:

http://book.cakephp.org/3.0/en/views/helpers/form.html

大きな変更はないが、phpの配列の書き方が変わったので注意のこと。

例えば以下のようなaddフォームにBootstrapのform-controlクラスを追加する場合は、


src/Template/Articles/add.ctp

    <?= $this->Form->create($article); ?>

<fieldset>
<legend><?= __('Add Article') ?></legend>
<?php
echo $this->Form->input('title');
echo $this->Form->input('body');
?>
</fieldset>
<?= $this->Form->button(__('Submit')) ?>
<?= $this->Form->end() ?>

以下のようにすればよい。

echo $this->Form->input('title', ['class' => 'form-control']);

出力結果

<input type="text" id="title" maxlength="50" class="form-control" name="title">


演習

Bootstrapを組みこんで、スタイルを適用してみましょう。


ビュー

BootstrapやjQueryを使う場合はLayoutのdefault.ctpに以下のように書いて、webroot以下のフォルダーにファイルを置けばよい。

    <?= $this->Html->css('bootstrap.min') ?>

<?= $this->Html->script('bootstrap.min') ?>

詳しくは、

http://book.cakephp.org/3.0/en/views.html

レイアウトを使わない時はコントローラに

$this->layout = false;

そもそもビューを使わない時は

$this->autoRender = false;


演習

ビューを使わずに、たんなるJSONデータを返すようなメソッドを作ってみましょう。

(Web APIとして利用できるので便利。)

答え:

https://gist.github.com/uedatakeshi/4856c087d105b25cc0f4


参考サイト

http://book.cakephp.org/3.0/en/contents.html

http://php.net/