Model::afterDelete does not fire

I cannot get Model::afterDelete to fire after a deletion. I want to perform operations on a successful deletion. I'm thinking that I could overload Model::delete but that probably wouldn't work well with DB transactons.

Does afterDelete fire for anyone under any circumstance? Do I need to set some flags?



41.7k

It appears that adding the behavior Phalcon\Mvc\Model\Behavior\SoftDelete to the model causes the afterDelete event to not fire. So it appears as though it is hacky workaround time.

With SoftDelete enabled:

beforeValidation
beforeValidationOnUpdate
validation
afterValidationOnUpdate
afterValidation
beforeSave
beforeUpdate
afterUpdate
afterSave
beforeDelete

With SoftDelete disabled (removed):

beforeDelete
afterDelete

Wow! The events list is very different.

It appears that the SoftDelete behaviour is consuming "afterDelete" behavior. I think that it should still fire. As it currently stands I need to do some really hacky stuff to run longer proccesses on afterSave or beforeDelete and I don't know if that will break DB transactions.

I'm not doing this now, but then is it possible to have softDelete on a file upload with a table entry if I wanted to delete the file but not the entry? How would I delete the file only after a successful database transaction if I don't have access to afterDelete event?

Should I take this to github? Is SoftDelete broken?



41.7k

I've worked around this by porting the Phalcon 2 Zephir SoftDelete Behavior into PHP and then manually triggering/calling the afterDelete method at the very end of the success condition

This solves one problem but I still don't have cascade delete since the delete operation is canceled. Now I'm looking into how to access the information to manually query delete those records from the model definition.

softDelete isn't really deletion - it's more accurately defined as a save for only 1 field. I think it's a judgement call whether the delete triggers should be fired when softDelete happens.

I think it would be worthwhile bringing up in github, but I think the best solution would be to have it configurable somehow.



41.7k

I thinking about offering a pull request to go with it. I want to flesh out how it could handle cascade deletes as well.

Is Phalcon 2.0 accepting feature requests or is it in a freeze to release?



41.7k

Another thing about the SoftDelete is that with as many side effects as it has it really should be documented better. At least now with Zephir it is fairly easy to see what is going on with it but a newer uses is going to get a brutal smack down with it.



41.7k

Here is my current PHP solution:

class SoftDelete extends Behavior implements BehaviorInterface
{

    /**
     * Class constructor.
     *
     * @param array $options
     */
    public function __construct($options = null)
    {
        parent::__construct($options);
    }

    /**
     *  [email protected]}
     *
     * @param string                      $eventType
     * @param \Phalcon\Mvc\ModelInterface $model
     */
    public function notify($eventType, $model)
    {
        if ($eventType == 'beforeDelete') {
            $options = $this->getOptions();

            $field = $options['field'];
            $value = $options['value'];

            $model->skipOperation(true);

            if ($model->{$field} === $value) {
                return;
            }

            $updateModel = clone $model;
            $updateModel->{$field} = $value;

            if (!$updateModel->save()) {
                foreach ($updateModel->getMessages() as $message) {
                    $model->appendMessage($message);
                }
                return;
            }

            $model->{$field} = $value;

            $model->afterDelete();

            $modelsManager = $model->getModelsManager();
            $hasManyRelations = $modelsManager->getHasMany($model);
            foreach ($hasManyRelations as $relation) {
                $alias = $relation->getOptions()['alias'];
                $relatedModels = $model->{"get{$alias}"}();
                foreach ($relatedModels as $relModel) {
                    $relModel->delete();
                }
            }
        }
    }
}

Good job man!

Here is my current PHP solution:

```php class SoftDelete extends Behavior implements BehaviorInterface {

/** * Class constructor. * * @param array $options */ public function construct($options = null) { parent::construct($options); }

/** * @inheritdoc} * * @param string $eventType * @param \Phalcon\Mvc\ModelInterface $model */ public function notify($eventType, $model) { if ($eventType == 'beforeDelete') { $options = $this->getOptions();

       $field = $options['field'];
     $value = $options['value'];

     $model->skipOperation(true);

     if ($model->{$field} === $value) {
         return;
     }

     $updateModel = clone $model;
     $updateModel->{$field} = $value;

     if (!$updateModel->save()) {
         foreach ($updateModel->getMessages() as $message) {
             $model->appendMessage($message);
         }
         return;
     }

     $model->{$field} = $value;

     $model->afterDelete();

     $modelsManager = $model->getModelsManager();
     $hasManyRelations = $modelsManager->getHasMany($model);
     foreach ($hasManyRelations as $relation) {
         $alias = $relation->getOptions()['alias'];
         $relatedModels = $model->{"get{$alias}"}();
         foreach ($relatedModels as $relModel) {
             $relModel->delete();
         }
     }
 }

} } ```



41.7k

Try some updated SoftDelete code:

Someone said that it isn't working and I haven't checked it in a while and it will probably be several months before I'm testing it again.

edited Oct '15

Did you manage to use getRelated with deleted records?

I used

protected static function softDeleteFetch($parameters = null)
    {
        if (method_exists(get_called_class(), 'getDeleted') === false) {
            return $parameters;
        }
        ...
    }

And extended thes functions find(),findFirst() and count().

 public static function count($parameters = null, $accept_deleted = 0)
    {
        if (!$accept_deleted) {
            $parameters = self::softDeleteFetch($parameters);
        }

        return parent::count($parameters);
    }

It worked with all of them but not with getRelated(). Any help?



41.7k

Sorry, I won't be working on that for months.