ホームページ >バックエンド開発 >PHPチュートリアル >YII関連クエリの詳細説明
この記事は主にYII関連のクエリの関連情報を紹介します。必要な友達は参照してください。お役に立てれば幸いです。
1. マルチテーブル相関の設定
AR を使用して相関クエリを実行する前に、ある AR クラスが別のクラスにどのように関連しているかを AR に知らせる必要があります。
2 つの AR クラス間の関係は、AR クラスによって表されるデータ テーブル間の関係を通じて直接関連付けられます。 データベースの観点から見ると、テーブル A と B の間には 3 種類のリレーションシップがあります。1 対多 (tbl_user と tbl_post など)、1 対 1 (tbl_user と tbl_profile など)、および多対多多 ( tbl_category や tbl_post などの多対多)。 AR には、4 種類の関係があります:
BELONGS_TO (所属): テーブル A と B の間の関係が 1 対多の場合、テーブル B はテーブル A に属します (たとえば、Post は User に属します)。
HAS_MANY (複数あります): テーブル A と B の関係が 1 対多の場合、A には複数の B があります (たとえば、User には複数の Post があります)
HAS_ONE (1 つあります)。 HAS_MANY の特殊な場合、A には最大 1 つの B があります (たとえば、ユーザーには最大 1 つのプロファイルがあります);
MANY_MANY: これはデータベース内の多対多の関係に対応します。 ほとんどの DBMS は多対多の関係を直接サポートしていないため、多対多の関係を 1 対多の関係に分割するには関係テーブルが必要です。 この例のデータ構造では、tbl_post_category がこの目的に使用されます。 AR 用語では、MANY_MANY を BELONGS_TO と HAS_MANY の組み合わせとして解釈できます。 たとえば、Post は多くの カテゴリに属し、カテゴリには多くのカテゴリがあります。Post.
AR で定義された関係は、CActiveRecord の relationship() メソッドをオーバーライドする必要があります。このメソッドは、関係構成の配列を返します。配列の各要素は、次の形式で単一の関係を表します。
'VarName'=>array('RelationType', 'ClassName', 'ForeignKey', ...additional options)
ここで、VarName は関係の名前であり、RelationType は次の 4 つの定数のいずれかです: self::BELONGS_TO、self::HAS_ONE、self:: HAS_MANY および self: :MANY_MANY; ClassName は、この AR クラスに関連付けられた AR クラスの名前です。ForeignKey は、リレーションシップで使用される外部キー (1 つ以上) を指定します。
明確にする必要があるいくつかの点:
(1)、VarName は何を参照していますか? 詳細については、以下の例 2 を参照してください。
(2)、関係タイプ。
self::HAS_MANY、self::BELONGS_TO、self::MANY_MANY、self::HAS_ONE の合計 4 種類があります。
(3)、クラス名。つまり、別の関連付けられた ../model/classname.php です。
(4)、ForeignKey。誰に対する外部キーは誰ですか?
(5)、追加条件
ER図
例1、1対多および多対1の関係(投稿とユーザーの関係)
1) models/Post.php
class Post extends CActiveRecord { ...... public function relations() { return array( 'author'=>array(self::BELONGS_TO, 'User', 'author_id'), ); } }
投稿とユーザーの関係は BELONGS_TO (多対一) の関係であり、投稿の author_id を通じてユーザーに関連付けられます。
Post の author_id は外部キーであり、User に関連付けられています。
注: ここでの VarName は作成者、つまりオブジェクトです。
(2) models/User.php
class User extends CActiveRecord { ...... public function relations() { return array( 'posts'=>array(self::HAS_MANY, 'Post', 'author_id'), 'profile'=>array(self::HAS_ONE, 'Profile', 'owner_id'), ); } }
User にとって、Post との関係は HAS_MANY (1 対多) の関係です。そして、Post の author_id を通じて Post に関連付けられます。
例 2、多対多の関係
FailParts.php
'Users' => array(self::MANY_MANY, 'User', 'fail_parts_user(fail_parts_id, user_id)'),
User.php
'FailParts' => array(self::MANY_MANY, 'FailParts', 'fail_parts_user(user_id, fail_parts_id)'),
二人はたくさんいるので-多くの関係があるため、User の代わりに Users を使用し、FailPart の代わりに FailParts を使用します。
ここでの Users と FailParts は以前の VarName です。
例 3、1 対 1 の関係
は比較的単純なので、ここでは省略します。
2、VarNameについて。
クラス A.php の場合、'VarName'=>array('RelationType', 'B', 'ForeignKey', ...追加オプション)
ここで、VarName は基本的に B と同じです。しかし、必ずしもまったく同じであるとは限りません。このとき、A の views/A/xx.php にある VarName を通じて B とその属性値にアクセスできます。
1対1の場合: A->VarName
多対1の場合: author_name = $post->Author->name;
1対多の場合: $ photos = $author->Post;
多対多の場合: $posts = $author->Post;//本質は、1対多と多対1に分割することです
foreach($posts as $u){ $_tmp_titles[] = $u -> title; } titleStr = implode(', ', $_tmp_titles);
2. コントローラー
1でのマルチテーブル関連付けの使用、遅延読み込み
(1) 多対一
$post = Post::model()->findByPk(10);
$author = $post ->author;
コメント: ここでの本質は 1 対 1 です。
(2) 1 対多
$user = User::model()->findByPk(10);
$posts = $user->posts;
(3) 多対多
集中する必要があります 注: 2 つの ID の間には順序関係があります。
$repairInfo インスタンスの観点からは、関連付けは
'FailParts' => array(self::MANY_MANY, 'FailParts', 'repair_mapping(repair_info_id,fail_parts_id)'),
である必要があります。また、$failParts インスタンスの観点からは、関連付けは
'RepairInfos' => array(self::MANY_MANY, 'RepairInfo', 'repair_mapping(fail_parts_id, repair_info_id)'),
而前面也已经指出,不需要双方都配置,只需需要的一方设置即可。
之前曾使用过的笨方法:
/*方法一:使用表关系(多对多)*/ $fails = $repairInfo->FailParts;//在$repairInfo中使用 /*方法二:使用原始方法*/ $id = $repairInfo->id; $maps = RepairMapping::model()->findAll("repair_info_id = $id"); $f_ids = array(); foreach($maps as $map){ array_push($f_ids, $maps[0]->fail_parts_id); } $f_idsStr = implode(',',$f_ids); $fails = FailParts::model()->findAll("id IN ($f_idsStr)");
2,主动加载——with
(1)一对多
(2)多对多
$posts = Post::model()->('author')->findAll();
例子:
User.php
//查询一个机房$idc_id的所有用户 function getAdminedUsersByIdc($idc_id){ $c = new CDbCriteria(); $c->join = "JOIN idc_user on t.id=idc_user.user_id"; $c->condition = "idc_user.idc_id=$idc_id"; return User::model()->with('Idcs')->findAll($c); } //规则中配置 'Idcs' => array(self::MANY_MANY, 'Idc', 'idc_user(user_id, idc_id)'),
批注:没有with('Idcs'),执行后的结果也一样。只不过不再是eager loading。
三、带参数的关联配置
常见的条件有
1,condition 按某个表的某个字段加过滤条件
例如:
//在User的model里定义,如下关联关系 'doingOutsources' => array(self::MANY_MANY, 'Outsource', 'outsource_user(user_id, outsource_id)', 'condition' => "doingOutsources.status_id IN(" . Status::ASSIGNED . "," . Status::STARTED ."," . Status::REJECTED .")"),
//结论:condition是array里指定model的一个字段。
显然,doingOutsources是真实数据表Outsource的别名,所以在condition中可以使用doingOutsources.status_id,当然也可以使用Outsource.status_id。另本表名user的默认别名是t。
2,order 按某个表的某个字段升序或降序
//在RepairInfo的model里定义,如下关联关系 'WorkSheet' => array(self::HAS_MANY, 'WorkSheet', 'repair_info_id', order => 'created_at desc'), //调用 $worksheets = $repair_info->WorkSheet; //此时$worksheets是按降序排列
//结论:order是array里指定model的一个字段。
with
joinType
select
params
on
alias
together
group
having
index
还有用于lazy loading的
limit 只取5个或10个
offset
through
官方手册
'posts'=>array(self::HAS_MANY, 'post', 'author_id', 'order'=>'posts.create_time DESC', 'with'=>'categories'),
四、静态查询(仅用于HAS_MANY和MANY_MANY)
关键字:self:STAT
1,基本用法。例如,
class Post extends CActiveRecord { ...... public function relations() { return array( 'commentCount'=>array(self::STAT, 'Comment', 'post_id'), 'categoryCount'=>array(self::STAT,'Category','post_category(post_id, category_id)'); ); } }
2,静态查询也支持上面的各种条件查询
如
'doingOutsourceCount' => array(self::STAT, 'Outsource', 'outsource_user(user_id, outsource_id)', 'condition' => "outsource.status_id IN(" . Status::ASSIGNED . "," . Status::STARTED ."," . Status::REJECTED .")"),
其他查询还包括
condition 使用较多
order
select
defaultValue
params
group
having
3,静态查询的加载方式
可以使用lazy loading方式
$post->commentCount.
也可以使用eager loading方式
$posts = Post::model()->with('commentCount','categoryCount')->findAll();
注with中字符串一定是别名。
两者的性能比较:
如果需要取所有post的所有comment,前者需要2N+1次查询,而后者只有一次。两者的选择视情况而定。
相关推荐:
以上がYII関連クエリの詳細説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。