質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
ORM

ORM(オブジェクト関係マッピング)はオブジェクト指向のシステムとリレーショナルデータベースの間でマッピングを行う技術です。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

データベース設計

データベース設計はデータベースの論理的や物理的な部分を特定する工程です。

FuelPHP

FuelPHPは、軽量高速で開発が可能なPHPのWebアプリケーションフレームワークです。

Q&A

1回答

2892閲覧

FuelPHPのORMでのリレーション設定とDB側での外部キー制約

退会済みユーザー

退会済みユーザー

総合スコア0

ORM

ORM(オブジェクト関係マッピング)はオブジェクト指向のシステムとリレーショナルデータベースの間でマッピングを行う技術です。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

データベース設計

データベース設計はデータベースの論理的や物理的な部分を特定する工程です。

FuelPHP

FuelPHPは、軽量高速で開発が可能なPHPのWebアプリケーションフレームワークです。

2グッド

1クリップ

投稿2017/06/15 01:48

編集2017/06/19 00:41

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\Modeldeleteメソッド(参照)は、親レコードを削除してからリレーション先の子レコードを削除するようになっているため(正確に言うと親レコードの削除前に、リレーション先の子レコードの削除処理を呼び出すのですが、リレーションの処理では親が削除されていないと何もしないので、何も起こりません)、親レコードの削除時に外部キー制約に引っかかってしまい、エラーが発生しています。
このエラーが起こらないように外部キー制約で連鎖削除するようにするとうまくいくのですが、FuelPHPのORMではまず親レコードを削除するので、そのタイミングでDB側の連鎖削除が機能することになり、ORMの連鎖削除では実際には何も削除されず、なんだかORMが意味ないカンジがしてモヤモヤしています。

ORMを使う場合、外部キー制約はORMにまかせて、DB側では一切かけないようにするほうがいいのでしょうか?
それとも上記でやっているように両方で同じように設定するのがよいのでしょうか?
もしくはこれ以外でなにか調整して役割分担させるようにするのがよいのでしょうか?
FuelPHPに限らず、ORMを使うならこうしたほうがいい、自分はこうしているということがございましたら、お教えいただきたいです。

よろしくお願いいたします。

KiyoshiMotoki, ikuwow👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

今回はORMの連鎖削除設定と、DBの外部キー制約での連鎖削除の両方を設定することで解決しました。
ただ、本文中にも書いていますが、なんかスッキリしない感じなので、皆様がどうしているのか、お教えいただければ幸いです。
よろしくお願いいたします。

投稿2017/06/19 00:37

編集2017/06/19 00:39
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問