CakePHP入門をなぞる
calendar_today
2022-11-30
insights
views: 146
thumbnail images

やること

CakePHPのドキュメントをなぞる。

環境

  • PHP 7.4.33
  • CakePHP 2.10.24

インストール

ダウンロード

git clone -b 2.x git://github.com/cakephp/cakephp.git

権限設定

chown -R www-data tmp

table作成

sqlで任意のテーブルを作成する。

ソルトの作成(任意)

// Config/core.php
Configure::write('Security.salt', '[任意のハッシュソルト]');

シードの作成(任意)

// Config/core.php
Configure::write('Security.cipherSeed', '[任意のシード]');

モデル作成

// Model/Post.php
<?php

class Post extends AppModel 
{
    //
}

コントローラ作成

// Controller/PostsController.php
class PostsController extends AppController
{
    public $helpers = array('Html', 'Form');

    public function index() {
        $this->set('posts', $this->Post->find('all'));        
    }
}

Postsコントローラの中にindexを配置するだけでexample.com/posts/indexにアクセスできるようになる。
このurlを変更するにはルート定義する。

ビューの作成

<!-- View/Posts/index.ctp -->
<h1>Posts</h1>
<table>
    <tr>
        <th>id</th>
        <th>title</th>
        <th>created at</th>
    </tr>
    <?php foreach ($posts as $post): ?>
    <tr>
        <td>
            <?= $post['Post']['id']; ?>
        </td>
        <td>
            <?= $this->Html->link($post['Post']['title'], [
                'controller' => 'posts',
                'action' => 'view',
                $post['Post']['id']
            ]); ?>
        </td>
        <td>
            <?= $post['Post']['created_at']; ?>
        </td>
    </tr>
    <?php endforech; ?>
    <?php unset($post); ?>
</table>

第一パラメータに表示文字、
第二パラメータにURLの生成に必要な情報
を渡す。

view(detail)の作成

// Controller/PostsController.php
// 追記
public function view($id = null) {

    if (!$id) throw new NotFoundException(__('Invalid post'));

    $post = $this->Post->findById($id);

    if (!$post) throw new NotFoundException(__('Invalid post'));
    
    $this->set('post', $post);
}

この後 example.com/posts/view/1 にアクセス出来るようになる。

add (create)の追加

// Controller/PostsController.php
// 追記
public funciton add() {
    if (!$this->request->is('post')) $this->Flash->error(__('Unable to add your post.'));
    
    $this->Post->create();
    $data = $this->request->data;
    $is_saved = $this->Post->save($data);
    
    if (!$is_saved) {
        $this->Flash->error(__('Unable to add your post.'));
    } else {
        $this->Flash->success(__('Your post has been saved.'));
        return $this->redirect(['action' => 'index']);
    }
}

$this->request->is()

リクエストのメソッド (get, put, post, delete) もしくはリクエスト識別子 (ajax) を指定する1つの引数を持つ。

バリデーション

バリデーションにはFormHeplerを使用する。

<!-- View/Posts/add.ctp -->
<h1>Add Post</h1>
<?= $this->Form->create('Post'); ?>
<?= $this->Form->input('title'); ?>
<?= $this->Form->input('content', ['rows' => '3']); ?>
<?= $this->Form->end('Save Post'); ?>

上記の出力例(実際には多少異なる):

<h1>Add Post</h1>
<form id="PostAddForm" method="POST" action="/posts/add">
    <input type="text" name="title">
    <textarea name="content" rows="3"></textarea>
    <button type="submit">
        Save Post
    </button>
</form>

ビューに記事を追加するためのリンク設置

<!-- View/Posts/index.ctp -->
<h1>Posts<h1>
<!-- 追記 -->
<?= $this->Html->link(
    'Add Post',
    [
        'controller' => 'posts',
        'action' => 'add',
    ]
); ?>

コントローラの編集

// Controller/PostsController.php
class Post extends AppModel 
{
    // 追記
    public $validate = [
        'title' => ['rule' => 'notBlank'],
        'body' => ['rule' => 'notBlank'],
    ];
}

バリデーションはsave()が呼ばれた際、$validateを使用してバリデートする。

editの追加

