If you pass patchEntity(), it will be converted to NULL.

Asked 1 years ago, Updated 1 years ago, 45 views

We are creating a user management system with PHP (CakePHP).
In the input form to add users on the management screen, the select box is used in the entry of permissions.When submitting the form, the following error message occurred:

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$endlogged
 */
class User extensions Entity
{

    /**
     * Fields that can be assigned newEntity() or patchEntity().
     *
     * Note that when '*' is set to true, this allow all unspecified fields to
     * be assigned.For security purpos, it is approved 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;

useApp\Model\Entity\User;
use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;

/**
 * Users Model
 *
 */
class UsersTable extensions 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',
          US>'joinType'=>'INNER'
        ]);
    }

    /**
     * Default validation rules.
     *
     * @param\Cake\Validation\Validator$validatorValidator instance.
     * @return\Cake\Validation\Validator
     */
    public function validationDefault (Validator $validator)
    {
        $validator
            ->add('id', 'valid', ['rule'=>'numerical')
            ->allowEmpty('id', 'create');

        $validator
            ->requirePresence('name', 'create')
            ->notEmpty('name');

        $validator
            ->requirePresence('password','create')
            ->notEmpty('password');

        $validator
            ->requirePresence ('role', 'create')
            ->notEmpty('role');

        $validator
            ->add('endlogged', 'valid', ['rule'=>'datetime')
            ->allowEmpty('endlogged');

        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 extensions 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">
        <lic class="heading">?=__('Actions'?>/li>
        <li><?=$this->Html->link(__('List Users'),['action'=>'index'])?>>/li>
    </ul>
</nav>
<div class="users form large-9medium-8columns 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>

Table Configuration

create table roles(
  role char(100) not null default 'admin',
  PRIMARY KEY (`role')
);

create table users(
  id unsigned not null auto_increment,
  name varchar(100) not null,
  password varchar(255) not null,
  role char(100) not null default 'admin',
  logged datetime default null,
  PRIMARY KEY(`id`),
  CONSTRAINT fk_role
    FOREIGN KEY (role)
    REFERENCES roles (roles)
    ON UPDATE CASCADE ON DELETE RESTRICT
);

The error message simply specifies NOT NULL in the role column, so NULL is only being scolded.
You can create a select box by associating it.The reason seems to be that if the value sent in the form goes through patchEntity(), the role will be converted to NULL.In other words, I thought there was a problem with validationDefault(), but I didn't do such a strange validation, so I looked into various things, but I couldn't solve it.

Please lend me your wisdom.Thank you for your cooperation.

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;
===== Same as above, so omitted ====
}
[
    'name' = > 'yamada',
    'password' = > 'ymymy',
    'role' = > 'admin'
     // The Roles value is displayed properly in the select box, select admin among the choices and send it.
     // The value sent in the post is admin, so this is as expected.
]
object(App\Model\Entity\User){

    'name' = > 'yamada',
    'password' = > 'ymymy',
    Convert to 'role' = > null, // null !!!
    '[new]' = > true,
    '[accessible]' =>[
        '*' =>true
    ],
    '[dirty]' =>[
        'name' = > true,
        'password' = > true,
        'role' = > true
    ],
    '[original]' = > [ ],
    '[virtual]' = > [ ],
    '[errors]' =>[],
    '[repository]' = > 'Users'

}

CakePHP3.1.14

php mysql cakephp

2022-09-30 16:03

1 Answers

CakePHP automatically recognizes associations defined in the association as entity fields.

In UsersTable

$this->belongsTo('Roles',[
          'foreignKey' = > 'role',
          US>'joinType'=>'INNER'
        ]);

Therefore, User.role is to be treated as a Role entity.

There is a conflict here because User.role is already defined as a text field.

As OOPer pointed out, you can either give the POST value in the form 'role'=>['role'=>'admin'] or
Rename the Roles association properties to eliminate conflicts.

$this->belongsTo('Roles',[
          'foreignKey' = > 'role',
          'joinType' = > 'INNER',
          'propertyName' = > 'role_obj',
        ]);

You can now specify User.role as the text value and User.role_obj as the Role entity.


2022-09-30 16:03

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.