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
{
}