YII関連クエリの分析について

不言
リリース: 2023-04-01 09:56:01
オリジナル
1263 人が閲覧しました

この記事では主に YII 相関クエリの関連情報を紹介します。必要な方は参照してください。

1 複数テーブルの相関クエリの構成。 ##AR を使用して関連クエリを実行する前に、ある 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 があります (たとえば、ユーザーには複数の投稿があります)。 #HAS_ONE (1 つあります) : これは HAS_MANY の特殊なケースです。A は最大 1 つの B を持つことができます (たとえば、ユーザーは最大 1 つのプロファイルを持つことができます)。データベース内の対多の関係。ほとんどの 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)、外部キー。誰に対する外部キーは誰ですか?


(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 (多数の1) 関係。投稿の 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)'),
ログイン後にコピー

この 2 つは多対多の関係があるため、User の代わりに FailParts を使用する必要があります。 FailPart の代わりに使用する必要があります。

ここでの 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 対多の場合: $posts = $author->Post;

多対多の場合: $posts = $author->Post;//本質は 1 つに分割することです。対多および多対 1

#

foreach($posts as $u){ 
$_tmp_titles[] = $u -> title; 
} 
titleStr = implode(', ', $_tmp_titles);
ログイン後にコピー



2. 複数テーブルの関連付けの使用

多くの場合、コントローラーで使用されます

1、読み込みの遅延 (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 インスタンスの観点から見ると、この関連付けはFor

'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、アクティブ ローディング—

(1) 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次查询,而后者只有一次。两者的选择视情况而定。

以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!

相关推荐:

Yii中表单用法实例

Yii2如何实现同时搜索多个字段

如何实现Yii2框架中使用PHPExcel导出Excel文件

以上がYII関連クエリの分析についての詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート