5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

CakePHP3.8で登録画面→確認画面→完了画面を実装する

Last updated at Posted at 2020-07-12
1 / 18

今回のお題


表題の通りです。

久しぶりにCakePHP3を使ってコーディングをする機会がありました。
既にCakePHP4も出ていますが、CakePHP3.8からはそんなに変化がないとのことなので
Cake4にもすんなり入れると良いなあ、などと勝手に考えており。。

需要があるかはさておき、備忘録として残しておきます。


環境

PHP: 5.6.40
CakePHP: 3.8
OS: CentOS7.2
DB: MySQL5.7.21

全体的にレガシーな環境。。
(なのでCakePHP3を採用したという経緯)


テーブル構成


ありきたりで恐縮ですが、ユーザーテーブルへの登録です。
年齢は実年齢ではなく、10代・20代のようなレンジでの管理となります。

CREATE TABLE `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) NOT NULL,
  `age` tinyint(4) NOT NULL,
  `gender` enum('male','female') NOT NULL,
  `email` varchar(255) NOT NULL,
  `password` varchar(255) NOT NULL,
  `last_login_at` datetime DEFAULT NULL,
  `is_deleted` tinyint(4) NOT NULL DEFAULT '0',
  `created` datetime NOT NULL,
  `modified` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CakePHP3実装


Model


Table

validationのコードも載せています。

src/Model/Table/UsersTable.php

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

class UsersTable extends Table
{
    public function initialize(array $config)
    {
        parent::initialize($config);

        $this->setTable('users');
        $this->setDisplayField('name');
        $this->setPrimaryKey('id');

        $this->addBehavior('Timestamp');
    }

    /**
     * Default validation rules.
     *
     * @param \Cake\Validation\Validator $validator Validator instance.
     * @return \Cake\Validation\Validator
     */
    public function validationDefault(Validator $validator)
    {
        $validator
            ->integer('id')
            ->allowEmptyString('id', null, 'create');

        $validator
            ->scalar('name')
            ->maxLength('name', 10, '名前は10文字以内で設定してください。')
            ->requirePresence('name', 'create')
            ->notEmptyString('name');

        $validator
            ->add('name', 'unique', [
                'rule' => 'validateUnique',
                'provider' => 'table',
                'message' => '名前がすでに登録されています。'
            ]);

        $validator
            ->scalar('age')
            ->requirePresence('age', true)
            ->notEmptyString('age');

        $validator
            ->scalar('gender')
            ->requirePresence('gender', true)
            ->notEmptyString('gender');

        $validator
            ->email('email', false, 'メールアドレスが正しくありません。')
            ->requirePresence('email', true)
            ->notEmptyString('email', 'メールアドレスを入力してください。');

        $validator
            ->add('email', 'unique', [
                'rule' => 'validateUnique',
                'provider' => 'table',
                'message' => 'メールアドレスがすでに登録されています。'
            ]);

        $validator
            ->scalar('password')
            ->minLength('password', 8, 'パスワードは半角英数字8文字以上で入力してください。')
            ->requirePresence('password', 'create', 'パスワードを入力してください。')
            ->allowEmptyString('password', 'パスワードを入力してください。', 'update');

        $validator
            ->scalar('password_confirm')
            ->minLength('password_confirm', 8, '確認用パスワードは半角英数字8文字以上で入力してください。')
            ->sameAs('password', 'password_confirm', '異なるパスワードが入力されています。')
            ->requirePresence('password_confirm', 'create', '確認用パスワードを入力してください。')
            ->allowEmptyString('password_confirm', '確認用パスワードを入力してください。', 'update');

        return $validator;
    }

    /**
     * Returns a rules checker object that will be used for validating
     * application integrity.
     *
     * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
     * @return \Cake\ORM\RulesChecker
     */
    public function buildRules(RulesChecker $rules)
    {
        $rules->add($rules->isUnique(['email']));

        return $rules;
    }
}

Entity

hashしたパスワードを保存するためにDefaultPasswordHasherを使用しています。

src/Model/Entity/User.php

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

class User extends Entity
{
    protected $_accessible = [
        'name' => true,
        'age' => true,
        'gender' => true,
        'email' => true,
        'password' => true,
        'last_login_at' => true,
        'is_deleted' => true,
        'created' => true,
        'modified' => true,
    ];

    protected $_hidden = [
        'password',
    ];

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

Controller


画面は以下の通りです。
add: 登録画面
confirm: 確認画面
complete: 完了画面

年齢と性別はconfigで選択肢を管理しています。
確認画面へ遷移した際にvalidationチェックを行い、通ったらセッションに保存をします。
完了画面は「完了しました」が表示されるだけです。

src/Controller/UsersController.php

use App\Controller\AppController;
use Cake\Core\Configure;
use Cake\Event\Event;
use Cake\I18n\Time;

class UsersController extends AppController
{
    public function beforeFilter(Event $event)
    {
        parent::beforeFilter($event);
        $this->Auth->allow([
            'add',
            'confirm',
            'complete',
        ]);
    }

    public function initialize()
    {
        parent::initialize();
    }

    public function add()
    {
        $user = $this->Users->newEntity();
        $ages = Configure::read('User.age');
        $genders = Configure::read('User.gender');

        if ($this->request->is('post')) {
            $user = $this->Users->patchEntity($user, $this->request->data);
            if ($user->errors()) {
                $this->Flash->error('入力内容を確認してください。');
            } else {
                $this->request->session()->write('session.user_add', $user);
                return $this->redirect(['action' => 'confirm']);
            }
        }

        if ($this->request->session()->check('session.user_add')) {
            $user = $this->request->session()->consume('session.user_add');
        }

        $this->set(compact('user', 'ages', 'genders'));
    }

    public function confirm()
    {
        if (!$this->request->session()->check('session.user_add')) {
            return $this->redirect(['action' => 'add']);
        }

        $ages = Configure::read('User.age');
        $genders = Configure::read('User.gender');

        $user = $this->request->session()->read('session.user_add');
        $this->set(compact('user', 'ages', 'genders'));
    }

    public function complete()
    {
        if ($this->request->session()->check('session.user_add')) {
            $user = $this->request->session()->consume('session.user_add');
            
            $result = $this->Users->save($user);
            if (!$result) {
                $this->Flash->error('保存できませんでした。');
                $this->request->session()->write('errors', $user);
                return $this->redirect($this->referer());
            }
        }
    }

}

config (選択肢)


bootstrap.phpにファイルを定義をすると使用することができます。

config/bootstrap.php
Configure::load('user', 'default', false);

定数はこのように定義します。

config/user.php
<?php
return [
    "User"=> [
        "age" => [
            1 => '20歳未満',
            2 => '20-29歳',
            3 => '30-39歳',
            4 => '40-49歳',
            5 => '50-59歳',
            6 => '60-69歳',
            7 => '70-79歳'
        ],
        "gender" => [
            'male' => '男性',
            'female' => '女性'
        ],
    ]
];

view


登録画面

ここでは細かいデザインは置いておいて、大まかなフォームの設定を記述します。

src/Template/Users/add.ctp
<?= $this->Form->create($user, ['type' => 'post', 'autocomplete' => 'off']) ?>
    
    名前
    <?= $this->Form->control('name', ['type' => 'text', 'label' => false, 'required' => false]) ?>
    
    年齢(セレクトボックス)
    <?= $this->Form->control('age', ['type' => 'select', 'label' => false, 'options' => $ages, 'required' => false, 'empty' => '選択してください']) ?>
    
    性別(ラジオボタン)
    <?= $this->Form->control('gender', ['type' => 'radio', 'label' => false, 'required' => false, 'options' => $genders]) ?>
    
    メールアドレス
    <?= $this->Form->control('email', ['type' => 'text', 'label' => false, 'required' => false]) ?>
    
    パスワード
    <?= $this->Form->control('password', ['type' => 'password', 'label' => false, 'div' => false, 'required' => false, 'value' => '']) ?>
    
    パスワード確認用
    <?= $this->Form->control('password_confirm', ['type' => 'password', 'label' => false, 'div' => false, 'required' => false, 'value' => '']) ?>
        
    <?= $this->Form->button('確認画面へ', ['type' => 'submit']) ?>

<?= $this->Form->end() ?>


確認画面

ここでも設定を書き残しておきます。
セッションから値を取得して表示します。

src/Template/Users/confirm.ctp
<?= $this->Form->create($user, ['type' => 'post', 'url' => ['controller' => 'Users', 'action' => 'complete']]) ?>
    
    名前
    <?= $user['name'] ?>
    
    年齢
    <?= $ages[$user['age']] ?>
    
    性別
    <?= $genders[$user['gender']] ?>
    
    メールアドレス
    <?= $user['email'] ?>
    
    <?= $this->Form->button('登録完了', ['type' => 'submit']) ?>

<?= $this->Form->end() ?>

以上です。
完了画面は「完了しました」が表示されるだけなので省略します。

同じCakePHP3でもフォームヘルパーの書き方が変わっていました。
CakePHP4でもこのような感じでいけるのではないかと(願望込み)。。

5
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?