CakePHP

CakePHP3.0のブログチュートリアル

更新日:

今日は、CakePHP3.0のブログチュートリアルを調べてみたいと思います。

それでは、ブログプロジェクトを作成するために、コマンドプロンプトで、下記の様に入力します。

cd C:\xampp\htdocs
composer create-project --prefer-dist cakephp/app blog

phpMyAdminで、blogデータベースを作成し、

2015-05-03 12-42-25

公式サイトのSQLをそのまま利用して、

CREATE TABLE articles (
 id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
 title VARCHAR(50),
 body TEXT,
 created DATETIME DEFAULT NULL,
 modified DATETIME DEFAULT NULL
);
INSERT INTO articles (title,body,created)
 VALUES ('The title', 'This is the article body.', NOW());
INSERT INTO articles (title,body,created)
 VALUES ('A title once again', 'And the article body follows.', NOW());
INSERT INTO articles (title,body,created)
 VALUES ('Title strikes back', 'This is really exciting! Not.', NOW());

データベースと3つのデータを入力すると、

2015-05-03 12-47-26

下記の様にデータベースが作成されます。

2015-05-03 12-52-17

作成されたデータベースをCakePHPで使用するためにconfigファイルの環境設定を修正します。

blog/config/app.php

'username' => 'root',
'password' => 'mysql's password',
'database' => 'blog',
'encoding' => 'utf8',
'timezone' => 'SYSTEM',

222-226行目をmysqlの環境に合わせて修正します。

Articleモデルの作成

bookmarkerチュートリアルでは、スキャフォールドで、モデル、コントローラ、ビューを一括作成していましたが、Blogチュートリアルでは、それぞれ個別に作成していますので、公式サイトに準じてモデル作成してみましょう。

blog/src/Model/Table/ArticlesTable.php

<?php
 namespace App\Model\Table;
use Cake\ORM\Table;
class ArticlesTable extends Table
 {
 public function initialize(array $config)
 {
 $this->addBehavior('Timestamp');
 }
 }

2行目:CakePHP3.0からは、名前空間の指定が必須になります。

3行目:use演算子で、blog/vendor/cakephp/src/ORM/Table.phpクラスを読み込んでいます。

4行目:ArticlesTableクラスは、上記のTableクラスを継承しています。

6行目:初期化処理です。

ArticlesControllerの作成

モデルの次には、コントローラを作成します。

blog/src/Controller/ArticlesController.php

<?php
 namespace App\Controller;
class ArticlesController extends AppController
 {
public function index()
 {
 $articles = $this->Articles->find('all');
 $this->set(compact('articles'));
 }
 }

2行目:モデルと同様、名前空間を指定します。

3行目:ArticlesControllerは、AppControllerを継承します。尚、AppControllerは、blog/vendor/cakephp/src/Cake/Controller/Controller.phpクラスを継承しています。尚、説明の記述が長くなりますので、今後は、blog/vendor/cakephp/src部分は、カットして、Cake以下からを記述することにします。

7行目:Articlesモデルのfindメソッドで、全てのオブジェクトを$articlesに代入しています。

8行目:blog/src/Template/Articles/index.ctpに上記のオブジェクトを引き渡しています。

Articleビューの作成

次に、ビューを作成します。CakePHP3.0では、ビューファイルは、Viewフォルダではなく、Templateフォルダに作成することに注意してください。

blog/src/Template/Articles/index.ctp

<h1>Blog articles</h1>
 <table>
 <tr>
 <th>Id</th>
 <th>Title</th>
 <th>Created</th>
 </tr>
 <?php foreach ($articles as $article): ?>
 <tr>
 <td><?= $article->id ?></td>
 <td>
 <?= $this->Html->link($article->title, ['action' => 'view', $article->id]) ?>
 </td>
 <td>
 <?= $article->created->format(DATE_RFC850) ?>
 </td>
 </tr>
 <?php endforeach; ?>
 </table>

8行目:ArticlesControllerから引き渡された$articlesオブジェクトをforeach文で展開します。

