3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
CakePHP2.13時間濃縮
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)by nipotan
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
本日の主旨
8時間耐久を圧縮CakePHP2.1の基本
骨の髄に(強制的に)刻みこむ時間が許す範囲で応用技
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
who am I
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
?CakePHP2実践入門(仮)
技術評論社より今夏出版予定
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
本日のメニューMVCの考え方
セットアップの肝コントローラーの使い方
モデルの使い方ビューの使い方応用技の紹介
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
MVCの考え方by crabchick
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
MVCだらけ
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
CakePHPもMVC
Railsインスパイア系
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
なぜMVC
複雑化するプログラム整理が必要分割の経験則
Model View Controller
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
MVCに分割
巨大なプログラム
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
MVCの役割
•Model データや処理(データベース処理)
•View 見た目を担当(HTMLの出力)
•Controller 入力を受けてモデルとビューを呼ぶ(それ以外)
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
CakePHPの前に
ふつうのPHPスクリプトで考えてみます
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
<?php
$keyword = '';
if (isset($_POST['keyword'])) {
$keyword = $_POST['keyword'];
}
mysql_connect('localhost','user','password');
mysql_select_db('cakephp_sample');
mysql_query('set names utf8');
$sql = sprintf(
"SELECT id,name,description FROM friends WHERE name LIKE '%s'",
mysql_real_escape_string('%'.$keyword.'%')
);
$result = mysql_query($sql);
$data = array();
while ($row = mysql_fetch_assoc($result)) {
$data[] = $row;
}
?>
<html>
<head><title>テストページ</title></head>
<body>
<form action="list1.php" method="POST">
<input name="keyword"><input type="submit">
</form>
<ul>
<?php
foreach ($data as $row) {
echo '<li>';
echo $row['name'];
echo $row['description'];
echo '</li>';
}
?></ul>
</body></html>
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
<?php
$keyword = '';
if (isset($_POST['keyword'])) {
$keyword = $_POST['keyword'];
}
mysql_connect('localhost','user','password');
mysql_select_db('cakephp_sample');
mysql_query('set names utf8');
$sql = sprintf(
"SELECT id,name,description FROM friends WHERE name LIKE '%s'",
mysql_real_escape_string('%'.$keyword.'%')
);
$result = mysql_query($sql);
$data = array();
while ($row = mysql_fetch_assoc($result)) {
$data[] = $row;
}
?>
<html>
<head><title>テストページ</title></head>
<body>
<form action="list1.php" method="POST">
<input name="keyword"><input type="submit">
</form>
<ul>
<?php
foreach ($data as $row) {
echo '<li>';
echo $row['name'];
echo $row['description'];
echo '</li>';
}
?></ul>
</body></html> Viewへ
Modelへ
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
<?php
//index.php
$keyword = '';
if (isset($_POST['keyword'])) {
$keyword = $_POST['keyword'];
}
include ‘model.php’;
include ‘view.php’;
<?php
//model.php
mysql_connect('localhost','user','password');
mysql_select_db('cakephp_sample');
mysql_query('set names utf8');
$sql = sprintf(
"SELECT id,name,description FROM friends WHERE name LIKE '%s'",
mysql_real_escape_string('%'.$keyword.'%')
);
$result = mysql_query($sql);
$data = array();
while ($row = mysql_fetch_assoc($result)) {
$data[] = $row;
}
<!-- view.php -->
<html>
<head><title>テストページ</title></head>
<body>
<form action="list1.php" method="POST">
<input name="keyword"><input type="submit">
</form>
<ul>
<?php
foreach ($data as $row) {
echo '<li>';
echo $row['name'];
echo $row['description'];
echo '</li>';
}
?></ul>
</body></html>
Model
View
Controller
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
別々にしただけ
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
ひとつの方が楽?
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
問題は量
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
自然発生
進化の答えがMVC
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
CakePHPのMVCController置き場(全ての起点)
Model置き場(データベース関連)
View置き場(HTML関連)
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
CakePHP習得の為に
Controllerの知識Modelの知識Viewの知識
それぞれの理解を深める
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
セットアップの肝
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
ポイントpdo_mysqlmod_rewritePHP5.2以上
core.php / database.phpchmod -R 777 app/tmp
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
phpinfo()
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
mod_rewriteが無い
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
mod_rewriteの有効化
わりと地雷(勉強会中)
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
rewrite無しの場合/** * To configure CakePHP *not* to use mod_rewrite and to * use CakePHP pretty URLs, remove these .htaccess * files: * * /.htaccess * /app/.htaccess * /app/webroot/.htaccess * * And uncomment the App.baseUrl below: */ //Configure::write('App.baseUrl', env('SCRIPT_NAME'));
コメントを外す(rewriteが無理な時だけ)urlの末尾にindex.phpを付ける
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
準備完了
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
Controllerの使い方
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
典型的なコントローラー<?php// app/Controller/TasksController.phpApp::uses('AppController', 'Controller');
class TasksController extends AppController { public function index() { $task_data = $this->Task->find(‘all’); $this->set(‘task_data’,$task_data); }}
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
Controllerの必須テクディスパッチのルール$scaffold $uses$this->render()$this->set()
$this->redirect()$this->request
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
ディスパッチ
アクセスされたURLに応じて適切なコントローラーを
呼び出す機構
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
ページコントローラー
index.phpmenu.php
mypage.phpに直接URLからアクセス
(ふつうのPHP)
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
フロントコントローラー
index.phpにまずアクセスして、
その中でそれぞれの処理に飛ばす
(CakePHPはこの方式)
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
ディスパッチの例/tasks/index→TasksControllerのindex/Oden/umai→OdenControllerのumai/my_page→MyPageControllerのindex
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
routes.phpなら
任意のマッピングも追加可能(最後にURLだけ変更とか)そのままでOKなら設定不要
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
$scaffold
public $scaffold;とするだけで標準機能が動く
※動作確認などに便利
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
$uses
コントローラーが使うモデルのリスト省略時はコントローラー名と同一
命名規則で苦しむのは横着するからです
class MyController extends AppController { public $uses = array(‘Task’,‘User’);
}
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
$this->render()
任意のViewを呼び出す省略時はアクション名と同名を呼ぶ
同じViewを使いまわす事もできる!
$this->render(‘hoge’);
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
$this->set()
任意のデータをViewへ渡すスカラー値も配列も渡せる
Viewで使いたいデータはset()!
$this->set(‘hoge’,‘this is data’);
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
$this->redirect()
任意のページへリダイレクト$this->flash() や
$this->Session->setFlash()と組みわせてメッセージ表示
登録完了やエラー時によく使う
$this->redirect(‘oden/umai’);
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
$this->request
フォームの入力内容などにアクセス可
$_POSTなどを使った者は校庭10周に処す
$this->request->data$this->request->pass$this->request->is()
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
Modelの使い方
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
典型的なモデル
<?php// app/Model/Task.phpApp::uses('AppModel', 'Model');
class Task extends AppModel { public $useTable = 'tasks';}
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
Modelの必須テク$useTable
$primaryKeyfind()
save() saveField() updateAll() delete()
deleteAll()
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
Modelの必須テク2
$validates$belongsTo
$hasOne / $hasMany$hasAndBelongsToMany
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
Model手強い
Modelを制する者はCakeを制す
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
$useTable
モデルが処理を行うテーブル名を指定省略時はモデル名の複数形になるfalseにするとテーブル無しモデル
ここもはまりやすい
public $useTable = ‘tablename’;
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
$primaryKey
テーブルの主キーを設定省略時は’id’
既存のテーブルを使う場合に便利
public $primaryKey = ‘id’;
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
$this->find(‘all’,$options);$this->find(‘first’,$options);$this->find(‘count’,$options);$this->find(‘list’,$options);
$this->find(‘threaded’,$options);$this->find(‘neighbors’,$options);
find()
オプション次第で自在にSQL文を実行(オプションが多い)
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
array( 'conditions' => array('Model.field' => $thisValue), 'recursive' => 1, //int 'fields' => array('Model.field1', 'DISTINCT Model.field2'), 'order' => array('Model.created', 'Model.field3 DESC'), 'group' => array('Model.field'), 'limit' => n, 'page' => n, 'offset' => n, 'callbacks' => true)
find()のオプション
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
find()のオプション
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
array( 'conditions' => array('Model.field' => $thisValue), 'recursive' => 1, //int 'fields' => array('Model.field1', 'DISTINCT Model.field2'), 'order' => array('Model.created', 'Model.field3 DESC'), 'group' => array('Model.field'), 'limit' => n, 'page' => n, 'offset' => n, 'callbacks' => true)
find()のオプション
必要ない部分は適宜省略可能様々なfind()にこのオプションを使う
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
find(‘all’) の結果$data = $this->Hoge->find(‘all’);
$data[0][‘Hoge’][‘name’]; // Hogeのname$data[0][‘Hoge’][‘twitter’]; // Hogeのtwitter
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
// field > ‘a’ のような比較array( 'conditions' => array('Model.field >' => $thisValue),)
= 以外の比較
キー名にスペースを空けて演算子
// field like ‘%a%’ のような比較array( 'conditions' => array('Model.field like' => ‘%’.$thisValue.’%’),)
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
// ANDarray( 'conditions' => array( 'Model.field <' => 100 'Model.field >' => 20 ),)
AND条件 OR条件
// ORarray( 'conditions' => array( ‘OR’ => array( 'Model.field' => 10, 'Model.type' => ‘A’, ) ),)
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
find(‘first’) の結果$data = $this->Hoge->find(‘first’);
$data[‘Hoge’][‘name’]; // Hogeのname$data[‘Hoge’][‘twitter’]; // Hogeのtwitter
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
find(‘count’) の結果$data = $this->Hoge->find(‘count’);
数値で帰ってくる
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
find(‘list’) の結果$data = $this->Hoge->find(‘list’);
リストで帰ってくる
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
find(‘threaded’)find(‘neighbors’)
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
save()
渡されたデータを元にデータを保存INSERT/UPDATEに両対応主キーがあるかないかで分岐
Model->save($data,$validate = true);
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
saveField()
単一のフィールドを更新しかしあまり使わない
(save()で同じ事ができる)
Model->id = $id;Model->saveField($name,$value);
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
updateAll()
条件にマッチするデータを全て更新あまり使わない
(データが少なければ1件づつsave()でも問題ないので)
Model->updateAll($fields,$condition);
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
delete() deleteAll()
DELETEを実行できる。しかし実際のシステムでDELETEは使わず削除フラグなどで操作する事が多い。
Model->delete($id,$cascade);Model->deleteAll($condition,$cascade);
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
$validates
配列で設定したとおりに検査save前に実行される
public $validate = array( 'twitter' => array( 'rule' => 'notEmpty', 'message' => 'Twitter is very important' ), 'name' => array( 'rule' => 'notEmpty', ) );
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
$validates
メッセージや複雑な条件も設定可能
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
アソシエーション
$belongsTo$hasOne / $hasMany
$hasAndBelongsToMany
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
$belongsTo
モデルが属する上位モデルを指定日記(たくさん) ー> ユーザー(1)
public $belongsTo = array( 'Shimokita' => array( 'foreignKey' => 'friendlist_id' ));
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
$belongsTo
設定さえすれば自動で関連データを取得
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
$hasMany
モデルが所有している下位モデルを指定ユーザー ー> 日記(たくさん)
public $hasMany = array( 'Item');
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
$hasMany
複数件の関連データが取得される
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
Viewの使い方
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
Viewの必須テクLayoutの変更$this->request$this->element()$this->Html$this->Form
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
Layout
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
Layoutの変更
ビューはレイアウトの中に読み込まれる
標準はapp/View/Layout/default.ctp
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
default.ctpの要所<body><div id="container">
<div id="header"><h1><?php echo $this->Html->link($cakeDescription, 'http://cakephp.org'); ?></h1></div>
<div id="content"><?php echo $this->Session->flash(); ?><?php echo $this->fetch('content'); ?>
</div><div id="footer">
<?php echo $this->Html->link($this->Html->image('cake.power.gif'),'http://www.cakephp.org/',array('target' => '_blank', 'escape' => false));?>
</div></div><?php echo $this->element('sql_dump'); ?></body>
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
CSSなど<head> <?php echo $this->Html->charset(); ?> <title> <?php echo $cakeDescription ?>: <?php echo $title_for_layout; ?> </title> <?php echo $this->Html->meta('icon'); echo $this->Html->css('cake.generic'); echo $scripts_for_layout; ?></head>
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
CSS、画像はwebroot
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
$this->request
リクエストはビューでも取れる(引き回す必要無し)
echo $this->request->data[‘name’]
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
$this->element
テンプレートから別のテンプレートを読み込む。
(変数はオプションで渡す)
echo $this->element(‘template’,$data);
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
$this->Html
HTMLを生成するヘルパーURLを自動生成して便利(手動でタグは書かない)
$url = array( ‘controller’ => ‘hoge’, ‘action’ => ‘index’);echo $this->Html->link($title,$url);
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
$this->Form
フォームを生成する初期値のフィルインや
エラーメッセージを自動化
echo $this->Form->create(‘ModelName’);echo $this->Form->input($fieldName);
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
応用技の紹介
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
CakePHPの応用技
MVCのバランスMVCの各部品を強化標準の強力な機能群MVCの各要素に対応
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
ベストプラクティス
モデル層を厚くせよ
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
MVC::BHC
ControllerModel
View
ComponentBehavior
Helper
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
応用技に手を伸ばす時
コードが肥大化した時まずはHelper
次にComponent最後にBehavior
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
Helper
HtmlFormCacheJs
PaginatorSessionRss
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
Component
AclAuthCookie
RequestHandler
PaginationSecuritySession
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
Behavior
TreeContainable
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
まだある応用技
プラグインCoreクラスConsole
ユニットテスト
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
今後の羅針盤
http://book.cakephp.org/2.0/en/http://book.cakephp.org/2.0/ja/
3時間濃縮CakePHP2.1@札幌 / Yusuke Ando (@yando)
吐き気に勝った!