Kohana ORM: Удаляем записи с корнем. Целостность БД

kohana
Думаю, всем понятно, что при удалении записи нужно следить за ссылочной целостностью. То есть если уж решили удалить запись, то надо сделать чтобы нигде не осталось ссылок на удалённую запись.

Если есть элементы, привязанные к этой записи по схеме много-к-одному или один-к-одному, то логично рассматривать эти записи как подчинённые и соответственно удалять их. Если же где-то в других таблицах есть записи привязанные к удаляемой записи по схеме много-ко-многим, логично удалять только связь.

Для этого надо у каждой модели прописать свою процедуру delete(), в которой и прописать алгоритм удаления. Но если база данных построена правильно, если все подчинённые записи подключены именно как «много-к-одному», а не «многие-ко-многим» и т.д., то можно автоматизировать этот процесс и написать одну функцию на все случаи жизни.

public function delete()
{
    if ($this -> loaded()){
	foreach($this->_has_many as $key => $value){
	    foreach( $this -> {$key}-> find_all() as $element){
		if(isset($value['through'])){
		    $this->remove($key, $element);
		}else{
		    $element -> delete();
		}
	    }
	}
    }
    return parent::delete();
}

Вот так.

Ну и естественно, БД должна быть сделана по уму и модели прописаны правильно. А иначе, можно ведь нечаянно удалить что-то нужное :)

Kohana ORM: Удаляем записи с корнем. Целостность БД: 4 комментария

  1. altesack Автор записи

    Можно и так =) Но для использования ON DELETE CASCADE вроде надо обязательно использовать InnoDB.

    Не нравится мне эти форейнкеи. При их использовании я частенько натыкался на проблемы. Например, надо накатить базу данных, а он дропнуть не даёт. Говорит, ошибка внешнего ключа.

  2. amberlex

    Я тоже всегда обеспечиваю целостность средствами БД. Потом можно вообще не думать о целостности, даже если в коде напартачил или еще че, она не даст этому всему делу поломаться. Да и схему БД можно визуально посмотреть в том же Adminer, что очень удобно.

  3. Beka

    Хорошая идея, но не хватает связи один к одному

    public function delete()
    {
    if ($this -> loaded())
    {
    foreach($this->_has_many as $key => $value)
    {
    foreach( $this ->{$key}-> find_all() as $element)
    {
    if(isset($value['through']))
    {
    $this->remove($key, $element);
    }
    else
    {
    $element->delete();
    }
    }
    }

    foreach($this->_has_one as $key => $value)
    {
    $this ->{$key}->delete();
    }
    }
    return parent::delete();
    }

Комментарии запрещены.