// Controller/PostsController.php
// 追記
public function edit($id = null) {
    
    if (!$id) throw new NotFoundException(__('Invalid post'));
    
    $post = $this->Post->findById($id);

    if (!$post) throw new NotFoundException(__('Invalid Post'));

    $this->Post->id = $id;
    $data = $this->request->data;

    if ($this->request->is(['post', 'put'])) {
        $is_saved = $this->Post->save($data);

        if (!$is_saved) {
            $this->Flash->error(__('Unable to update your post.'));
        } else {
            $this->Flash->success(__('your post has been updated.'));
            return $this->redirect(['action' => 'index']);
        }
    }
    
    if (!$data) $this->request->data = $post;

editビュー

<!-- View/Posts/edit.ctp -->
<h1>Edit Post</h1>
<?= $this->Form->create('Post'); ?>
<?= $this->Form->input('title'); ?>
<?= $this->Form->input('content', ['rows' => '3']); ?>
<?= $this->Form->input('id', ['type' => 'hidden']); ?>
<?= $this->Form->end('Save Post'); ?>

編集フォームにはidを埋め込む。

indexビュー

<!-- View/Posts/index.ctp -->
<h1>Posts</h1>
<table>
    <tr>
        <th>id</th>
        <th>title</th>
        <th>action</th> <!-- 追記 -->
        <th>created at</th>
    </tr>
    <?php foreach ($posts as $post): ?>
    <tr>
        <td>
            <?= $post['Post']['id']; ?>
        </td>
        <td>
            <?= $this->Html->link($post['Post']['title'], [
                'controller' => 'posts',
                'action' => 'view',
                $post['Post']['id']
            ]); ?>
        </td>
        <td> <!-- 追記 -->
            <?= $this->Html->link('Edit', [
                'action' => 'edit', 
                $post['Post']['id']
            ]); ?>
        </td>
        <td>
            <?= $post['Post']['created_at']; ?>
        </td>
    </tr>
    <?php endforech; ?>
    <?php unset($post); ?>
</table>

delete の追加

// Controller/PostsController.php
public function delete($id) {
    if ($this->request->id('get')) throw new methodNotAllowedException();
    
    $is_deleted = $this->Post->delete($id);

    if ($is_deleted) {
        $this->Flash->success(__('The post with id: %s has been deleted.', h($id)));
    } else {
        $this->Flash->error(__('The post with id: %s could not be deleted.'), h($id));
    }
    
    return $this->redirect(['action' => 'index']);

indexビュー

<!-- View/Posts/index.ctp -->
<h1>Posts</h1>
<table>
    <tr>
        <th>id</th>
        <th>title</th>
        <th>action</th>
        <th>created at</th>
    </tr>
    <?php foreach ($posts as $post): ?>
    <tr>
        <td>
            <?= $post['Post']['id']; ?>
        </td>
        <td>
            <?= $this->Html->link($post['Post']['title'], [
                'controller' => 'posts',
                'action' => 'view',
                $post['Post']['id']
            ]); ?>
        </td>
        <td>
            <!-- 追記 -->
            <?= 
                $this->Html->link('Delete', [
                    'action' => 'delete',
                    $post['Post']['id']
                ], ['confirm' => 'Are you sure?']
            ); ?>
            <?= $this->Html->link('Edit', [
                'action' => 'edit', 
                $post['Post']['id']
            ]); ?>
        </td>
        <td>
            <?= $post['Post']['created_at']; ?>
        </td>
    </tr>
    <?php endforech; ?>
    <?php unset($post); ?>
</table>

ルーティング

ルーティングはConfig/routes.phpにある。

Router::connect('/', ['controller' => 'posts', 'action' => 'index']);

所感

Laravelと比べて、かなりPHPの書き方が違うと感じた。特に、

  • Classの波括弧の位置
  • インデントがTab

とか。
もしかするとCakePHP2時代のPSR-2は未成熟だったりしたのかもしれない。
またCakePHP2自体のコーディング規約もあるみたい。if文を一行で書くのはだめっぽい。
ということで色々と違いに戸惑いつつも、なるだけフレームワークやプロジェクトのコーディングスタイルに合わせるように努力しようと思う。

calendar_today
2022-11-30
insights
views: 146