XF 2.2 how to check if record exists before saving with basicEntitySave

XboxUnlimited

Active member
Hi,

I'm using $form->basicEntitySave to save inputs from a form into my database which all works well, the only problem is that it allows duplicates which I don't want, so I'm probably missing something obvious but how do you check if the record exists before saving? Is there a build in function for that?

Thanks
 

asprin

Active member
Two ways you can achieve this:

(a) By setting unique property in the entity structure definition
PHP:
'my_field' => ['type' => self::STR, 'unique' => 'my_error_phrase_name'] // my_error_phrase_name is the phrase name. You can also use a hardcoded string

(b) By using the __preSave() function in the entity structure definition. You can validate the uniqueness in this function.
 

mjda

Well-known member
Isn't there also a function to insert or update an entity? I was thinking I'd seen this somewhere, but I'm not able to find it now. I'll look more, if I remember, this weekend, assuming nobody else has answered by then.
 

asprin

Active member
(b) By using the __preSave() function in the entity structure definition. You can validate the uniqueness in this function.
An example for this as well
PHP:
protected function _preSave()
{
    $exists = $this->finder('YourAddonShortName')
        ->where('col_name', $this->col_name)->fetchOne();

    if ($exists && $exists != $this)
    {
        $this->error(\XF::phrase('duplicate_record_found'));
    }
}

Replace col_name with the one defined in your entity.
 

XboxUnlimited

Active member
An example for this as well
PHP:
protected function _preSave()
{
    $exists = $this->finder('YourAddonShortName')
        ->where('col_name', $this->col_name)->fetchOne();

    if ($exists && $exists != $this)
    {
        $this->error(\XF::phrase('duplicate_record_found'));
    }
}

Replace col_name with the one defined in your entity.

I have added this to my controller (is that right?), but it doesn't seem to do anything, looks like the _presave code is being ignored,
 

XboxUnlimited

Active member
It doesn't go in the controller. It's a function of the entity's structure class (found usually at <xen_root>/src/addons/YOURADDON/Entity/YourEntity.php)
Thanks, I'm getting there now kind of working, how do I stop it saving the record if duplicate exist, I get the warning but it still saves it.

So basically if duplicate error is detected I want to skip the save
 
Last edited:

briansol

Well-known member
this->error() should kill it. Makes me think there's something else in your flow that might be out of sync (eg, it saves before pre save fires for some reason)

are you using basicentitysave standard process?
 

XboxUnlimited

Active member
this->error() should kill it. Makes me think there's something else in your flow that might be out of sync (eg, it saves before pre save fires for some reason)

are you using basicentitysave standard process?
Yes, I am using basicEntitySave in my controller, however it's highly likely I'm doing something wrong here :)

So basically I have a form in my template and the data is saved to the database once submitted, however is you click the submit quickly many times it will save the data multiple times which is what I want to avoid - I'm sure it's something simple I'm missing or have setup wrong
 
Last edited:

XboxUnlimited

Active member
this->error() should kill it. Makes me think there's something else in your flow that might be out of sync (eg, it saves before pre save fires for some reason)

are you using basicentitysave standard process?
Ok I have this working now (nearly) - this->error() does kill it so that works ok, but what I would like to do is kill it without any onscreen message and then redirect to another page, is that possible? Thanks
 

XboxUnlimited

Active member
you should be able to do a redirect right in presave.

try:

if($yourpresavedupe check fails){
return $this->redirect($url);
}
Thanks, redirect doesn't appear to work from the _preSave, it gives and error, the same redirect code does work from the controller not with in the entity -

** Update - you have to use "return \XF::app()->router('public')->buildLink(''$url);' **
 
Last edited:

XboxUnlimited

Active member
An example for this as well
PHP:
protected function _preSave()
{
    $exists = $this->finder('YourAddonShortName')
        ->where('col_name', $this->col_name)->fetchOne();

    if ($exists && $exists != $this)
    {
        $this->error(\XF::phrase('duplicate_record_found'));
    }
}

Replace col_name with the one defined in your entity.

Couldn't get it working with pre-save but I have got this working now by using the finder to check for the record before calling the basicEntitySave - might not be the "correct" way of doing it but it works (y)
 
Top