前提・実現したいこと

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