12行目:Htmlヘルパーのlinkメソッドで、リンクを作成します。第1引数に表示文字列、第2引数に、パラメーターを配列で指定します。つまり、下記のようなタグを生成します。
<a href="/blog/articles/view/1">The title</a>

15行目:Cake2.xで使用されていたTimeヘルパーと同じだと思いますが、後日調べてみます。

尚、現状では、リンク先がありませんので、リンクをクリックしてもエラーになります。下記の様にArticlesController.phpにviewsアクションとview.ctpを追加してください

blog/src/Controller/ArticlesController.php

public function view($id = null)
 {
 $article = $this->Articles->get($id);
 $this->set(compact('article'));
 }

3行目:Articlesモデルから、指定されたidのオブジェクトを取得して、$articlesに代入しています。

4行目:上記オブジェクトをviewビューに引き渡(セット)しています。

blog/src/Template/Articles/view.ctp

<h1><?= h($article->title) ?></h1>
<p><?= h($article->body) ?></p>
<p><small>Created: <?= $article->created->format(DATE_RFC850) ?></small></p>

1行目:hヘルパー(htmlspecialchars)で、文字列をエスケープしています。

それでは、ブラウザで確認してみましょう。

http://localhost/blog/articles

2015-05-03 14-27-32

データの新規作成

データの新規作成用のコードをコントローラに追加記述します。下記のコードを追加してください。

blog/src/Controller/ArticlesController.php

public function add()
{
 $article = $this->Articles->newEntity();
 if ($this->request->is('post')) {
 $article = $this->Articles->patchEntity($article, $this->request->data);
 if ($this->Articles->save($article)) {
 $this->Flash->success(__('あなたの記事は保存されました'));
 return $this->redirect(['action' => 'index']);
 }
 $this->Flash->error(__('あなたの記事は追加できません'));
 }
 $this->set('article', $article);
}

3行目:$articleにインスタンス化したArticlesモデルのオブジェクトを代入します。

4-12行目:受け取ったデータがPOST時の処理を行います。

5-10行目:受け取ったリクエストデータが保存されたら、indexアクションへリダイレクトし、保存されなかったら、元のaddアクションへリダイレクトされます。その時にフラッシューデータをセットします。

データバリデーション

上記のままでは、たとえ空白のままデータを入力しても、すべてのデータを受け入れて新規作成してしまいます。そこで、未入力のデータは保存されないように、バリデーションを作成します。

バリデーションは、Tableモデルに作成します。

blog/src/Model/Table/ArticlesTable.php

<?php
namespace App\Model\Table;

use Cake\ORM\Table;
use Cake\Validation\Validator; //追加

class ArticlesTable extends Table
{
 public function initialize(array $config)
 {
 $this->addBehavior('Timestamp');
 }
 //追加
 public function validationDefault(Validator $validator)
 {
 $validator
 ->notEmpty('title')
 ->notEmpty('body');

 return $validator;
 }
}

5行目:Cake\Validation\Validatorクラスをインポートします。

14-21行目:バリデーションの内容を記述します。ValidatorクラスのnotEmptyメソッドは、必須項目指定のためのバリデーションです。

それでは、実際にデータを新規作成するために、addビューを下記の様に作成します。

blog/src/Template/Articles/add.ctp

<h1>Add Article</h1>
<?php
echo $this->Form->create($article);
echo $this->Form->input('title');
echo $this->Form->input('body', ['rows' => '3']);
echo $this->Form->button(__('Save Article'));
echo $this->Form->end();
?>

データの修正

データを修正するためのeditアクションをコントローラに追加します。

blog/src/Controller/ArticlesController.php

public function edit($id = null)
{
 $article = $this->Articles->get($id);
 if ($this->request->is(['post', 'put'])) {
 $this->Articles->patchEntity($article, $this->request->data);
 if ($this->Articles->save($article)) {
 $this->Flash->success(__('あなたの記事は更新されました'));
 return $this->redirect(['action' => 'index']);
 }
 $this->Flash->error(__('あなたの記事は更新されません'));
 }
 $this->set('article', $article);
}

