patchEntity()を通すとNULLに変換されてしまう
前提・実現したいこと
PHP(CakePHP)でユーザー管理システムを作っています。
管理画面でユーザーを追加する入力フォームで、権限の入力箇所にセレクトボックスを使っております。フォームを送信すると、以下のエラーメッセージが発生しました。
発生している問題・エラーメッセージ
Error: SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'role' cannot be null
該当のソースコード
Model/Entity/User
<?php
namespace App\Model\Entity;
use Cake\ORM\Entity;
/**
* User Entity.
*
* @property int $id
* @property string $name
* @property string $password
* @property string $role
* @property \Cake\I18n\Time $endlogined
*/
class User extends Entity
{
/**
* Fields that can be mass assigned using newEntity() or patchEntity().
*
* Note that when '*' is set to true, this allows all unspecified fields to
* be mass assigned. For security purposes, it is advised to set '*' to false
* (or remove it), and explicitly make individual fields accessible as needed.
*
* @var array
*/
protected $_accessible = [
'*' => true,
'id' => false,
];
/**
* Fields that are excluded from JSON an array versions of the entity.
*
* @var array
*/
protected $_hidden = [
'password'
];
}
Model/Table/UsersTable
<?php
namespace App\Model\Table;
use App\Model\Entity\User;
use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;
/**
* Users Model
*
*/
class UsersTable extends Table
{
/**
* Initialize method
*
* @param array $config The configuration for the Table.
* @return void
*/
public function initialize(array $config)
{
parent::initialize($config);
$this->table('users');
$this->displayField('name');
$this->primaryKey('id');
$this->belongsTo('Roles', [
'foreignKey' => 'role',
'joinType' => 'INNER'
]);
}
/**
* Default validation rules.
*
* @param \Cake\Validation\Validator $validator Validator instance.
* @return \Cake\Validation\Validator
*/
public function validationDefault(Validator $validator)
{
$validator
->add('id', 'valid', ['rule' => 'numeric'])
->allowEmpty('id', 'create');
$validator
->requirePresence('name', 'create')
->notEmpty('name');
$validator
->requirePresence('password', 'create')
->notEmpty('password');
$validator
->requirePresence('role', 'create')
->notEmpty('role');
$validator
->add('endlogined', 'valid', ['rule' => 'datetime'])
->allowEmpty('endlogined');
return $validator;
}
}
Controller/Admin/UsersController
<?php
namespace App\Controller\Admin;
use App\Controller\AppController;
use Cake\Event\Event;
use Cake\ORM\Table;
use Cake\ORM\TableRegistry;
use Cake\Error\Debugger;
class UsersController extends AppController
{
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' => 'index']);
} else {
$this->Flash->error(__('The user could not be saved. Please, try again.'));
}
}
$roles = $this->Users->Roles->find('list', ['limit' => 200]);
$this->set(compact('user', 'roles'));
$this->set('_serialize', ['user']);
}
}
Template/Admin/Users/add.ctp
<nav class="large-3 medium-4 columns" id="actions-sidebar">
<ul class="side-nav">
<li class="heading"><?= __('Actions') ?></li>
<li><?= $this->Html->link(__('List Users'), ['action' => 'index']) ?></li>
</ul>
</nav>
<div class="users form large-9 medium-8 columns content">
<?= $this->Form->create($user) ?>
<fieldset>
<legend><?= __('Add User') ?></legend>
<?php
echo $this->Form->input('name');
echo $this->Form->input('password');
echo $this->Form->input('role', ['options' => $roles]);
?>
</fieldset>
<?= $this->Form->button(__('Submit')) ?>
<?= $this->Form->end() ?>
</div>
テーブル構成
create table roles (
role char(100) not null default 'admin',
PRIMARY KEY (`role`)
);
create table users (
id int unsigned not null auto_increment,
name varchar(100) not null,
password varchar(255) not null,
role char(100) not null default 'admin',
endlogined datetime default null,
PRIMARY KEY (`id`),
CONSTRAINT fk_role
FOREIGN KEY (role)
REFERENCES roles (role)
ON UPDATE CASCADE ON DELETE RESTRICT
);
試したこと
エラーメッセージは単純にroleカラムにNOT NULLを指定しているので、NULLを怒られているだけ。
アソシエーションで紐付けて、セレクトボックスの生成はできています。原因は、フォームで送信した値がpatchEntity()を通すとroleがNULLに変換されてしまうことだと思われます。つまり、validationDefault()に問題があるのかと思いきや、そういったおかしなバリデーションもしていないし、ということで、色々調べたりしたのですが、解決できませんでした。
みなさんのお知恵をお貸しください。よろしくお願いいたします。
問題あると思われるpatchEntityの前後の出力結果
Controller/Admin/UsersController
public function add()
{
$user = $this->Users->newEntity();
if ($this->request->is('post')) {
Debugger::dump($this->request->data);
$user = $this->Users->patchEntity($user, $this->request->data);
Debugger::dump($user);
exit;
=====上に同じなので、省略====
}
[
'name' => 'yamada',
'password' => 'ymymym',
'role' => 'admin'
// セレクトボックスでちゃんとRolesの値が表示できていて、選択肢のうち、adminを選択して送信。
// postで送信された値はadminなのでここまでは想定通り。
]
object(App\Model\Entity\User) {
'name' => 'yamada',
'password' => 'ymymym',
'role' => null, // nullに変換される!!!!!
'[new]' => true,
'[accessible]' => [
'*' => true
],
'[dirty]' => [
'name' => true,
'password' => true,
'role' => true
],
'[original]' => [],
'[virtual]' => [],
'[errors]' => [],
'[repository]' => 'Users'
}
補足情報(FW/ツールのバージョンなど)
CakePHP3.1.14