M
M
Mark2020-01-12 17:43:29
Yii
Mark, 2020-01-12 17:43:29

What is the best way to implement cascading hiding in nesting?

Situation : Suppose there is the following nesting in a service: Category->Groups->Services.

Illustration

kiss_9kb.1578833041.png

Task : It is necessary to organize a pseudo-deletion, that is, formally the user does not see the category / group / service, but in fact they are in the database.
That is, so that the "is deleted" flag becomes active.
But it is necessary to do this with cascading. For example: if a category is "deleted" - with it the groups nested in it, and behind the groups - the services nested in them.
If only a group means related services.
Illustration

kiss_11kb.1578833367.png

The question is: what is the best way to implement this?
Now I see from the options - to implement deletion events for categories, groups and in a chain they will "pull" each other and "delete".
But, perhaps, this can be somehow "resolved" from the side of the database? In fact, before the emergence of this problem, it was she who solved the issue of cascade (but physical) removal.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
D
Dmitry Kim, 2020-01-15
@kimono

I did not check for errors, but I think you can do something like this:

interface SoftDeletableInterface
{
    public function softDelete() : bool;

    public function getChildren() : array;
}

abstract class SoftDeletableModel extends ActiveRecord implements SoftDeletableInterface
{
    public function getChildren() : array
    {
        return [];
    }

    final public function softDelete(bool $inTransaction = false) : bool
    {
        if ($inTransaction) {
            $this->softDeleteInternal();

            return true;
        }

        $transaction = \Yii::$app->db->beginTransaction();
        try {
            $this->softDeleteInternal();
            $transaction->commit();

            return true;
        } catch (\Exception $exception) {
            $transaction->rollBack();

            return false;
        }
    }

    private function softDeleteInternal() : void
    {
        $this->updateAttributes(['is_deleted' => true]);

        foreach ($this->getChildren() as $children) {
            foreach ((array)$children as $child) {
                $child->softDelete(true);
            }
        }
    }
}

class Category extends SoftDeletableModel
{
    public function getChildren() : array
    {
        return $this->groups;
    }

    public function getGroups()
    {
        return $this->hasMany(Group::class, ['category_id' => 'id']);
    }
}

class Group extends SoftDeletableModel
{
    public function getChildren() : array
    {
        return [$this->services, $this->users] /* array of array */;
    }

    public function getServices()
    {
        return $this->hasMany(Service::class, ['group_id' => 'id']);
    }

    public function getUsers()
    {
        return $this->hasMany(User::class, ['group_id' => 'id']);
    }
}

class Service extends SoftDeletableModel
{
}

class User extends SoftDeletableModel
{
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question