Cakephp 3 retains the object even though the request data is null

I am developing a REST api with cakephp 3 and I encountered strange behavior.

I changed route.config so requests are possible .json, .xml

. I also loaded the component RequestHandler

into the controllers initialization method.

My register action in UserController ()

public function register()
{
    $message = array('code' => '200', 'message' => 'The user could not be saved. Please, try again.');
    $user = $this->Users->newEntity($this->request->data);
    if ($this->request->is('post')) {
        if ($this->Users->save($user)) {
            $message = array('code' => '100', 'message' => 'The user has been registred');
        }
    }
    $this->set([
        'message' => $message,
        'user' => $user,
        '_serialize' => ['message', 'user']
    ]);
}

      

Model check:

 public function validationDefault(Validator $validator)
    {
        $validator
            ->add('id', 'valid', ['rule' => 'numeric'])
            ->allowEmpty('id', 'create');

        $validator
            ->requirePresence('username', 'create');

        $validator
            ->notEmpty('username', 'A username is required')
            ->add('username', [
                'length' => [
                    'rule' => ['minLength', 3],
                    'message' => 'Username need to be at least 3 characters long',
                ]
            ])
            ->notEmpty('password', 'A password is required')
            ->add('password', [
                'length' => [
                    'rule' => ['minLength', 3],
                    'message' => 'Password need to be at least 3 characters long',
                ]
            ]);

        return $validator;
    }

      

Problem: If I make a post request with a content header application/x-www-form-urlencoded

everything works fine, the new user is saved and the validation rules are respected. But if I make a post request like content header application/json

, an empty user will be saved. The reason $this->request->data

is zero. But why does cakephp keep an empty user? (not null is declared in the database username and password)

+3


source to share


1 answer


Transfer null

will not result in verification

The first argument for newEntity()

is optional, so when passed null

it is like you hadn't passed anything, resulting in a new, new, empty object that won't be checked.

This is one of the reasons why you shouldn't do what you are doing there, you shouldn't pass the request data in newEntity()

, but use patchEntity()

for the object created with newEntity()

, instead, made in the code generated by the bake shell.

// ...
$user = $this->Users->newEntity();
if ($this->request->is('post')) {
    $user = $this->Users->patchEntity($user, $this->request->data);
    if ($this->Users->save($user)) {
        // ...
    }
}
// ...

      

Thus, the pass null

will not be accepted and will throw an error instead, since the argument is required and must be an array.

I think the docs should be updated to reflect this.

Use additional application / table rules

Apart from data validation when creating / updating objects, there are also application / table rules that will apply anyway before saving data. By using these rules, you can prevent such problematic save operations no matter how the object was created.

Here's a very simple example that checks for an empty field:



public function buildRules(RulesChecker $rules)
{
    $rules->add(function ($entity, $options) {
        return !empty($entity->get('field'));
    });
    return $rules;
}

      

See also Bookbook> ORM> Data Persistence> Applying Application Rules

Prohibit the use of null

all

In case if null

is an expected value, that is, it is legal that it is null under certain circumstances, then you can even add the correct precautions and check the data for null

before trying to work with it.

Why is the record inserted even though the columns speak NOT NULL

?

Well, which is pretty easy to explain, the query INSERT

generated by the ORM will only contain the fields of the object that are contaminated (changed), and by default, these are only fields that are automatically updated by the Timestamp

behavior, so inserting an empty object might result in something like

INSERT INTO table (created, modified) VALUES ('2015-05-06 11:34:49', '2015-05-06 11:34:49')

      

Depending on your DBMS and configuration, this will not result in any error, MySQL for example will set non-passed columns to their implicit defaults if not in strict mode, so you only get an error if the actual value null

is passed for a specific column NOT NULL

.

+6


source







All Articles