brew tap homebrew/dupes
brew tap homebrew/versions
brew tap homebrew/homebrew-php
brew install php56 composer mysql
composer global require stecman/composer-bash-completion-plugin dev-master
~/.zshrc
## composer completion
function _composer {
# Emulate BASH's command line contents variable
local -x COMP_LINE="$words"
# Emulate BASH's cursor position variable, setting it to the end of the current word.
local -x COMP_POINT
(( COMP_POINT = ${#${(j. .)words[1,CURRENT]}} ))
# Honour the COMPOSER_HOME variable if set
local composer_dir=$COMPOSER_HOME
if [ -z "$composer_dir" ]; then
composer_dir=$HOME/.composer
fi
local RESULT STATUS
local -x COMPOSER_CWD=`pwd`
RESULT=("${(@f)$( cd $composer_dir && composer depends _completion )}")
STATUS=$?;
# Bail out if PHP didn't exit cleanly
if [ $STATUS -ne 0 ]; then
echo $RESULT;
return $?;
fi;
compadd -- $RESULT
};
compdef _composer composer;
exec $SHELL -l
http://book.cakephp.org/3.0/en/tutorials-and-examples/bookmarks/intro.html
プロジェクトの作成
composer create-project --prefer-dist cakephp/app bookmarker
bin/cake server
データベースの作成
mysqladmin create -u root -p cake_bookmarks
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),
INDEX tag_idx (tag_id, bookmark_id),
FOREIGN KEY tag_key(tag_id) REFERENCES tags(id),
FOREIGN KEY bookmark_key(bookmark_id) REFERENCES bookmarks(id)
);
CREATE TABLEの実行
- 設定 config/app.php
- データベースへの接続 Datasources
Scaffold
bin/cake bake all users
bin/cake bake all bookmarks
bin/cake bake all tags
http://localhost:8765/bookmarks
-
パスワードのハッシュ化
- Entity クラス
- setterメソッド
- _setPassowrd($value)
- use Cake\Auth\DefaultPasswordHasher;
- http://book.cakephp.org/3.0/en/orm/entities.html#accessors-mutators
-
ルーティング
- http://localhost:8765/bookmarks/tags/aaa/bbb
- config/routes.php
- tagsアクションをbookmarksコントローラへ追加
-
Custom Finder Method
- $this->Bookmarks->find('tagged') はTableクラスのfindTagged(Query $query, array $options)となる
-
ビュー作成
- src/Template/コントローラ/アクション.ctp
http://book.cakephp.org/3.0/en/tutorials-and-examples/bookmarks/part-two.html
- AuthComponent
- AppController::initialize()の
$this->loadComponent('Flash');
の後ろに追加設定- $this->laodComponent()
- UsersController::login()の実装 (/users/login)
- $this->Auth->identify();
- $this->Auth->setUser($user);
- $this->Auth->redirectUrl();
- テンプレート(ビュー)の実装
- src/Template/Users/login.ctp
- ログインがいらないページは
$this->Auth->allow(['display']);
で設定
- AppController::initialize()の
- AuthComponent
$this->Auth->logout()
- 戻り値はログアウトした際のURLが返る
- ControllerのbeforeFilterで
$this->Auth->allow(メソッド名)
しておくと認証必要なくなる - initialize()はbeforeFilter()よりも先に呼ばれる
- ログイン中の自分のブクマ以外、閲覧・削除できないようにする(/bookmarksページはみえちゃうけど)
- AuthComponent
- 認証 authenticate adapter(ログインのところでAuthの設定をしていたほう)
- 権限 authorization adapter(今回こっち)
'authorize'=> 'Controller' // コントローラで権限管理する
isAuthorized($user)
をオーバーライドして自分のブクマのみを表示するページでだけ実装する- 戻り値が、falseであれば権限無し
- 戻り値が、trueであれば権限あり
- 権限が内場合の通知
<?= $this->Flash->render('auth') ?>
- 全体のレイアウトのファイル
src/Template/Layout/default.ctp
- 現状の問題点を直す
- ブクマを追加・編集する際にユーザを選択できてしまう
- フォームからuser_idの入力を外す
- 登録時に現在ログイン中のユーザIDで保存する
- 他のユーザのブクマが一覧に表示されてしまう
- 検索条件に自分のユーザIDを指定
$this->Auth->user('id')
- ブクマを追加・編集する際にユーザを選択できてしまう
- ブクマを登録する際のユーザビリティ向上を図る
- カンマ区切りでブクマのタグを入力できるようにする
- Bookmarkを読み出す際に、実際にbookmarksテーブルには無い架空のプロパティ
tag_string
をつくる- Entityクラスに書く
- DBから読み出す際のコールバックは
_get
+ アッパーキャメル (_getTagString()
) protected $_accessible
にtag_string
を忘れない- Collection::reduce() の利用
- DBから読み出す際のコールバックは
- Tableクラスに、Bookmark保存時にTagを紐付けるロジックを書く(Collectionをつかえばもっと簡単に実装できる)
public function beforeSave($event, $entity, $options)
コールバック- 対応するEntityを引数でもらっているので参照できる
$entity->tag_string
$entity->tag
- Entityクラスに書く
- Bookmarks/add.ctp, edit.ctpに
tag_string
の入力項目を追加echo $this->Form->input('tags._ids', ['options' => $tags]);
で、HABTMのidの選択フォームができるっぽい
- Bookmarkを読み出す際に、実際にbookmarksテーブルには無い架空のプロパティ
どちらもModel/にある。どっちに何を書けば良いか分からなくなりそうなので、現時点で整理してみる
-
Entity (例: Model/Entity/Bookmark.php)
- 単数形
class Bookmark extends Entity
- Mass Assignment 脆弱性対策の設定
- newEntity() / patchEntity() でアクセス可能なフィールドを
$_accessible
に設定する
- newEntity() / patchEntity() でアクセス可能なフィールドを
- DBには存在しない仮想的なフィールドの設定
- DBに保存したり、DBから読み出す際の加工処理
_set
+ フィールド名アッパーキャメル_get
+ フィールド名アッパーキャメル
- 単数形
-
Table(例: Model/Table/BookmarksTable.php)
- 複数形
class BookmarksTable extends Table
- モデルが実際に扱うテーブル名や、リレーションの設定
- initialize()で行う
- バリデーションの設定
find('tagged')
などの自前検索ロジックbeforeSave()
などのコールバック
- 複数形
-
Controller
-参照->Table
-参照->Entity
- Controllerクラスから
$this->Bookmarks
と扱うのはTableクラス - Tableクラス内でコールバックの引数などでもらって
$entity
と扱うのがEntityクラス - EntityはDBの1レコードの抽象化、TableクラスはDBのテーブルの抽象化
- Controllerクラスから