ORMのリレーション機能を使用する場合、DB側の外部キー制約はどのように設定するのがよいのか判断できず、よい方策があればお教えいただきたいと思います。
2017-06-19 追記
今回ぶつかっていた案件では、結局のところDB側でも同様の外部キー制約(連鎖削除する)を設けるようにして解決しました。
ただ、他の方はどうしているのかを知りたく、また1つの答えのようなものもないように思いますので、ORMを使った場合のDB側との使い分けについて(FuelPHPに限らず)、「自分はこうしている」というものがあれば、お教えいただけると幸いです。
現在、FuelPHPのORMを使用しています。
下記のように質問モデルと回答モデルの間にリレーションを設定していると、質問モデル(Model_Question
)のdelete
メソッドを呼び出してレコードの削除を行うと、関連する回答レコードも削除されるようになります。
php
1class Model_Question extends \Orm\Model 2{ 3 protected static $_has_many = [ 4 'answers' => [ 5 'key_from' => 'question_id', 6 'model_to' => 'Model_Answer', 7 'key_to' => 'question_id', 8 'cascade_save' => false, 9 'cascade_delete' => true, 10 ], 11 ]; 12} 13 14class Model_Answer extends \Orm\Model 15{ 16 protected static $_belongs_to = [ 17 'question' => [ 18 'key_from' => 'question_id', 19 'model_to' => 'Model_Question', 20 'key_to' => 'question_id', 21 'cascade_save' => false, 22 'cascade_delete' => false, 23 ], 24 ]; 25}
ここで直接SQLを使った処理を行った場合(クエリビルダなども含む)でもデータの矛盾が起こらないようにしたいと思い、DBで外部キー制約をかけるとします。ただ連鎖削除はORMがやってくれるので、DB側では下記のように削除時には何もしないようにしました。
sql
1CONSTRAINT `fk_answers` FOREIGN KEY (`question_id`) REFERENCES `questions` (`question_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
この状態で質問モデルで削除操作を行うと下記のようなエラーが発生してしまいます。MySQLの外部キー制約が連鎖削除しないように設定されているのが原因です。
Fuel\Core\Database_Exception [ 23000 ]: SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails (`sample-db`.`answers`, CONSTRAINT `fk_answers` FOREIGN KEY (`question_id`) REFERENCES `questions` (`question_id`) ON DELETE NO ACTION ON UPDATE NO ACTION) with query: "DELETE FROM `questions` WHERE `question_id` = 'XXXX' LIMIT 1"
ORMで連鎖削除するように設定しているので、ここはすんなりいってほしいところですが、FuelPHPのORMのモデル\Orm\Model
のdelete
メソッド(参照)は、親レコードを削除してからリレーション先の子レコードを削除するようになっているため(正確に言うと親レコードの削除前に、リレーション先の子レコードの削除処理を呼び出すのですが、リレーションの処理では親が削除されていないと何もしないので、何も起こりません)、親レコードの削除時に外部キー制約に引っかかってしまい、エラーが発生しています。
このエラーが起こらないように外部キー制約で連鎖削除するようにするとうまくいくのですが、FuelPHPのORMではまず親レコードを削除するので、そのタイミングでDB側の連鎖削除が機能することになり、ORMの連鎖削除では実際には何も削除されず、なんだかORMが意味ないカンジがしてモヤモヤしています。
ORMを使う場合、外部キー制約はORMにまかせて、DB側では一切かけないようにするほうがいいのでしょうか?
それとも上記でやっているように両方で同じように設定するのがよいのでしょうか?
もしくはこれ以外でなにか調整して役割分担させるようにするのがよいのでしょうか?
FuelPHPに限らず、ORMを使うならこうしたほうがいい、自分はこうしているということがございましたら、お教えいただきたいです。
よろしくお願いいたします。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。