このチュートリアルは簡単なブックマークのためのアプリケーション (bookmarker) を作ります。 はじめに CakePHP のインストールを行い、データベースの作成、 そしてアプリケーションを素早く仕上げるための CakePHP が提供するツールを使います。
必要なもの:
データベースサーバー。このチュートリアルでは MySQL サーバーを使います。
データベースを作成するための SQL の知識が必要です。CakePHP は、それを前提としています。
MySQL を使用するとき、 PHP で pdo_mysql
が有効になっていることを確認してください。
基礎的な PHP の知識。
始める前に、最新の PHP バージョンであることを確認してください。
php -v
最低でも PHP 8.1 (CLI) 以上をインストールしてください。 あなたのウェブサーバーの PHP バージョンもまた、8.1 以上でなければなりません。そして、 コマンドラインインターフェイス (CLI) の PHP バージョンと同じバージョンがベストです。 完全なアプリケーションを確認したい場合、 cakephp/bookmarker をチェックアウトしてください。 さあ、はじめましょう!
最も簡単な CakePHP のインストール方法は Composer を使う方法です。Composer は、 ターミナルやコマンドラインプロンプトから CakePHP をインストールするためのシンプルな方法です。 まだ準備ができていない場合、最初に Composer をダウンロードとインストールが必要です。 cURL がインストールされていたら、以下のように実行するのが簡単です。
curl -s https://getcomposer.org/installer | php
もしくは Composer のウェブサイト
から composer.phar
をダウンロードすることができます。
そして、CakePHP アプリケーションのスケルトンを bookmarker ディレクトリーにインストールするために、 インストールディレクトリーからターミナルに以下の行をシンプルにタイプしてください。
php composer.phar create-project --prefer-dist cakephp/app:4.* bookmarker
Composer Windows Installer をダウンロードして実行した場合、インストールディレクトリー (例えば、 C:\wamp\www\dev\cakephp3) からターミナルに以下の行をタイプしてください。
composer self-update && composer create-project --prefer-dist cakephp/app:4.* bookmarker
Composer を使うメリットは、 正しいファイルパーミッションの設定や、 config/app.php ファイルの作成などのように、自動的に完全なセットアップをしてくれることです。
CakePHP をインストールする他の方法があります。 Composer を使いたくない場合、 インストール セクションをご覧ください.
CakePHP のダウンロードやインストール方法にかかわらず、いったんセットアップが完了すると、 ディレクトリー構成は以下のようになります。
/bookmarker
/bin
/config
/logs
/plugins
/src
/tests
/tmp
/vendor
/webroot
.editorconfig
.gitignore
.htaccess
.travis.yml
composer.json
index.php
phpunit.xml.dist
README.md
CakePHP のディレクトリー構造がどのように働くかを学ぶのにいい機会かもしれません。 CakePHP のフォルダー構成 セクションをご覧ください。
デフォルトホームページを確認することで、インストールが正しいことをざっと確かめることができます。 その前に、開発用サーバーを起動する必要があります。
bin/cake server
注釈
Windows では、このコマンドは bin\cake server
(バックスラッシュ) です。
これで、 8765 ポートで PHP のビルトインウェブサーバーが起動します。ウェルカムページを見るために http://localhost:8765 をウェブブラウザーで開いてください。CakePHP がデータベース接続が 可能かどうか以外は、すべての確認事項がチェック済みになるべきです。そうでなければ、PHP 拡張の 追加のインストールやディレクトリーのパーミッション設定が必要かもしれません。
次に、ブックマークアプリケーションのデータベースをセットアップしましょう。
まだセットアップしていない場合、例えば cake_bookmarks
のように、あなたの好きな名前で、
このチュートリアルで使用する空のデータベースを作成してください。必要なテーブルを作成するために、
以下の 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)
);
複合主キーを持つ bookmarks_tags
テーブルにお気づきでしょうか。CakePHP は、
ほぼどこでも複合主キーをサポートします。それは、マルチテナントなアプリケーションの構築が
しやすくなります。
私たちが使用するテーブルやカラムの名前は恣意的ではありませんでした。CakePHP の 命名規則 を使用することによって、CakePHP がより効果的になり、 フレームワークの設定を避けられます。CakePHP はレガシーなデータベーススキーマに対応できるくらい 十分に柔軟ですが、規約に従うことで、時間を節約できます。
次に、どこにデータベースあるか、そしてどうやってテータベースに接続するかを CakePHP に伝えましょう。おそらく、これが何らかの設定が必要となる最初で最後です。
この設定はとても単純です。あなたのセットアップを適用するために config/app.php
ファイルの中の Datasources.default
配列の値を置き換えてください。
完全な設定配列の例は、以下のようになります。
return [
// More configuration above.
'Datasources' => [
'default' => [
'className' => 'Cake\Database\Connection',
'driver' => 'Cake\Database\Driver\Mysql',
'persistent' => false,
'host' => 'localhost',
'username' => 'cakephp',
'password' => 'AngelF00dC4k3~',
'database' => 'cake_bookmarks',
'encoding' => 'utf8',
'timezone' => 'UTC',
'cacheMetadata' => true,
],
],
// More configuration below.
];
1度 config/app.php ファイルを保存して、 'CakePHP is able to connect to the database' がチェック済みであることを確認してください。
注釈
CakePHP のデフォルト設定ファイルは config/app.default.php にあります。
データベースが CakePHP の命名規則に従っているので、 基本的なアプリケーションを 素早く生成するために bake コンソール アプリケーションが使用できます。 コマンドライン上で、以下のコマンドを実行してください。
// Windows 上では、代わりに bin\cake を使用する必要があります。
bin/cake bake all users
bin/cake bake all bookmarks
bin/cake bake all tags
これは、 users、 bookmarks、 tags リソースのためのコントローラー、モデル、ビュー、 それらに対応するテストケース、フィクスチャーを生成します。あなたのサーバーが停止している場合、 再起動して http://localhost:8765/bookmarks に行ってください。
アプリケーションのデータベーステーブルへのデータアクセスを提供する基本的だが機能的な アプリケーションを見てください。1度、ブックマーク一覧を表示して、いくつかの ユーザー、ブックマーク、タグを追加してください。
(http://localhost:8765/users にアクセスして) ユーザーを作成した時、パスワードが平文で保存されることにおそらく気づくでしょう。 これはセキュリティの観点から、とても良くありませんので修正しましょう。
これはまた、CakePHP のモデル層について説明する良い機会です。CakePHP では、
オブジェクトの集合と、異なるクラスの単一オブジェクトを操作する方法を分けてます。
エンティティーの集合は、 Table
クラス内に格納され、1つのレコードに属する機能は、
Entity
クラス内に格納されます。
例えば、パスワードのハッシュ化は、個々のレコードで行われ、エンティティーオブジェクトに この振る舞いを実装します。パスワードがセットされるたびにハッシュ化したいので、 ミューテーターメソッドやセッターメソッドを使います。CakePHP は規約に基づいて、 エンティティーの一つにプロパティーをセットするセッターメソッドを呼びます。 では、パスワードのためのセッターを追加してみましょう。 src/Model/Entity/User.php に 以下を追加してください。
namespace App\Model\Entity;
use Cake\Auth\DefaultPasswordHasher; // この行を追加してください
use Cake\ORM\Entity;
class User extends Entity
{
// bake で生成されたコード
protected function _setPassword($value)
{
$hasher = new DefaultPasswordHasher();
return $hasher->hash($value);
}
}
今から既存のユーザーのパスワードを更新してくだい。パスワードを変更した際、一覧もしくは詳細ページで、 入力した値の代わりにハッシュ化されたパスワードがあることを確認してください。CakePHP は、 デフォルトで bcrypt を使ってパスワードをハッシュ化します。既存のデータベースが動作している場合、 sha1 や md5 も 使用できます。
注釈
パスワードがハッシュ化されない場合、セッター関数の命名について、 クラスのパスワードメンバーと大文字小文字が同じかを確認してください。
これで、パスワードを安全に保存できますので、アプリケーションにもっと面白い機能を構築できます。 一度ブックマークのコレクションを蓄えて、タグでの検索ができるようになると便利です。 次は、タグでのブックマークを検索するため、ルート、コントローラーのアクション、finder メソッドを実装します。
理想的には、 http://localhost:8765/bookmarks/tagged/funny/cat/gifs のような URL にしたいと思います。この URL は、 'funny', 'cat', もしくは 'gifs' タグが付いたブックマークすべてを検索することを意図しています。これを実装する前に、 新しいルートを追加します。 config/routes.php を以下のようにしてください。
<?php
use Cake\Routing\Route\DashedRoute;
use Cake\Routing\Router;
Router::defaultRouteClass(DashedRoute::class);
// 新しいルートを tagged アクションのために追加します。
// 末尾の `*` は、渡された引数を持っていることを
// CakePHP に伝えます。
Router::scope(
'/bookmarks',
['controller' => 'Bookmarks'],
function ($routes) {
$routes->connect('/tagged/*', ['action' => 'tags']);
}
);
Router::scope('/', function ($routes) {
// デフォルトのホームと /pages/* ルートへの接続
$routes->connect('/', [
'controller' => 'Pages',
'action' => 'display', 'home'
]);
$routes->connect('/pages/*', [
'controller' => 'Pages',
'action' => 'display'
]);
// デフォルトのルートへ接続
$routes->fallbacks();
});
上記は、 /bookmarks/tagged/ パスを BookmarksController::tags()
に接続する
新しい「ルート」を定義します。ルートを定義することによて、 URL の見た目と、
それらどのように実装されたかを分離することができます。
http://localhost:8765/bookmarks/tagged にアクセスした場合、CakePHP から
コントローラーのアクションがないことを伝える役に立つエラーページが表示されます。
今から存在しないメソッドを実装してみましょう。 src/Controller/BookmarksController.php
に以下を追加してください。
public function tags()
{
// CakePHP によって提供された 'pass' キーは全ての
// リクエストにある渡された URL のパスセグメントです。
$tags = $this->request->getParam('pass');
// タグ付きのブックマークを探すために BookmarksTable を使用
$bookmarks = $this->Bookmarks->find('tagged', [
'tags' => $tags
]);
// ビューテンプレートに変数を渡します
$this->set([
'bookmarks' => $bookmarks,
'tags' => $tags
]);
}
リクエストデータの他の部分にアクセスするためには リクエスト セクションを 参考にしてください。
CakePHP では、コントローラーのアクションをスリムに保ち、アプリケーションの多くのロジックを
モデルに置くことをお勧めします。 /bookmarks/tagged の URL にアクセスした場合、
findTagged()
メソッドがまだ実装されていないエラーが表示されます。
src/Model/Table/BookmarksTable.php に以下を追加してください。
// $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')
->where(['Tags.title IS' => null]);
} else {
$bookmarks
->innerJoinWith('Tags')
->where(['Tags.title IN ' => $options['tags']]);
}
return $bookmarks->group(['Bookmarks.id']);
}
カスタム Finder メソッド を実装しました。
これは、再利用可能なクエリーをまとめることを実現する CakePHP の非常に強力な概念です。
Finder メソッドは、常に クエリービルダー オブジェクトとオプション配列を
パラメーターとして取得します。Finder メソッドは、クエリーを操作し、任意の必須条件や抽出条件を
追加することができます。完了時、Finder メソッドは更新されたクエリーオブジェクトを
返さなければなりません。finder の中で、一致するタグを持つ特定のブックマークを検索するために、
innerJoinWith()
、 where()
そして group
メソッドを使います。
タグの指定がない場合、タグなしでブックマークを検索するために leftJoinWith()
を使用して、
'where' 条件を変更します。
/bookmarks/tagged の URL にアクセスすると、 CakePHP は、ビューファイルがないことを
知らせるエラーを表示します。次に、ビューファイルを tags()
アクションのために作りましょう。
templates/Bookmarks/tags.php に以下の内容を追加します。
<h1>
Bookmarks tagged with
<?= $this->Text->toList(h($tags)) ?>
</h1>
<section>
<?php foreach ($bookmarks as $bookmark): ?>
<article>
<!-- リンクを作成するために HtmlHelper を使用 -->
<h4><?= $this->Html->link($bookmark->title, $bookmark->url) ?></h4>
<small><?= h($bookmark->url) ?></small>
<!-- テキストを整形するために TextHelper を使用 -->
<?= $this->Text->autoParagraph(h($bookmark->description)) ?>
</article>
<?php endforeach; ?>
</section>
上記のコードは Html と Text を
ビューの出力生成を補助するために使いました。また、 HTML エンコード出力するために
h
ショートカット関数を使いました。HTML インジェクション問題を防ぐために
ユーザーデータ出力時には、必ず h()
を使用することを覚えておいて下さい。
ビューテンプレートファイルのための CakePHP の規約に従って tags.php ファイルを作りました。 この規約は、小文字を使い、コントローラーのアクション名をアンダースコアー化したテンプレート名にすることです。
ビューで $tags
や $bookmarks
変数を使えることにお気づきでしょう。
コントローラーで set()
メソッドを使って、指定した変数をビューに送るためにセットします。
ビューは、渡されたすべての変数をテンプレート内でローカル変数として利用可能にします。
/bookmarks/tagged/funny の URL にアクセスできるようにして、 全ての 'funny' でタグ付けされたブックマークを確認しましょう。
ここまで、ブックマーク、タグ、ユーザーを管理する基本的なアプリケーションを作成してきました。 しかしながら、全員のタグが全員に見えてしまいます。次の章では、認証を実装し、現在のユーザーに 属するブックマークのみを表示するよう制限します。
あなたのアプリケーションの構築を続けるために ブックマークチュートリアル パート2 を読み続けるか、 CakePHP で出来ることをより詳しく学ぶために ドキュメントの中に飛び込んで ください。