Home > Back-end >  "Cannot use object of type Laminas\Diactoros\UploadedFile as array" with multi-upload in
"Cannot use object of type Laminas\Diactoros\UploadedFile as array" with multi-upload in

Time:11-17

I'm creating a plugin FileManager where all uploads are stored in a single table. This plugin has an AttachmentBehavior that attaches a hasMany association.

I use multi-files input in templates Articles/add.php and Articles/edit.php to upload files that will be linked to an article :

// Example in Articles/edit.php
echo $this->Form->create($article, ['type' => 'file']);
echo $this->Form->control('title', /*[...]*/);
echo $this->Form->control('body', /*[...]*/);
echo $this->Form->control('pieces_jointes', ['type' => 'file', 'multiple' => true, 'name' => 'pieces_jointes[]']);

I can add new article with files, there's no problem.

I can edit an article that doesn't not have file to add files, there's no problem.

But when I edit an article that already have files to add some more files, I have an error "Cannot use object of type Laminas\Diactoros\UploadedFile as array" This error appears when the entity Article is patched. Here's my controller :

// in ArticlesController.php
public function edit($id)
{
    $article = $this->Articles->findById($id)->firstOrFail();

    if ($this->request->is(['post', 'put'])) {
        debug($article); // $article->pieces_jointes is an array of entities of my files table.
        debug($this->request->getData()); // $this->request->getData()->pieces_jointes is an array of UplaodedFile objects
        $article = $this->Articles->patchEntity($article, $this->request->getData()); // The error occurs here

        if ($this->Articles->save($article)) {
            return $this->redirect(/*[...]*/);
        }
    }

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

It's not really clear for me about what is going on. Does anyone can explain me and help me to solve this problem ?

CodePudding user response:

Removing associated file Model in AttachmentBehavior::beforeMarshal seems to fix the Error :

// in AttachmentBehavior
public function beforeMarshal(Event $event, ArrayObject $data, ArrayObject $options)
{
    foreach ($this->_fields as $field => $value) {
        // Remove associated file Model (PiecesJointes, ...) in $options['associated']
        $options['associated'] = collection($options['associated'])
                    ->reject(function ($modelAssociated, $key) use ($value) {
                        return $modelAssociated == $value['alias'];
                    })
                    ->toArray();

        // [...]
    }
}

But I would need the confirmation that I'm right (?)

CodePudding user response:

You shouldn't use the same name for the upload field and the association property, that's a clash waiting to happen in various places of the framework.

Rename the fields in your forms, etc, so that it's using a name that neither matches any association property, nor any column name, and then let your behavior and stuff process the input using the "external" name, and convert it to the "internal" name after transforming the input into the structure required for saving the data.

  • Related