cakephp: [RFC] EntityContext should not use ServerRequest::getData() to restore input values

Reported in #japanese channel on our Slack.

This is a (multiple allowed):

  • bug

  • enhancement

  • feature-discussion (RFC)

  • CakePHP Version: 3.4.12

  • Platform and Target: Non-related

What you did

Created a bulk edit action:

// In UsersController.php
public function bulkEdit() {
    $users = $this->paginate($this->Users);

    $data = $this->request->getData('users');
    if ($data) {
        // ...
        $this->Users->patchEntities($users, $data);
        // ...
    }

    $this->set(compact('users'));
}

And the template:

// In bulk_edit.ctp
<?= $this->Form->create($users, ['novalidate' => true]) ?>
<?php foreach ($users as $i => $user): ?>
<fieldset>
<legend><?= h($user->id) ?></legend>
<?php
echo $this->Form->control("$i.id", ['name' => "users[$i][id]"]);
echo $this->Form->control("$i.email", ['name' => "users[$i][email]"]);
?>
</fieldset>
<?php endforeach ?>
<?= $this->Form->button(__('Submit')) ?>
<?= $this->Form->end() ?>

(Note that name options are given to prevent the pollution of $_POST.)

Entered an invalid email in a email field, and submitted the form. bulk-edit1

What happened

Got a correct error message expectedly. However, the invalid email I entered was not restored unexpectedly. bulk-edit2

What you expected to happen

The form values should be restored.

Why this issue happens

Because EntityContext uses SeverRequest::getData() to restore form values, and it fails to do it if name options are given. See https://github.com/cakephp/cakephp/blob/ee2ead47b4b5b25a520a91d0b50a039c193af7eb/src/View/Form/EntityContext.php#L234

Suggestion

EntityContext should not use ServerRequest::getData(). Instead, it should use Entity::invalid() (getInvalidField() in 3.5) for invalid properties, and Entity::get() for normal properties. Or adding new properties something like patched may be better.

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 18 (17 by maintainers)

Most upvoted comments

We could do a change like that in 4.1.0

Great 😃

What do you think about giving priority to context with [‘context’, ‘data’] by default?

@diegosardina Using the valueSources list would be a good solution and approach to simplifying the context objects. We could do a change like that in 4.1.0

I worry about not reading from the request as people may have properties in their forms that are not assigned to entities. We’d be breaking those scenarios if we removed reading from request data.

Yup, for e.g. “I agree to terms” checkboxes, password confirm fields etc.

I worry about not reading from the request as people may have properties in their forms that are not assigned to entities. We’d be breaking those scenarios if we removed reading from request data.