SoftDelete realtionships deletion

Hi.

I set up a relationship and add a foreign key : "action" => Relation::ACTION_CASCADE on the "master" class (on the hasMany) The thing is I made my own SoftDelete with trait and interface, and when I call delete on the master class, I don't find any ways (and dunno if it's possible, so) to retrieve related records on the BeforeDelete event to manually delete them (as the beforeDelete event is not called on the "slave" class records if I stop the deletion).

Hi @etshy first check that you have not declared the cascade on delete in the table relationship

Second the method notify have 2 params notify($eventType, $model) then you should have something like that

use Phalcon\Mvc\Model\Behavior;
use Phalcon\Mvc\Model\BehaviorInterface;

class MySoftDelete extends Behavior implements BehaviorInterface {
  public function notify($eventType, $model) {
      if ($eventType === 'beforeDelete') {
          $model->getRelated('aliasOfSlaves')->delete(); // here delete children
      }
  }
}

Good luck



4.1k
edited Dec '17

hmm I'll need to learn more about custom behaviour.

Is there a way to retrieve dynamically the aliasOfSlaves ? Or I need to list all the lalias that couls be deleted ?

because from what I already know, create a behaviour is equivalent to what I did with my trait SoftDelete

<?php

namespace App\Models\Traits;

trait ModelSoftDeletableTrait
{

    /**
     * @var bool
     */
    protected $deleted;

    /**
     * @return bool
     */
    public function isDeleted()
    {
        return $this->deleted;
    }

    /**
     * @param bool $deleted
     */
    public function setDeleted($deleted)
    {
        $this->deleted = $deleted;
    }

    public function beforeDelete()
    {
        //We update the model
        $this->setDeleted(true);
        $this->save();
        //TODO find a way to retrieve relation hasMany and launch a delete for the related records

        //return false to stop the deletion
        return false;
    }
}

Edit : Talking about behaviour, I tried to use the timestampable behaviour (instead of setting the date manually on beforeValidationOnUpdate event) but it doesn't work.

here is my behaviour

$this->addBehavior(
            new Timestampable(
                [
                    'beforeValidationOnCreate' => [
                        'field'  => 'createdAt',
                        'format' => function () {
                            $datetime = new \DateTime();
                            return $datetime->format(\DateTime::ISO8601);
                        }
                    ],
                    'beforeValidationOnUpdate' => [
                        'field'  => 'updatedAt',
                        'format' => function () {
                            $datetime = new \DateTime();
                            return $datetime->format(\DateTime::ISO8601);
                        }
                    ]
                ]
            )
        );

in the initialize of my model (in the model directly, not in a trait or another class) but it doesn't work, my field updatedAt is updated but to 0000-00-00 00:00:00, not the current date. and for some reasons I can't do a dump in the function to check the datetime value.

the aliasOfSlaves is the alias defined in you hasMany relationship.

You can do anythink you want

use Phalcon\Mvc\Model\Behavior;
use Phalcon\Mvc\Model\BehaviorInterface;

class MySoftDelete extends Behavior implements BehaviorInterface {
  public function notify($eventType, $model) {
      if ($eventType === 'beforeDelete') {
          // find relations by alias and then delete
          $model->getRelated('alias')->delete();

          // or find relations by quering and tne delete
          $model->getModelsManager()
          ->createBuilder()
          ->from(Slaves::class)
          ->where('parentId = {id:int}')
          ->getQuery()
          ->execute([
            'id' => $model->getId()
          ])->delete();
      }
  }
}

The var_dump() or die()into anonymous functions didn't work. I prefer encapsulate the behavior in classes to reuse the code and try to make a more abstract code with params for configuration and you can use var_dump() and die().

The timestampable behavior look fine but try with return $datetime->format('Y-m-d H:i:sP'); and check the columns names and data types.

Good luck