「CakePHP3でWebアプリ開発」の記事見てお勉強

CakePHP3でWebアプリ開発

以下の記事を見ながら実際にWebアプリを作ってみる。

qiita.com

現時点で作ったこと

  • ドットインストールのCakePHP3入門で何となく作り方のイメージが出来た

http://dotinstall.com/lessons/basic_cakephp_v2

認証機能の実装

記事のとおりに作成していく

1. userテーブルを作成

mysql> CREATE TABLE users (
    -> id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    -> username VARCHAR(50),
    -> password VARCHAR(255),
    -> role VARCHAR(20),
    -> created DATETIME DEFAULT NULL,
    -> modified DATETIME DEFAULT NULL
    -> );
Query OK, 0 rows affected (0.09 sec)

mysql>

2. Model src/Model/Table/UsersTable.phpを作成する。

<?php

namespace App\Model\Table;

use Cake\ORM\Table;
use Cake\Validation\Validator;

class UsersTable extends Table
{

    public function validationDefault(Validator $validator)
    {
        return $validator
            ->notEmpty('username', 'A username is required')
            ->notEmpty('password', 'A password is required')
            ->notEmpty('role', 'A role is required')
            ->add('role', 'inList', [
                'rule' => ['inList', ['admin', 'user']],
                'message' => 'Please enter a valid role'
            ]);
    }

}

3. src/Model/Entity/User.phpを作成

<?php

namespace App\Model\Entity;

use Cake\Auth\DefaultPasswordHasher;
use Cake\ORM\Entity;

class User extends Entity
{

    protected $_accessible = [
        '*' => true,
        'id' => false
    ];

    protected function _setPassword($password)
    {
        return (new DefaultPasswordHasher)->hash($password);
    }
}

4. Controller src/Controller/AppController.phpを修正

認証機能を有効にする 以下の記事だとコメントが書いてあるので読んでみた jmatsuzaki.com

    /**
     * Initialization hook method.
     *
     * Use this method to add common initialization code like loading components.
     *
     * e.g. `$this->loadComponent('Security');`
     *
     * @return void
     */
    public function initialize()
    {
        parent::initialize();

        $this->viewBuilder()->layout('my_layout');

        $this->loadComponent('RequestHandler');
        $this->loadComponent('Flash');

        // 20170612 ADD 認証機能を有効
        $this->loadComponent('Auth', [
                'authorize' => ['Controller'],
                'loginRedirect' => [
                    'controller' => 'Users',
                    'action' => 'index'
                ],
                'logoutRedirect' => [
                    'controller' => 'Users',
                    'action' => 'login'
                ]
        ]);

        /*
         * Enable the following components for recommended CakePHP security settings.
         * see http://book.cakephp.org/3.0/en/controllers/components/security.html
         */
        //$this->loadComponent('Security');
        //$this->loadComponent('Csrf');
    }

5. UsersController src/Controller/UsersController.phpを作成

<?php

namespace App\Controller;

use App\Controller\AppController;
use Cake\Event\Event;

class UsersController extends AppController
{

    public function beforeFilter(Event $event)
    {
        parent::beforeFilter($event);
        $this->Auth->allow(['add', 'logout']);
    }

    public function login()
    {
        if ($this->request->is('post')) {
            $user = $this->Auth->identify();
            if ($user) {
                $this->Auth->setUser($user);
                return $this->redirect($this->Auth->redirectUrl());
            }

            $this->Flash->error(__('Invalid username or password, try again'));
        }
    }

    public function logout()
    {
        return $this->redirect($this->Auth->logout());
    }

    public function isAuthorized($user) 
    {
        return true;
    }   

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

    public function view($id)
    {
        $user = $this->Users->get($id);
        $this->set(compact('user'));
    }

    public function add()
    {
        $user = $this->Users->newEntity();
        if ($this->request->is('post')) {
            $user = $this->Users->patchEntity($user, $this->request->data);
            if ($this->Users->save($user)) {
                $this->Flash->success(__('The user has been saved.'));
                return $this->redirect(['action' => 'add']);
            }
            $this->Flash->error(__('Unable to add the user.'));
        }
        $this->set('user', $user);
    }

}

beforeFilter:Actionが実行されるよりも前に常にこのbeforeFilterの処理が先行して処理される cakephp.euonymus.info

6. View

src/Template/Users/add.ctpを作成

<div class="users form">
<?= $this->Form->create($user) ?>
    <fieldset>
        <legend><?= __('Add User') ?></legend>
        <?= $this->Form->input('username') ?>
        <?= $this->Form->input('password') ?>
        <?= $this->Form->input('role', [
            'options' => ['admin' => 'Admin', 'user' => 'user']
        ]) ?>
   </fieldset>
<?= $this->Form->button(__('Submit')); ?>
<?= $this->Form->end() ?>
</div>

7 .ログイン画面のテンプレートを定義するため、src/Template/Users/login.ctpを作成

<div class="users form">
<?= $this->Flash->render('auth') ?>
<?= $this->Form->create() ?>
    <fieldset>
        <legend><?= __('ログイン'); ?></legend>
        <?= $this->Form->input('username', array('label' => 'ユーザ:')) ?>
        <?= $this->Form->input('password', array('label' => 'パスワード:')) ?>
    </fieldset>
<?= $this->Form->button(__('Login')); ?>
<?= $this->Form->end() ?>
</div>

8. ユーザ一覧画面のテンプレートを定義するため、src/Template/Users/index.ctpを作成

<h1>users</h1>
<table>
    <tr>
        <th>Id</th>
        <th>Username</th>
    </tr>
    <?php foreach ($users as $user): ?>
    <tr>
        <td><?= $user->id ?></td>
        <td><?= $this->Html->link($user->username, ['action' => 'view', $user->id]) ?></td>
    </tr>
    <?php endforeach; ?>
</table>

画面を確認することが出来ました。