Дек 10 2008

Мягкое удаление с помощью Soft Delete Behavior

Раздел: МоделиМета @ 23:29

С помощью этого компонента вы можете использовать в своих проектах «мягкое удаление» - т.е. установку флага для пометки удаленных записей, вместо реального их удаления. Зачем это нужно? Например, для хранения предыдущих версий отредактированных записей на блоге, для сохранения архива старых товаров в магазине — применений масса. Я стараюсь во всех своих проектах использовать «мягкое удаление» даже просто для того чтобы исключить ошибку случайного удаления. Заказчики часто обращаются: «ой, а мы удалили, а потом передумали, а можно восстановить?».

Внимание! Я еще не тестировал этот компонент с CakePHP 1.2 RC3. Судя по отзывам в комментариях к компоненту, есть проблемы с совместимостью. Эта запись — перевод документации, в следующей я опишу возможные проблемы и пути их решения.

1. Установка.

Создайте файл soft_deletable.php в папке /app/models/behaviors/.

Для тех моделей, в которых будет применяться «мягкое удаление» создайте специальное поле для хранения флага удаления, например deleted. Значение этого поля будет выставляться в 1 при «удалении» записи. Также, вы можете создать дополнительное поле для хранения времени удаления, например deleted_date.

2. Использование

Самый простой способ подключения этого компонента к вашему приложению, это добавление его названия в массив $actsAs. Например, у вас есть модель Article, привязанная к таблице articles (и в таблице уже созданы поля deleted и deleted_date). Отредактируйте файл модели /app/models/article.php и добавьте в него $actsAs:

<?php  
class Article extends AppModel { 
    var $name = 'Article'; 
    var $actsAs = array('SoftDeletable'); 
} 
?>

И, в общем то, все. Теперь, когда вы используете функцию del(), запись будет удалена «мягко» - поле deleted станет единичкой, а в deleted_date запишется timestamp.

Чтобы изменить настройки компонента, надо добавить массив с новыми настройками к $actsAs. Вы можете изменять следующие настройки:

  • field: имя поля для хранения флага удаления. Можно сделать булевым (или integer(1)). Значением по-умолчанию у поля должен быть 0. При удалении устанавливается в 1. Имя поля по-умолчанию — deleted.
  • field_date: имя поля для хранения времени удаления записи. По-умолчанию — deleted_date. Это поле необязательное. Если вам оно не нужно, то установите значение этой настройки в null.
  • delete: булево значение. Установите в true если хотите чтобы осуществлялось «мягкое удаление», в false – для полного, безвозвратного удаления. По-умолчанию — true.
  • find: тоже булево значение. True – для автоматического добавления условий поиска для выборки только не-удаленных записей. False – для поиска по всем записям. По-умолчанию – true.

Любые другие атрибуты в массиве настроек в формате имя => значение будут рассматриваться компонентом как значения для полей с указанным именем для установки в момент удаления.

Например, вы хотите чтобы при удалении записи из модели Article поле published устанавливалось в 0, а также не хотите чтобы компонент автоматически фильтровал при поиске «удаленные» записи:

<?php  
class Article extends AppModel { 
    var $name = 'Article'; 
    var $actsAs = array('SoftDelete' => array('find' => false, 'published' => '0')); 
} 
?>

3. Изменение стандартных условий поиска

Если не установить параметр find в false, то компонент Soft Delete будет автоматически добавлять специальные условия поиска ко всем вызовам find(), так что модель будет возвращать только не помеченные как удаленные записи.

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

<?php  
class ArticlesController extends AppController { 
    var $name = 'Articles'; 
 
    function index() { 
        $articles = $this->Article->findAll(array('Article.deleted' => array(0, 1))); 
        $this->set('articles', $articles); 
    } 
} 
?>

В этом примере, вы получите и «удаленные» и не-«удаленные» записи, благодаря установке условия отбора по полю deleted. Такой вызов не зависит от параметра find компонента.

4. Дополнительные функции компонента

Также можно временно отключить автоматическое добавление спец-условий, а затем включить обратно с помощью функции компонента enableSoftDeletable(). Она принимает булеву переменную: true для включения условий, false – для выключения.

<?php  
class ArticlesController extends AppController { 
    var $name = 'Articles'; 
 
    function index() { 
        $this->Article->enableSoftDeletable(false); 
        $articles = $this->Article->findAll(); 
        $this->Article->enableSoftDeletable(true); 
 
        $this->set('articles', $articles); 
    } 
} 
?>

Обратите внимание, что при вызове функции enableSoftDeletable() только с одним параметром, вы выключаете не только условия поиска, а полностью всю работу компонента, т.е. записи будут удаляться насовсем. Если вы хотите выключить только условия поиска, то безопаснее указать это:

<?php  
class ArticlesController extends AppController { 
    var $name = 'Articles'; 
 
    function index() { 
        $this->Article->enableSoftDeletable('find', false); 
        $articles = $this->Article->findAll(); 
        $this->Article->enableSoftDeletable('find', true); 
 
        $this->set('articles', $articles); 
    } 
} 
?>

Если вам нужно удалить какую-то запись насовсем, то можно временно выключить функции «мягкого удаления»:

<?php  
class ArticlesController extends AppController { 
    var $name = 'Articles'; 
 
    function index() { 
        $this->Article->enableSoftDeletable('delete', false); 
        $this->Article->del(1); 
    } 
} 
?>

Или можно для этого же использовать специальную функцию hardDelete():

<?php  
class ArticlesController extends AppController { 
    var $name = 'Articles'; 
 
    function index() { 
        $this->Article->hardDelete(1); 
    } 
} 
?>

Если вы хотите очистить таблицу от всех «мягко удаленных» записей и полностью уничтожить их, используйте метод purge():

<?php  
class ArticlesController extends AppController { 
    var $name = 'Articles'; 
 
    function index() { 
        $this->Article->purge(); 
    } 
} 
?>

5. Восстановление записей

Каждую «мягко удаленную» запись можно легко восстановить с помощью метода undelete().

В следующем примере запись сначала удаляется, выводится список всех записей чтобы удостовериться что она удалена, а затем запись восстанавливается и это опять проверяется списком:

<?php  
// Удаляем запись с ID 1 
 
$this->Article->del(1); 
 
// Отображаем все записи (автоматические условия включены,  
// поэтому будут показаны только не-удаленные записи) 
 
debug($this->Article->findAll()); 
 
// Восстанавливаем удаленную запись
 
$this->Article->undelete(1); 
 
// Отображаем все записи
 
debug($this->Article->findAll()); 
?>

Теги: , , ,

3 Responses to “Мягкое удаление с помощью Soft Delete Behavior”

  1. WEB рукоделие » SluggableBehavior — помощник в создании ЧПУ says:

    [...] его проекта Cake Syrup. О другой интересной составляющей, SoftDeletableBehavior, недавно, кстати, можно прочесть здесь.Это расширение не использует Inflector::slug() — когда оно [...]

  2. Lexius says:

    Очень интересный блог, и очень хотелось бы узнать, продолжение материала будет. А то у же целый месяц прошёл, а не одной новой статьи так и не появилось :(

  3. Мета says:

    Продолжение обязательно будет. Сейчас работаю над большим проектом, поэтому совершенно нет времени. Как только сдадим (думаю, уже на днях) - продолжу наполнение блога.

Напиши комментарий!