下記のように公式の解説が充実していますが、途中で結構とまどってしまいました。
ここではフレームワークの詳しい解説は抜きにして、チュートリアルで作るブックマークアプリの作業手順とスクリーンショットを淡々と記録しています。
私と同じ環境ならば、本文に従って進めることでブックマークアプリができあがるはずです。
環境
- Windows 10
- CakePHP 3.4.1
- XAMPP 7.1.1 / PHP 7.1.1 (導入済み)
- Composer 1.3.2 (Windows用インストーラで導入済み)
- Webサーバー: XAMPPのApacheを使用
- DB: XAMPPのMySQLを使用
インストール
注意: intl拡張を有効にする
公式解説にもあるように、XAMPPではphp.iniの下記の行のコメントアウトを解除しなければなりません。
- ;extension=php_intl.dll
+ extension=php_intl.dll
これを忘れると、下記のようにインストールが失敗していしまいます。
「lib-icuが必要だ」と警告されます。
>composer self-update && composer create-project --prefer-dist cakephp/app my_cake3_test
You are already using composer version 1.3.2 (stable channel).
Installing cakephp/app (3.4.0)
- Installing cakephp/app (3.4.0) Downloading: 100%
Created project in my_cake3_test
Loading composer repositories with package information
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.
Problem 1
- cakephp/cakephp 3.4.1 requires lib-icu >=4.8 -> the requested linked library icu has the wrong version installed or is missing from your system, make sure to have the extension providing it.
- cakephp/cakephp 3.4.0 requires lib-icu >=4.8 -> the requested linked library icu has the wrong version installed or is missing from your system, make sure to have the extension providing it.
- Installation request for cakephp/cakephp 3.4.* -> satisfiable by cakephp/cakephp[3.4.0, 3.4.1].
Composerでインストール
intl拡張を有効にすれば、インストールは下記のように滞りなく進みます。
最後に、フォルダのパーミッション設定について尋ねられます。
y
を押して許可します。
>composer self-update && composer create-project --prefer-dist cakephp/app cake3_test
(省略)
Set Folder Permissions ? (Default to Y) [Y,n]?
下の画像のようなCakePHPのホーム画面が表示されれば、インストールは成功です。
(ちなみに、私の場合はApacheのドキュメントルートの下の"cake3/"にインストールしたので、URLはhttp://localhost/cake3/cake3_test
となります)
なお、データベースに接続できないと警告されますが、これは次章で設定するのでそのままで構いません。
データベースの準備
データベースとテーブルを作る
phpMyAdminで新しいデータベースを作り、下記で紹介されているSQLを貼り付けて実行します。
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
email VARCHAR(255) NOT NULL,
password VARCHAR(255) NOT NULL,
created DATETIME,
modified DATETIME
);
CREATE TABLE bookmarks (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
title VARCHAR(50),
description TEXT,
url TEXT,
created DATETIME,
modified DATETIME,
FOREIGN KEY user_key (user_id) REFERENCES users(id)
);
CREATE TABLE tags (
id INT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(255),
created DATETIME,
modified DATETIME,
UNIQUE KEY (title)
);
CREATE TABLE bookmarks_tags (
bookmark_id INT NOT NULL,
tag_id INT NOT NULL,
PRIMARY KEY (bookmark_id, tag_id),
FOREIGN KEY tag_key(tag_id) REFERENCES tags(id),
FOREIGN KEY bookmark_key(bookmark_id) REFERENCES bookmarks(id)
);
今回はDB名は「cake3_test」としました。
下記のようにテーブルが4つ作成されれば成功です。
データベースの接続設定をする
公式解説に従ってapp.phpを修正します。
phpMyAdminがデフォルトのままなら、username
とpassword
は下記のようにします。
'default' => [
'className' => 'Cake\Database\Connection',
'driver' => 'Cake\Database\Driver\Mysql',
'persistent' => false,
'host' => 'localhost',
+ 'username' => 'root',
+ 'password' => '',
'database' => 'cake3_test',
'encoding' => 'utf8',
'timezone' => 'UTC',
'cacheMetadata' => true,
],
ホーム画面を更新して、下記のようにDB接続が有効になっていれば成功です。
Scaffoldコードを生成する
bakeのインストール
まず、下記に従ってアプリフォルダ内にbakeをインストールします。
>composer require --dev cakephp/bake:~1.0
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 0 installs, 1 update, 0 removals
- Updating cakephp/bake (1.2.14 => 1.3.0) Downloading: 100%
Writing lock file
Generating autoload files
> Cake\Composer\Installer\PluginInstaller::postAutoloadDump
コードを生成する
下記に従い、スラッシュをバックスラッシュに替えた上でコマンドを実行します。
bin\cake bake all users
bin\cake bake all bookmarks
bin\cake bake all tags
下記のように末尾で「Bake All complete.」と表示されれば成功です。
>bin\cake bake all users
Welcome to CakePHP v3.4.1 Console
(省略)
Bake All complete.
各ページの表示を確認する
ホーム画面のURLに/users
, /bookmarks
, /tags
をそれぞれ追加して、下記のような画面が表示されれば成功です。
(私の場合はhttp://localhost/cake3/cake3_test/users
)
パスワードのハッシュ化
ハッシュ化しないとどうなるか
まず、ハッシュ化しないとどうなるかを確認します。
http://localhost/cake3/cake3_test/users
でユーザーを作成する際に、パスワードをabcd1234
とします。
すると、アプリでもphpMyAdminでも、パスワードが平文のままであることが分かります。
ハッシュ化する
下記に従って、src\Model\Entity\User.php
にコードを追加します。
<?php
namespace App\Model\Entity;
+ use Cake\Auth\DefaultPasswordHasher;
use Cake\ORM\Entity;
class User extends Entity
{
(省略)
+ /**
+ * パスワードのハッシュ化
+ */
+ protected function _setPassword($value)
+ {
+ $hasher = new DefaultPasswordHasher();
+ return $hasher->hash($value);
+ }
なお、_setPassword
というメソッド名は下記に基づくようです。
アクセサーは _get + フィールド名のキャメルケースという命名ルールを使います。
ハッシュ化を確認する
もう一度パスワードをabcd1234
で保存すると、今度は暗号化されているはずです。
タグによる検索機能の追加
ルーティングを追加
下記に従って、config/routes.php
に追記します。
Router::defaultRouteClass(DashedRoute::class);
+ // 新しいルートを tagged アクションのために追加します。
+ // 末尾の `*` は、渡された引数を持っていることを
+ // CakePHP に伝えます。
+ Router::scope(
+ '/bookmarks',
+ ['controller' => 'Bookmarks'],
+ function ($routes) {
+ $routes->connect('/tagged/*', ['action' => 'tags']);
+ }
+ );
Router::scope('/', function (RouteBuilder $routes) {
- 関連情報: Cookbook | ルーティング
この状態でhttp://localhost/cake3/cake3_test/bookmarks/tagged
にアクセスすると、下記のような警告が表示されます。
tagsアクションが存在しないこと、そしてそれをどこで定義すればいいかを丁寧に教えてくれています。
これには感心しました。
tagsアクションを追加
公式解説と先程の警告に従って、src\Controller\BookmarksController.php
にコードを追加します。
class BookmarksController extends AppController
{
+ /**
+ * タグ検索用のメソッド
+ */
+ public function tags()
+ {
+ // CakePHP によって提供された 'pass' キーは全ての
+ // リクエストにある渡された URL のパスセグメントです。
+ $tags = $this->request->param('pass');
+ // タグ付きのブックマークを探すために BookmarksTable を使用
+ $bookmarks = $this->Bookmarks->find('tagged', [
+ 'tags' => $tags
+ ]);
+ // ビューテンプレートに変数を渡します
+ $this->set([
+ 'bookmarks' => $bookmarks,
+ 'tags' => $tags
+ ]);
+ }
ここで画面を更新すると、今度は「tagged」という名のFinderメソッドが存在しないことを教えてくれます。
Finderメソッドの作成
公式解説と先程の警告に従って、src\Model\Table\BookmarksTable.php
にコードを追加します。
class BookmarksTable extends Table
{
+ // $query 引数は、クエリービルダーのインスタンスです。
+ // $options 配列には、コントローラのアクション中で find('tagged') に渡した
+ // 'tag' オプションが含まれます。
+ public function findTagged(Query $query, array $options)
+ {
+ $bookmarks = $this->find()
+ ->select(['id', 'url', 'title', 'description']);
+ if (empty($options['tags'])) {
+ $bookmarks->leftJoinWith('Tags', function ($q) {
+ return $q->where(['Tags.title IS ' => null]);
+ });
+ } else {
+ $bookmarks->innerJoinWith('Tags', function ($q) use ($options) {
+ return $q->where(['Tags.title IN' => $options['tags']]);
+ });
+ }
+ return $bookmarks->group(['Bookmarks.id']);
+ }
ここで画面を更新すると、今度はビューファイルがないと警告されます。
ビューの作成
公式解説と先程の警告に従って、src\Template\Bookmarks
内に新たにtags.ctp
を作成します。
<h1>
Bookmarks tagged with
<?= $this->Text->toList(h($tags)) ?>
</h1>
<section>
<?php foreach ($bookmarks as $bookmark): ?>
<article>
<!-- Use the HtmlHelper to create a link -->
<h4><?= $this->Html->link($bookmark->title, $bookmark->url) ?></h4>
<small><?= h($bookmark->url) ?></small>
<!-- Use the TextHelper to format text -->
<?= $this->Text->autoParagraph(h($bookmark->description)) ?>
</article>
<?php endforeach; ?>
</section>
ここで画面を更新すると、ようやく警告のない状態になります。
タグ検索の動作確認
テストのため、Bookmarksで「Qiita」と「GitHub」を、Tagsで「プログラマ向け」を作成して、タグをブックマークに関連させます。
その上でhttp://localhost/cake3/cake3_test/bookmarks/tagged/プログラマ向け
にアクセスすると、下記のように表示されるはずです。
これで、チュートリアル前編まで完了しました。