XF 2.1 _postSave on same row resulting in forceSet error

asprin

Active member
Hi experts,

In my entity's _postSave function, my use case is to update a column belonging to the same entity. So I'm using the following code:

PHP:
protected function _postSave()
{
    // sys_id is primary key column on the entity
    $upload = $this->app()->request()->getFile('upload', false, false);
    $filename = 'myfile_'.$this->sys_id.'.'.$upload->getExtension(); // so this becomes something like myfile_123.png
    $this->path_to_file = $filename;
}

This is throwing the forceSet error. So I looked at Xenforo's code and found some samples and tried with the following:
PHP:
// sys_id is primary key column on the entity
$upload = $this->app()->request()->getFile('upload', false, false);

$filename = 'myfile_'.$this->sys_id.'.'.$upload->getExtension();
$this->set('path_to_file', $filename, ['forceSet' => true]);
$this->save();

This resulted in Duplicate entry 'xxx' for key 'PRIMARY' error message.

So I'm now out of ideas on how to go about achieving this.

(a) I cannot use the _preSave() function because I need the $this->sys_id value which will not be available in presave.
(b) If I use _postSave() function, I've been unsuccessful at getting it to work.

Any suggestions?
 
Last edited:
Solution
Are you suggesting I write these lines of code after I call the run() method on the formAction object in my public controller that accepts the form input?
The FormAction class exposes a method called complete which you can pass a closure into that will be fired once the form has been successfully executed.
Though for derived data you might want to just make this a getter instead of an actual column:
Yep, this seems like a far better approach. Plus it would save me a column on the table as well. But I'll need to have the file uploaded first.

You really do not want to have such code in entities, just like in your recent thread:
But this is something I need to happen after the insert OR when transaction is about to be committed. Reason being is that I need the primary key value of the just inserted record. Are you suggesting I write these lines of code after I call the run() method on the formAction object in my public controller that accepts the form input?

It's just that I understand entity and form inputs should generally not be tightly coupled but was just wondering if there could be exceptions as well.
 
Are you suggesting I write these lines of code after I call the run() method on the formAction object in my public controller that accepts the form input?
The FormAction class exposes a method called complete which you can pass a closure into that will be fired once the form has been successfully executed.
 
Solution
You could probably do...
PHP:
$this->fastUpdate('path_to_file', $filename);

Though for derived data you might want to just make this a getter instead of an actual column:
This is a "good to know" stuff. Thanks for that.


The FormAction class exposes a method called complete which you can pass a closure into that will be fired once the form has been successfully executed.
Thanks. I'll test this and see how it goes (assuming I can still access the form data in the closure - mainly the uploaded file in it)
 
Last edited:
The FormAction class exposes a method called complete which you can pass a closure into that will be fired once the form has been successfully executed.
It worked. Used the following template:


PHP:
$form->basicEntitySave($theEntity, $input);

$form->complete(function() use ($theEntity)
{
    $uploads = $this->request->getFile('upload', false, false);          
    if($uploads)
    {
        $uploads->requireImage();
        $filename = 'my_file'.$theEntity->sys_id.'.'.$uploads->getExtension();      
        \XF\Util\File::copyFileToAbstractedPath($uploads->getTempFile(), 'path/to/data/folder/'.$filename);
        $theEntity->path_to_file = $filename;
        $theEntity->save();
    }
}

return $form;

The complete method is giving the last insert Id which I'm able to use in the filename.

Cheers for pointing me in the correct direction.
 
Top Bottom