3行目:指定されたIDのモデルオブジェクトを$articleに代入します。

4-11行目:受け取ったリクエストがPOSTまたは、PUT時の処理を記述しています。

5-10行目:記事が無事保存されたら、success時のフラッシュデータと伴に、indexアクションへリダイレクトされます。記事が保存されなかったら、error時のフラッシューデータと伴に、editアクションへリダイレクトされます。

それでは、実際にデータを新規作成するために、addビューを下記の様に作成します。

blog/src/Template/Articles/edit.ctp

<h1>Edit Article</h1>
<?php
echo $this->Form->create($article);
echo $this->Form->input('title');
echo $this->Form->input('body', ['rows' => '3']);
echo $this->Form->button(__('Save Article'));
echo $this->Form->end();
?>

上記のadd.ctpとedit.ctpの両方とも基本的には、変わりません。<h1>タグの表題が違うだけです。上記の受け取ったデータをコントローラの処理により、データを新規作成するのと、元のデータを修正するのに変わります。

indexビューの修正

blogアプリケーションのトップページindexビューから、新規作成と、データ修正ページへ移動できるように、indexビューを下記の様に修正します。

blog/src/Template/Articles/index.ctp

<h1>ブログ記事</h1>
 <p><?= $this->Html->link("Add Article", ['action' => 'add']) ?></p><!-- 追加行 -->
 <table>
 <tr>
 <th>Id</th>
 <th>Title</th>
 <th>Created</th>
 <th>Action</th><!-- 追加行 -->
 </tr>
 <?php foreach ($articles as $article): ?>
 <tr>
 <td><?= $article->id ?></td>
 <td>
 <?= $this->Html->link($article->title, ['action' => 'view', $article->id]) ?>
 </td>
 <td>
 <?= $article->created->format(DATE_RFC850) ?>
 </td>
 <td>
 <?= $this->Html->link('Edit', ['action' => 'edit', $article->id]) ?><!-- 追加(+前後)-->
 </td>
 </tr>
 <?php endforeach; ?>
</table>

下記の様になりました。

2015-05-03 20-03-05

データの削除

データ削除用のdeleteアクションをコントローラに追加記述します。

blog/src/Controller/ArticlesController.php

public function delete($id)
 {
 $this->request->allowMethod(['post', 'delete']);
$article = $this->Articles->get($id);
 if ($this->Articles->delete($article)) {
 $this->Flash->success(__('id: {0} の記事は削除されました', h($id)));
 return $this->redirect(['action' => 'index']);
 }
 }

3行目:リクエストクラスのallowMethodメソッドで、POSTまたは、DELETE時にこのアクションは実行されます。

4行目:指定IDのArtclesモデルオブジェクトを$artcleに代入します。

5-9行目:指定データ(オブジェクト)が削除されたら、フラッシュデータと伴にindexアクションへリダイレクトします。

indexビューに、削除用リンクを追加します。edit用のリンクの隣に作成してください。

blog/src/Template/Articles/index.ctp

<?= $this->Form->postLink(
 'Delete',
 ['action' => 'delete', $article->id],
 ['confirm' => 'Are you sure?'])
?>

ルーターの修正

現状では、localhost/blogと入力すると、CakePHPのデフォルトのトップページ、Template/Pages/index.ctpが表示されます。これをTemplate/Articles/index.ctpが表示されるようにルーターを修正します。

blog/config/routes.php

$routes->connect('/', ['controller' => 'Pages', 'action' => 'display', 'home']);

を下記の様に修正します。

$routes->connect('/', ['controller' => 'Articles', 'action' => 'index']);

これで、ブラウザからlocalhost/blogと入力すると、下記の様にArticlesアプリケーションのトップページが表示されます。

2015-05-03 20-52-57

本日は以上です。


							

-CakePHP

Copyright© WinRoad徒然草 , 2018 All Rights Reserved Powered by AFFINGER5.