2011年11月26日に開催した、CakePHP2.0ハンズオン@札幌の資料をHTMLにしたものを公開します。
解説は現場で行ったため、説明不足の資料になっています。基本的には公式のチュートリアルと同一です。なので、以前の記事とも内容が重複しています。
1. 作業の注意・この資料について
プログラムを保存する場合、
文字コードは「
UTF-8」にして保存してください。改行コードは何でもいいです(LFのみ推奨)。
ファイル名の大文字小文字は間違えないように入力してください。
この資料は、
http://book.cakephp.org/2.0/en/ を元に作成されています。
ダウンロード
http://cakephp.org/から、2.0.3 Stable(現時点での最新バージョン)のパッケージをダウンロードします。解凍し、
Apacheが見える場所(htdocs直下など)に展開してください。
ここでは仮に、htdocs/cakeblog/に展開します。
XAMPP(Windows)環境の場合は、 ダウンロードして展開して作られた「
cakephp-
cakephp-2b55a02」(ファイル名はダウンロードしたバージョンによって違います)というフォルダを、「C:¥xampp¥htdocs」に移動します。その後、「
cakephp-
cakephp-2b55a02」を「cakeblog」にリネームします。
MAMP(
MacOSX)環境の場合は、ダウンロードして展開して作られた「
cakephp-
cakephp-2b55a02」(ファイル名はダウンロードしたバージョンによって違います)というフォルダを、「/Application/MAMP/htdocs」(あるいは「 アプリケーション -> MAMP -> htdocs」)に移動します。その後、「
cakephp-
cakephp-2b55a02」を「cakeblog」にリネームします。
起動と設定
http://localhost/cakeblog/でアクセスできると思うので、アクセスしてみてください。(環境によっては変わるかもしれません)
エラーがいろいろ出ると思うので、確認していきます。(環境によって出るものと出ないものがあります)
「Please change the value of ‘Security.salt’ in app/Config/core.php to a salt value specific to your application」と出た場合
「app/Config/core.
php」を開いて、
Configure::write(’Security.salt’, ‘DYhG93b0qyJfIxfs2guVoUubWwvniR2G0FgaC9mi’);
の行の、よくわからない文字列の部分を、適当なよくわからない文字列に変更してください。(何でもいいです)
「Please change the value of ‘Security.cipherSeed’ in app/Config/core.php to a numeric (digits only) seed value 〜」と出た場合
「app/Config/core.php」を開いて、
Configure::write(’Security.cipherSeed’, ‘76859309657453542496749683645’);
の行の、よくわからない数字の部分を、適当なよくわからない数字に変更してください。
「Your database configuration file is NOT present.」と出た場合
次項で説明します。
「Cake is NOT able to connect to the database.」と出た場合
DBの設定は書けていますが、設定した通りのDBに接続ができません。次項を読みなおしてください。
「Warning: _cake_core_ cache was unable to write ‘cake_dev_ja’ to Apc cache in 〜」と出た場合
APCが無効になっています。APCを有効にするか、apc.soを読み込まないようにしてください。どちらもphp.iniで設定できます。
「Warning: _cake_core_ cache was unable to write ‘cake_dev_ja’ to File cache in 〜」と出た場合
APCは無効ですが、ファイルキャッシュへの書き込みができません。「chmod -R 777 app/tmp」で、いろいろエラーが消えます。
「Warning: /Application/MAMP/htdocs/cakeblog/app/tmp/cache/ is not writable in 〜」と出た場合
「chmod -R 777 app/tmp」で解決します。
「Your tmp directory is NOT writable.」と出た場合
「chmod -R 777 app/tmp」で解決します。
「URL rewriting is not properly configured on your server. 」と出た場合
Apacheでmod_rewriteを有効にしてください。できない場合は、app/Config/core.phpの、
//Configure::write(’App.baseUrl’, env(’SCRIPT_NAME’));
の行を、
Configure::write(’App.baseUrl’, env(’SCRIPT_NAME’));
と変更した上で、今後の説明の「http://localhost/cakeblog/」を、「http://localhost/cakeblog/index.php/」に読み替えてください。
(例:「http://localhost/cakeblog/posts」→「http://localhost/cakeblog/index.php/posts」
3. DBの設定
「app/Config/database.
php.default」を、「app/Config/database.
php」にリネーム(あるいはコピー)してください。
中のプログラムの、
public $default = array(
‘datasource’ => ‘Database/Mysql’,
‘persistent’ => false,
‘host’ => ‘localhost’,
‘login’ => ‘user’,
‘password’ => ‘password’,
‘database’ => ‘database_name’,
‘prefix’ => ‘’,
//’encoding’ => ‘utf8’,
);
の部分を、
public $default = array(
‘datasource’ => ‘Database/Mysql’,
‘persistent’ => false,
‘host’ => ‘localhost’,
‘login’ => ‘root’,
‘password’ => ‘’,
‘database’ => ‘cakeblog’,
‘prefix’ => ‘’,
‘encoding’ => ‘utf8’,
);
のように変更します。(独自のDB接続設定がある場合は、それに合わせて修正してください)
phpMyAdmin等で、「cakeblog」というデータベースを作成します。phpMyAdminの場合は、「新規データベースを作成する」の箇所に「cakeblog」と入力し、「照合順序」を、「utf8_bin」にして、「作成」を押してください。
その後、以下のSQLを入力します。phpMyAdminの場合は、「cakeblog」のデータベースを選択し、「SQL」タブで、以下を貼りつけて、「実行する」を押します。
CREATE TABLE posts (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(50),
body TEXT,
created DATETIME DEFAULT NULL,
modified DATETIME DEFAULT NULL
) Engine=InnoDB;
INSERT INTO posts (title,body,created)
VALUES (’The title’, ‘This is the post body.’, NOW());
INSERT INTO posts (title,body,created)
VALUES (’A title once again’, ‘And the post body follows.’, NOW());
INSERT INTO posts (title,body,created)
VALUES (’Title strikes back’, ‘This is really exciting! Not.’, NOW());
4. モデルの作成
app/Model/Post.phpを作成します。
<?php
class Post extends AppModel {
}
5. コントローラーの作成
app/Controller/PostsController.
phpを作成します。
<?php
class PostsController extends AppController {
public $helpers = array (’Html’,’Form’);
public function index() {
$this->set(’posts’, $this->Post->find(’all’));
}
}
6. ビューの作成
app/View/Posts/index.ctpを作成します。
<h1>Blog posts</h1>
<table>
<tr>
<th>Id</th>
<th>Title</th>
<th>Created</th>
</tr>
<?php foreach ($posts as $post): ?>
<tr>
<td><?php echo $post[’Post’][’id’]; ?></td>
<td>
<?php echo $this->Html->link($post[’Post’][’title’],
array(’controller’ => ‘posts’, ‘action’ => ‘view’, $post[’Post’][’id’])); ?>
</td>
<td><?php echo $post[’Post’][’created’]; ?></td>
</tr>
<?php endforeach; ?>
</table>
7. 詳細画面の作成
app/Controller/PostsController.
phpを修正します。
<?php
class PostsController extends AppController {
public $helpers = array(’Html’, ‘Form’);
public function index() {
$this->set(’posts’, $this->Post->find(’all’));
}
public function view($id = null) {
$this->Post->id = $id;
$this->set(’post’, $this->Post->read());
}
}
app/View/Posts/view.ctpを作成します。
<h1><?php echo $post[’Post’][’title’]?></h1>
<p><small>Created: <?php echo $post[’Post’][’created’]?></small></p>
<p><?php echo $post[’Post’][’body’]?></p>
8. 新規作成画面の作成
app/Controller/PostsController.
phpを修正します。
<?php
class PostsController extends AppController {
public $components = array(’Session’);
public function index() {
$this->set(’posts’, $this->Post->find(’all’));
}
public function view($id) {
$this->Post->id = $id;
$this->set(’post’, $this->Post->read());
}
public function add() {
if ($this->request->is(’post’)) {
if ($this->Post->save($this->request->data)) {
$this->Session->setFlash(’Your post has been saved.’);
$this->redirect(array(’action’ => ‘index’));
}
}
}
}
app/View/Posts/add.ctpを作成します。
<h1>Add Post</h1>
<?php
echo $this->Form->create(’Post’);
echo $this->Form->input(’title’);
echo $this->Form->input(’body’, array(’rows’ => ‘3’));
echo $this->Form->end(’Save Post’);
app/View/Post/index.ctpの末尾に、addへのリンクを追加します。
<?php echo $this->Html->link(’Add Post’, array(’controller’ => ‘posts’, ‘action’ => ‘add’)); ?>
9. バリデーション
app/Model/Post.
phpを修正します。
<?php
class Post extends AppModel {
public $validate = array(
‘title’ => array(
‘rule’ => ‘notEmpty’
),
‘body’ => array(
‘rule’ => ‘notEmpty’
)
);
}
10. 編集画面の作成
app/Controller/PostsController.
phpに、以下の処理を追加します。
<?php
class PostsController extends AppController {
...
public function edit($id = null) {
$this->Post->id = $id;
if ($this->request->is(’get’)) {
$this->request->data = $this->Post->read();
} else {
if ($this->Post->save($this->request->data)) {
$this->Session->setFlash(’Your post has been updated.’);
$this->redirect(array(’action’ => ‘index’));
}
}
}
…
}
app/View/Posts/edit.ctpを作成します。
<h1>Edit Post</h1>
<?php
echo $this->Form->create(’Post’, array(’action’ => ‘edit’));
echo $this->Form->input(’title’);
echo $this->Form->input(’body’, array(’rows’ => ‘3’));
echo $this->Form->input(’id’, array(’type’ => ‘hidden’));
echo $this->Form->end(’Save Post’);
?>
app/View/Posts/index.ctpに、編集リンクを追加します。
<h1>Blog posts</h1>
<p><?php echo $this->Html->link("Add Post", array(’action’ => ‘add’)); ?></p>
<table>
<tr>
<th>Id</th>
<th>Title</th>
<th>Action</th>
<th>Created</th>
</tr>
<?php foreach ($posts as $post): ?>
<tr>
<td><?php echo $post[’Post’][’id’]; ?></td>
<td>
<?php echo $this->Html->link($post[’Post’][’title’], array(’action’ => ‘view’, $post[’Post’][’id’]));?>
</td>
<td>
<?php echo $this->Form->postLink(
‘Delete’,
array(’action’ => ‘delete’, $post[’Post’][’id’]),
array(’confirm’ => ‘Are you sure?’)
)?>
<?php echo $this->Html->link(’Edit’, array(’action’ => ‘edit’, $post[’Post’][’id’]));?>
</td>
<td><?php echo $post[’Post’][’created’]; ?></td>
</tr>
<?php endforeach; ?>
</table>
11. 削除機能の作成
app/Controller/PostsController.
phpに、以下の処理を追加します。
<?php
class PostsController extends AppController {
...
public function delete($id) {
if (!$this->request->is(’post’)) {
throw new MethodNotAllowedException();
}
if ($this->Post->delete($id)) {
$this->Session->setFlash(’The post with id: ‘ . $id . ‘ has been deleted.’);
$this->redirect(array(’action’ => ‘index’));
}
}
…
}
12. ルーティング
ルーティングを変更する場合は、app/Config/routes.
phpを編集します。
現在は
http://localhost/cakeblog/posts からアクセスしていますが、これを
http://localhost/cakeblog/ でアクセスできるようにするには、
Router::connect(’/’, array(’controller’ => ‘posts’, ‘action’ => ‘index’));
//Router::connect(’/’, array(’controller’ => ‘pages’, ‘action’ => ‘display’, ‘home’));
のようにします。
13. 見た目の変更
app/View/Layouts/default.ctpを作成することによって、外観を自由に変更することができます。
以下の内容をサンプルに、自由に書き換えてみましょう。
<!DOCTYPE html>
<html>
<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>
<body>
<div id="container">
<div id="header">
<h1>CakePHP 2.0 Sample</h1>
</div>
<div id="content">
<?php echo $this->Session->flash(); ?>
<?php echo $content_for_layout; ?>
</div>
<div id="footer">
Powered by CakePHP
</div>
</div>
<?php echo $this->element(’sql_dump’); ?>
</body>
</html>
14. コメント機能
ここまでの実装を元に、コメント機能を作成してみましょう。(時間が余った人向け)
15. 管理画面の作成
CakePHPには、管理画面を簡単に作成できる機能が入っています。
仮に、ユーザーというテーブルがあり、それを管理できる画面を簡単に作ります。
データベースに、以下の
SQLを投入します。
CREATE TABLE users (
id int(11) NOT NULL AUTO_INCREMENT,
username varchar(255) NOT NULL,
password varchar(255) NOT NULL,
created datetime DEFAULT NULL,
modified datetime DEFAULT NULL,
PRIMARY KEY (id)
) Engine=InnoDB;
app/Model/User.phpを作成します。
<?php
class User extends AppModel {
}
app/Controller/UsersController.phpを作成します。
<?php
class UsersController extends AppController {
public $scaffold;
}
http://localhost/cakeblog/users にアクセスしてみましょう。
16. 認証
一覧・表示以外は、認証が必要にします。
ここでは、先程作成した、Usersモデル及びコントローラーを使用します。
パスワードを暗号化しなければいけないので、自動で保存時に暗号化されるようにします。app/Model/User.
phpを変更します。
<?php
App::uses(’AuthComponent’, ‘Controller/Component’);
class User extends AppModel {
// ...
public function beforeSave() {
if (isset($this->data[$this->alias][’password’])) {
$this->data[$this->alias][’password’] = AuthComponent::password($this->data[$this->alias][’password’]);
}
return true;
}
// ...
変更したら、http://localhost/cakeblog/usersから、適当にユーザーを作成してみてください。
作成したら、ログインとログアウトができるようにします。
ログイン関係はUsersControllerに追加します。app/Controller/UsersController.phpを編集します。
<?php
class UsersController extends AppController {
public $scaffold;
public $components = array('Session', 'Auth');
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow('login');
}
public function login() {
if ($this->request->is('post')) {
if ($this->Auth->login()) {
$this->redirect($this->Auth->redirect());
} else {
$this->Session->setFlash(__('Invalid username or password, try again'));
}
}
}
public function logout() {
$this->redirect($this->Auth->logout());
}
}
ログイン画面が必要なので、app/View/Users/login.ctpを作成します。
<div class="users form">
<?php echo $this->Session->flash('auth'); ?>
<?php echo $this->Form->create('User');?>
<fieldset>
<legend><?php echo __('Please enter your username and password'); ?></legend>
<?php
echo $this->Form->input('username');
echo $this->Form->input('password');
?>
</fieldset>
<?php echo $this->Form->end(__('Login'));?>
</div>
これでhttp://localhost/cakeblog/users/loginにアクセスするとログインができるようになります。
ログインできているのかどうかよくわからないので、ブログの投稿・編集・削除は、ログインが必要にします。
app/Controller/PostsController.phpを編集します。
<?php
class PostsController extends AppController {
public $components = array('Session', 'Auth');
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow('index', 'view');
}
// .....
ついでに、ログインとログアウトのリンクを追加します。app/View/Layouts/default.ctpの適当な場所に、以下を追加します。
<?php
if ($login_user_id !== null) {
echo "Welcome ".h($login_user_name)." !!<br />";
echo $this->Html->link('Logout', array('controller' => 'users', 'action' => 'logout'));
} else {
echo $this->Html->link('Login', array('controller' => 'users', 'action' => 'login'));
}
?>
このままではエラーになるので、$login_user_idと$login_user_nameが常に入るようにします。app/Controller/AppController.phpを作成します。
<?php
class AppController extends Controller
{
public $components = array('Session', 'Auth');
public function beforeFilter() {
parent::beforeFilter();
$this->set('login_user_id', $this->Auth->user('id'));
$this->set('login_user_name', $this->Auth->user('username'));
}
}
ブログの投稿時にユーザーIDを記録するようにします。
まず、postsテーブルにuser_idを追加します。phpMyAdmin等で、以下のSQLを入力してください。
ALTER TABLE posts ADD COLUMN user_id INT(11);
これに合わせて、PostsControllerのaddの際に、user_idを自動入力させます。app/Controller/PostsController.phpを編集します。
<?php
// app/Controller/PostsController.php
public function add() {
if ($this->request->is(’post’)) {
$this->request->data[’Post’][’user_id’] = $this->Auth->user(’id’); //Added this line
if ($this->Post->save($this->request->data)) {
$this->Session->setFlash(’Your post has been saved.’);
$this->redirect(array(’action’ => ‘index’));
}
}
}