BadHorsie
BadHorsie

Reputation: 14564

CakePHP 3 - Simplest way to only allow saving of specific fields on entity

In Cake 2 you could save a model and specify which fields you wanted to restrict the save to.

Is there a built-in way to do this simply in Cake 3? For example, if the request data is being put straight into a new entity which is then saved, how can I tell the method to only save the fields I allow?

Simplified Example

// User makes a request; their POST data goes directly into the entity
$customer = $this->Customers->newEntity($this->request->data);
$this->Customers->save($customer);

The obvious danger here is that I can set any properties I like on that customer entity, via the request. In reality, I only want to allowing saving of a couple of specific fields.

Upvotes: 1

Views: 2727

Answers (2)

ndm
ndm

Reputation: 60473

That's what mass assignment protection is there for, in the form of the $_accessible entity property

class Customer extends Entity
{
    // allow only `first_name` and `last_name` to be mass assigned
    protected $_accessible = [
        'first_name' => true,
        'last_name' => true
    ];
}

and the fieldList and accessibleFields options for Table::newEntity/newEntities/patchEntity/patchEntities()

// allow only `first_name` and `last_name` to be mass assigned,
// ignoring the entity accessible defaults
$customer = $this->Customers->newEntity($this->request->data(), [
    'fieldList' => [
        'first_name',
        'last_name'
    ]
]);

The accessibleFields option will change the accessibility of the specified fields only. Also it will actually modify the entity, ie unlike fieldList, which the marshaller will simply use as the whitelist instead of the entity defaults, accessibleFields will change the values of the entities $_accessible property!

See

Upvotes: 4

Pradeep
Pradeep

Reputation: 9707

There are two ways of protecting you against this problem. The first one is by setting the default columns that can be safely set from a request using the Mass Assignment feature in the entities.

The _accessible property allows you to provide a map of properties and whether or not they can be mass-assigned. The values true and false indicate whether a field can or cannot be mass-assigned:

http://book.cakephp.org/3.0/en/orm/entities.html#entities-mass-assignment

    namespace App\Model\Entity;

    use Cake\ORM\Entity;

    class Article extends Entity
    {
        protected $_accessible = [
       'title' => true,
        'body' => true,
         '*' => false,
    ];
   }

The second way is by using the fieldList option when creating or merging data into an entity:

        // Contains ['user_id' => 100, 'title' => 'Hacked!'];
          $data = $this->request->data;

        // Only allow title to be changed
          $entity = $this->patchEntity($entity, $data, [
                  'fieldList' => ['title']
                 ]);
           $this->save($entity);

You can also control which properties can be assigned for associations:

            // Only allow changing the title and tags
           // and the tag name is the only column that can be set
              $entity = $this->patchEntity($entity, $data, [
                       'fieldList' => ['title', 'tags'],
                       'associated' => ['Tags' => ['fieldList' => ['name']]]
                       ]);
              $this->save($entity);

Using this feature is handy when you have many different functions your users can access and you want to let your users edit different data based on their privileges.

The fieldList options is also accepted by the newEntity(), newEntities() and patchEntities() methods.

For more :http://book.cakephp.org/3.0/en/orm/saving-data.html

Upvotes: 2

Related Questions