ikkez / f3-cortex

A multi-engine ORM / ODM for the PHP Fat-Free Framework
GNU General Public License v3.0
118 stars 22 forks source link

Beforeerase function is not triggered #105

Open adkurz opened 4 years ago

adkurz commented 4 years ago

I have some tables with 1-n-relations. To delete them without any foreign key problems, al these models have onerase in their constructors. Example:

Model Category:
    $this->beforeerase(
      function($self) {
        // Delete all items of this category if there is one:
        $item = new Item();
        $item->erase(['category_id = ?', $self->_id]);
        return true;
      }
    );

Model Item:

  public function __construct() {
    parent::__construct();
    // before erase function, delete all contracts of the deleted item:
    $this->beforeerase(
      function($self) {
          // Delete all contracts of this item
        $contract = new Contract();
        $contract->erase(['objekt_id = ?', $self->_id]);
        return true;
      }
    );

If I now want to erase a category, like $category->load(...), $category->erase(), The onerase function of the category-model is triggered, but not the onerase function of the items. If I use a foreach loop instead, it works, but is slow:

    $this->beforeerase(
      function($self) {
        // Delete all items of this category if there is one:
        $item = new Item();
        $items = $item->find(['kategorie_id = ?', $self->_id]);
        foreach ($items as $value) {
          $value->erase();
        } // foreach
        return true;
      }
    );

Could you please fix this problem?

adkurz commented 4 years ago

Sorry, not erase, but find in the before the foreach loop.

ikkez commented 4 years ago

This cannot be fixed that way, because the erase query does not return the ID's of affected / deleted rows. So we would end up with preloading all records that should be deleted, run the beforeease and then decide if it should be deleted or not... which then is the same method you're already using, so it wont be any faster. If you pass a $filter to the erase method, the beforeerase handler is ignored because of that, as state here https://fatfreeframework.com/3.7/sql-mapper#erase If you have an idea how to solve that more efficiently, I'm all ears.