0

I want to create a CakePHP Behavior that will handle the data before they are stored in the db.

For example I have Posts add form like:

// Post title
echo $this->Form->input('title',['value'=>'aaa']);
// Post has many Photos (names)
echo $this->Form->input('photos.0.name',['value'=>'zzz']);
echo $this->Form->input('photos.1.name',['value'=>'hhh']);
echo $this->Form->input('photos.2.name',['value'=>'fff']);

PostsController:

public function add()
{
    $post = $this->Posts->newEntity();
    if ($this->request->is('post')) {
        $post = $this->Posts->patchEntity($post, $this->request->data);

        if ($this->Posts->save($post)) {
            $this->Flash->success(__('The post has been saved.'));
            return $this->redirect(['action' => 'index']);
        } else {
            $this->Flash->error(__('The post could not be saved. Please, try again.'));
        }
    }
    $this->set(compact('post'));
    $this->set('_serialize', ['post']);
}

Data from the form is properly stored in a database.

Next, I bake a new behavior (eg, MyBehavoir), and attach it to PhotosTable. I want to retrieve all three "name" field, process them eg. convert via ucfirst method, and send it back to be stored in the database.

public function beforeMarshal(Event $event, ArrayObject $data, ArrayObject $options)
{
    $data['name'] = ucfirst($data['name']);
    debug($data);
}
 // debug return three outputs for every field

object(ArrayObject) {
    name => 'Zzz' // Hhh, Fff
}

But only the first result (Zzz) is saved.

What should I do, to save all fields after processing in Behavior?

Also,

public function beforeSave(Event $event, Entity $entity)
{   
    debug($entity);
    return true;
}

debug show only data from first fields

object(App\Model\Entity\Photo) {

    'name' => 'Zzz',
    'post_id' => (int) 486,
    ...
Salines
  • 5,674
  • 3
  • 25
  • 50

1 Answers1

1

This is a misuse of the beforeMarshall function. What you should be doing is using an Entity Mutator method to set the property as you want it before it is persisted.

By creating a method such as protected function _setName() in your PhotoEntity you can change the name before the entity is persisted.

You can find out more about Entity Mutators in the book.

David Yell
  • 11,756
  • 13
  • 61
  • 100
  • Modifying Request Data Before Building Entities If you need to modify request data before it is converted into entities, you can use the Model.beforeMarshal event. This event lets you manipulate the request data just before entities are created: http://book.cakephp.org/3.0/en/orm/saving-data.html#before-marshal – Salines Oct 07 '15 at 16:06
  • 1
    Marshalling is converting of request data into entities, you want to change the entity data. Perhaps I didn't explain, but you've no need to change the data before the entities are created. You can do it inside the entity. – David Yell Oct 07 '15 at 16:09
  • Thank you for your reply, my fault, I put in afterSave exit method, and stop storing multiple data. I have the habit to put die or exit after a debug function. I did not know the model and behavior repeatedly used when storing multiple data. – Salines Oct 07 '15 at 18:29