SoftDelete:日本語版
レコードを削除する際に、本当に削除(物理削除)するのではなく
削除フラグを立てることによって、削除モードにする(論理削除)機能。
【環境】
OpenPNE:3.8.15
Symfony:1.4.13
doctrine:1.2.4
設定
ProjectConfiguration
ここまで実装方法などについて書いてきましたが、実はこれだけだと動きません。
Doctrineのデフォルトの設定では、Doctrine_Queryを実行前後で修正することが出来なくなっており、そこを設定してあげる必要があります。この設定の方法がsymfony 1.0とsymfony 1.1で変わってきます。
symfony 1.1ではProjectConfigurationクラスに設定を記述します。
アシアルブログ:Doctrineで論理削除を意識せずに扱う
ProjectConfiguration.class.php
class ProjectConfiguration extends sfProjectConfiguration
{
protected $plugins = array('sfDoctrinePlugin');
public function configureDoctrine($manager)
{
$manager->setAttribute(Doctrine::ATTR_USE_DQL_CALLBACKS, true);
}
}
OpnePNE3
OpenPNE3 では、こういう設定を追加する場所が用意されているっぽい。
まだ、成功体験をしていないので、本当にこれでよいかは不明。
(openpne3)\config\ProjectConfiguration.class.php
public function setupProjectOpenPNEDoctrine($manager)
{
// You can write your own configurations.
// In default, OpenPNE uses foreign key.
// If you want not to use foreign key, comment out the following configuration:
// $manager->setAttribute(Doctrine::ATTR_EXPORT, Doctrine::EXPORT_ALL ^ Doctrine::EXPORT_CONSTRAINTS);
$manager->setAttribute(Doctrine::ATTR_USE_DQL_CALLBACKS, true);
}
schema
schema.yml
Category:
actAs:
- SoftDelete
設定変更
カラム名やデータ型を変更したい場合は、下記のように記述すればよいみたい。
Symfony world:Doctrine SoftDelete behavior usage
→この記事のコメント投稿内情報。未検証。
Category:
actAs:
SoftDelete:
name: is_deleted
type: datetime
力技でやっている人もいるみたい。
@chisei のはてなブログ:Doctrineの論理削除
マニュアルとの差異
このように設定することで、当該テーブルへ deleted_at カラムが追加される
んだけど・・・
公式マニュアル では、delete カラムが追加される、とされている。
データ型も、公式マニュアルでは、TYNYINT とあるけど、実際は DATETIME になる。
バージョンの問題かしらね~。
データ挿入
んで、実際に試してみた。
CSV で、データを突っ込む際に、deleted_at カラムには null を指定しておいたところ
当該カラムの値は 0000-00-00 00:00:00 となった。
CSV から Null を放り込む方法
文系プログラマによるTIPSブログ:MySQLのload dataで日付型にnullをセットする
こちらの記事がビンゴ!
LOAD DATA
LOCAL INFILE 'data.csv'
INTO TABLE [table_name]
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
SET
deleted_at = nullif(deleted_at, '0000-00-00 00:00:00')
;
上記記事では、指定項目がもっといっぱいあったけど
ひとまず、私の今回の環境およびデータでは、上記 SQL にて、
無事に daleted_at カラムへ Null 値を放り込めた。
nullif
どうやら第2引数に、データ型に合わせたデフォルト値を設定するみたい。
なので、その他のデータ型は下記の通り。
SET
datetime = nullif(datetime, '0000-00-00 00:00:00')
date = nullif(date, '0000-00-00')
time = nullif(time, '00:00:00')
データ取得
$result = $this->createQuery('c')
->execute();
データ取得を試みたところ
取得データ数は 0 。
SQL 確認
SQL の確認 のごとく、発行された SQL 文を確認すると、
ちゃんと WHERE 句が付記されている。
WHERE (o.deleted_at IS NULL)
※エイリアスに p を指定しているのに、テーブル名の先頭文字 o をエイリアスにされているが気になるけど。。。
エイリアス o
これは、こちらの指定した DQL から Doctrine が SQL を生成する際に、
指定されたテーブルを順番に o1, o2, o3, … と再指定しているためだった。
その o も、恐らく、テーブル名の頭文字を取っていると思われる。
OpenPNE3 の場合、テーブル接頭辞を付けているため
全テーブルが op_ で始まるのよね。
原因
Doctrine が NULL を探しているのに対して、
データ側は ‘0000-00-00 00:00:00’ という値であるため
スルーされていた。
解決
上記 データ挿入→CSV から Null を放り込む方法 を用いて
値を Null にしてやることで、ちゃんとデータを取得できるようになった。
過去の対応策
$result = $this->createQuery('p')
->andWhere('p.deleted_at = ?', '0000-00-00 00:00:00')
->execute();
これで一応拾ってくることはできた。
とりあえずはこれでいくしかないけど。。。意味なーい!
いつか解明しなければ。。。
(やっと解明できた)
エイリアス
ちなみにテーブルエイリアスを付けないと、上記記述でも拾ってこない。
// NG
$result = $this->createQuery()
->andWhere('deleted_at = ?', '0000-00-00 00:00:00')
->execute();
必ずエイリアスをつける必要があります。
ただしこれはSELECT限定で、DELETEのときはエイリアスがなくても動くようです。
アシアルブログ:Doctrineで論理削除を意識せずに扱う