Search code examples
formsvalidationuniquephalcon

Phalcon uniqueness on update


folks. The uniqueness validator in my form works as expected on adding new records, but on updating an exsisting record, it throws an error that the url already exists. It exists, in fact, but only in the current record.

Here is my controller:

$feed = Feeds::findFirst($id);
$feedForm = new FeedForm($feed, array('edit' => true));

if ($this->request->isPost() == true) {
    $feedData = $this->request->getPost();
    if ($feedForm->isValid($feedData, $feed)) {
        if ($feed->save()) {
            $this->flash->success("Feed successfuly updated.");
            } else {
                $this->flash->error("Update failed.");
            }
       } else {
           foreach ($feedForm->getMessages() as $message) {
               $this->flash->error($message);
           }
    }
}

And my form class:

class FeedForm extends FormBase {

    public $options;

    public function initialize($entity = null, $options = null) {
        parent::initialize();
        $this->setEntity($entity);
        $this->options = $options;

        $status = new Radio('status');
        $status->addValidator(
                new PresenceOf(
                array(
            'message' => 'The status is required.'
                )
        ));
        $this->add($status);

        $name = new Text('name');
        $name->addValidator(
                new PresenceOf(
                array(
            'message' => 'The name is required.'
                )
        ));
        $name->addValidator(
                new StringLength(
                array(
            'max' => 50,
            'messageMaximum' => 'The name you entered is too long.'
                )
        ));
        $this->add($name);

        $xml = new Text('xml');
        $xml->addValidator(
                new PresenceOf(
                array(
            'message' => 'The URL address is required.'
                )
        ));
        $xml->addValidator(
                new StringLength(
                array(
            'max' => 2048,
            'messageMaximum' => 'The URL address you entered is too long.'
                )
        ));
        $xml->addValidator(
                new Url(
                array(
            'message' => 'The URL you entered is invalid.'
                )
        ));
        $xml->addValidator(
                new Uniqueness(
                array(
            'model' => 'Sravnisite\Admin\Models\Feeds',
            'table' => 'feeds',
            'column' => 'xml',
            'message' => 'The entered URL address already exists.'
                )
        ));

        $periodOptions = array();
        for ($i = 4; $i <= 24; $i++) {
            array_push($periodOptions, $i);
        }
        $this->add($xml);

        $period = new Select('period', $periodOptions);
        $period->addValidator(
                new PresenceOf(
                array(
            'message' => 'The period is required.'
                )
        ));
        $this->add($period);

        $shopID = new Select('shop_id', Shops::find(), array('using' => array('id', 'name')));
        $shopID->addValidator(
                new PresenceOf(
                array(
            'message' => 'The shop is required.'
                )
        ));
        $this->add($shopID);
    }

}

Any ideas?


Solution

  • The form validation doesn't know to ignore the record you are updating - so for uniqueness it finds the record you're trying to update and gives an error. You could do some complicated find logic to keep the uniqueness validation in the form but it is better moved to the model. Your result would end up something like:

    Controller

    $feed = Feeds::findFirst($id);
    $feedForm = new FeedForm($feed, array('edit' => true));
    
    if ($this->request->isPost() == true) {
        $feedData = $this->request->getPost();
        if ($feedForm->isValid($feedData, $feed)) {
            if ($feed->save()) {
                $this->flash->success("Feed successfuly updated.");
                } else {
                    $this->flash->error("Update failed.");
                    // Get each of the validation messages from the model
                    foreach ($feed->getMessages() as $message) {
                        $this->flash->error($message);
                    }
                }
           } else {
               foreach ($feedForm->getMessages() as $message) {
                   $this->flash->error($message);
               }
        }
    }
    

    Form

    // Exactly the same as you currently have but without the Uniqueness Validator
    

    Model

    class Feeds extends Phalcon\Mvc\Model
    
    /**
     * Validate that xml URLs are unique
     */
    public function validation()
    {
        $this->validate(new Uniqueness(array(
            "field" => "xml",
            "message" => "The url must be unique."
        )));
    
        return $this->validationHasFailed() != true;
    }