ホームページ バックエンド開発 PHPチュートリアル Yii2 で join と joinwith マルチテーブル関連クエリを使用する方法

Yii2 で join と joinwith マルチテーブル関連クエリを使用する方法

Dec 29, 2017 pm 05:57 PM
join yii2

この記事では主に Yii2 でのマルチテーブル関連付けクエリ (join、joinwith) の使い方を紹介します。必要な方は参考にしてください。お役に立てれば幸いです。

テーブル構造

現在、customer テーブル、order テーブル、book テーブル、author テーブルがあります。

Customer テーブル Customer (id customer_name)
Order テーブル Order (id order_name customer_id book_id)
Book テーブル (id book_name) author_id )
著者テーブル (id author_name)

モデル定義

以下はこれら 4 つのモデルの定義であり、それらの間の関係のみが書かれています

顧客


class Customer extends \yii\db\ActiveRecord
{
// 这是获取客户的订单,由上面我们知道这个是一对多的关联,一个客户有多个订单
public function getOrders()
{
// 第一个参数为要关联的子表模型类名,
// 第二个参数指定 通过子表的customer_id,关联主表的id字段
return $this->hasMany(Order::className(), ['customer_id' => 'id']);
}
}
ログイン後にコピー

注文


class Order extends \yii\db\ActiveRecord
{
// 获取订单所属用户
public function getCustomer()
{
//同样第一个参数指定关联的子表模型类名
//
return $this->hasOne(Customer::className(), ['id' => 'customer_id']);
}
// 获取订单中所有图书
public function getBooks()
{
//同样第一个参数指定关联的子表模型类名
//
return $this->hasMany(Book::className(), ['id' => 'book_id']);
}
}
ログイン後にコピー

Book


class Book extends \yii\db\ActiveRecord
{
// 获取图书的作者
public function getAuthor()
{
//同样第一个参数指定关联的子表模型类名
return $this->hasOne(Author::className(), ['id' => 'author_id']);
}
}
ログイン後にコピー

Author


class Autor extends \yii\db\ActiveRecord
{
}
ログイン後にコピー

hasMany、Yii2のテーブル間には2種類の関連付けが使用されますモデル間の 2 つの関連付けを指定します。 一対多: hasMany

一対一: hasOne


戻り結果: 両方のメソッドの戻り結果は yiidbActiveQuery オブジェクトです


最初のパラメーター: 関連付けられたモデルのクラス名。

2 番目のパラメーター: は配列であり、キーは関連付けられたモデルの属性、値は現在のモデルの属性です。

関連付けの使用法

これで、顧客のすべての注文情報を取得できます

// 获取一个客户信息
$customer = Customer::findOne(1);
$orders = $customer->orders; // 通过在Customer中定义的关联方法(getOrders())来获取这个客户的所有的订单。
ログイン後にコピー

上記の2行のコードは、次のSQLステートメントを生成します


SELECT * FROM customer WHERE id=1;
SELECT * FROM order WHERE customer_id=1;
ログイン後にコピー


関連付け結果キャッシュ

お客様のご注文に変更があった場合は、

$orders = $customer->orders;
ログイン後にコピー

に再度お電話させていただきますが、再度ご注文をいただいた時点で変更がないことがわかります。その理由は、$customer->orders が初めて実行されるときにのみデータベースがクエリされ、その結果がキャッシュされ、後続のクエリでは SQL が実行されないためです。


では、SQL を再度実行したい場合はどうすればよいでしょうか?

unset($customer->orders);
$customer->orders;
ログイン後にコピー

を実行すると、データベースからデータを取得できます。


複数の関連付けを定義する

同様に、Customer で複数の関連付けを定義することもできます。 返された注文の合計数が 100 を超える場合。


class Customer extends \yii\db\ActiveRecord
{
public function getBigOrders($threshold = 100)
{
return $this->hasMany(Order::className(), ['customer_id' => 'id'])
->where('subtotal > :threshold', [':threshold' => $threshold])
->orderBy('id');
}
}
ログイン後にコピー


に関連付けられた 2 つのアクセス方法は、上に示したとおりです。

$customer->bigOrders
ログイン後にコピー
を使用すると、100 を超えるすべての注文が取得されます。 200 を超える注文を返したい場合は、次のように記述できます

$orders = $customer->getBigOrders(200)->all();
ログイン後にコピー

上記からわかるように、関連付けにアクセスするには 2 つの方法があります

関数として呼び出された場合、ActiveQuery オブジェクトは返される ($customer-> ;getOrders()->all())


属性として呼び出された場合、モデルの結果 ($customer->orders) が直接返されます

については、次のコードは、顧客の注文を取得するためのものです


// 执行sql语句: SELECT * FROM customer WHERE id=1
$customer = Customer::findOne(1);
//执行sql:SELECT * FROM order WHERE customer_id=1
$orders1 = $customer->orders;
//这个不会执行sql,直接使用上面的缓存结果
$orders2 = $customer->orders;
ログイン後にコピー

ここで 100 人のユーザーを取り出し、各ユーザーの注文にアクセスしたい場合、上記の理解に基づいて、次のコードを書くことができます

// 执行sql语句: SELECT * FROM customer LIMIT 100
$customers = Customer::find()->limit(100)->all();
foreach ($customers as $customer) {
// 执行sql: SELECT * FROM order WHERE customer_id=...
$orders = $customer->orders;
// 处理订单。。。
}
ログイン後にコピー

ただし、本当にこのように書きたい場合は、 foreach の各ループで SQL が実行され、データベース内のデータをクエリします。 $customer オブジェクトはそれぞれ異なるためです。

上記の問題を解決するには、yiidbActiveQuery::with() を使用できます。

幅パラメータはリレーションシップの名前です。つまり、getCustomer のモデル、注文、顧客で定義された getOrders です


// 先执行sql: SELECT * FROM customer LIMIT 100;
// SELECT * FROM orders WHERE customer_id IN (1,2,...)
$customers = Customer::find()->limit(100)
->with('orders')->all();
foreach ($customers as $customer) {
// 在这个循环的时候就不会再执行sql了
$orders = $customer->orders;
// ...handle $orders...
}
ログイン後にコピー

select を使用して返される列を指定する場合は、返される列が関連付けられたモデルの関連付けられたフィールドを含みます。それ以外の場合、関連付けられたテーブルのモデルは返されません。各顧客の注文の合計が 100 を超えています

$orders = Order::find()->select(['id', 'amount'])->with('customer')->all();
// $orders[0]->customer 的结果将会是null
// 因为上面的select中没有返回所关联的模型(customer)中的指定的关联字段。
// 如果加上customer_id,$orders[0]->customer就可以返回正确的结果
$orders = Order::find()->select(['id', 'amount', 'customer_id'])->with('customer')->all();
ログイン後にコピー

ここで、width パラメーターは配列です。キーは関連付けられた名前、値はコールバック関数です。

つまり、注文の関連付けによって返された ActiveQuery に対して、$query->andWhere('subtotal>100'); を実行します


テーブルの関連付けには joinWith を使用します

複数のテーブル間の関連付けを書き込むには、join on を使用します。まず、yii2

//首先执行sql: SELECT * FROM customer WHERE id=1
$customer = Customer::findOne(1);
// 再执行查询订单的sql语句:SELECT * FROM order WHERE customer_id=1 AND subtotal>100
$orders = $customer->getOrders()->where('subtotal>100')->all();
ログイン後にコピー

$with の joinWit の宣言を見てください。データ型は文字列または配列です。文字列の場合は、モデルで定義された関連付けの名前です (サブクラスの場合もあります)。協会)。


配列の場合、キーはモデル内の getXXX 形式で定義された関連付けであり、値はこの関連付けに対するさらなるコールバック操作です。

$eagerLoading $with に関連付けられたモデルのデータをロードするかどうか。

$joinType 联接类型,可用值为:LEFT JOIN、INNER JOIN,默认值为LEFT JOIN


// 订单表和客户表以Left join的方式关联。
// 查找所有订单,并以客户 ID 和订单 ID 排序
$orders = Order::find()->joinWith('customer')->orderBy('customer.id, order.id')->all();
// 订单表和客户表以Inner join的方式关联
// 查找所有的订单和书
$orders = Order::find()->innerJoinWith('books')->all();
// 使用inner join 连接order中的 books关联和customer关联。
// 并对custmer关联再次进行回调过滤:找出24小时内注册客户包含书籍的订单
$orders = Order::find()->innerJoinWith([
'books',
'customer' => function ($query) {
$query->where('customer.created_at > ' . (time() - 24 * 3600));
}
])->all();
// 使用left join连接 books关联,books关联再用left join 连接 author关联
$orders = Order::find()->joinWith('books.author')->all();
ログイン後にコピー

在实现上,Yii 先执行满足JOIN查询条件的SQL语句,把结果填充到主模型中, 然后再为每个关联执行一条查询语句, 并填充相应的关联模型。


// Order和books关联 inner join ,但不获取books关联对应的数据
$orders = Order::find()->innerJoinWith('books', false)->all();
ログイン後にコピー

On条件

在定义关联的时候还可以指定on条件


class User extends ActiveRecord
{
public function getBooks()
{
return $this->hasMany(Item::className(), ['owner_id' => 'id'])->onCondition(['category_id' => 1]);
}
}
ログイン後にコピー

在joinWith中使用


//先查询主模型(User)的数据, SELECT user.* FROM user LEFT JOIN item ON item.owner_id=user.id AND category_id=1
// 然后再根据关联条件查询相关模型数据SELECT * FROM item WHERE owner_id IN (...) AND category_id=1
// 这两个在查询的过程中都使用了 on条件。
$users = User::find()->joinWith('books')->all();
ログイン後にコピー

如果没有使用join操作,即使用的是with 或者 直接以属性来访问关联。这个时候on条件会作为where 条件。

// SELECT * FROM user WHERE id=10
$user = User::findOne(10);
ログイン後にコピー

总结

首先需要在模型中定义好关联(如getOrders中的Orders为一个关联)

然后在with或者joinWith中使用在模型中定义的关联。

其中在使用关联的时候还可以指定回调方法。

再有就是可以给关联、with、joinWith指定where或者on条件。

相关推荐:

Yii2实现QQ互联登录

Yii2使用缓存的简单解析

Yii2实现rbac权限控制

以上がYii2 で join と joinwith マルチテーブル関連クエリを使用する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

MySQLでJOINを使用する方法 MySQLでJOINを使用する方法 Jun 04, 2023 am 08:02 AM

JOIN の意味は英語の「結合」と同じで、2 つのテーブルを結合するもので、内部結合、外部結合、右結合、左結合、自然結合に大別されます。まず 2 つのテーブルを作成します。例として次のものが使用されます。 CREATETABLEt_blog(idINTPRIMARYKEYAUTO_INCREMENT,titleVARCHAR(50),typeIdINT);SELECT*FROMt_blog;+----+------+--------+ | id|title|typeId|+----+----------+--------+|1|aaa|1||2|bbb|2||3|ccc|3 |

yii2でjqueryを削除する方法 yii2でjqueryを削除する方法 Feb 17, 2023 am 09:55 AM

yii2 から jquery を削除する方法: 1. AppAsset.php ファイルを編集し、変数 $depends の「yii\web\YiiAsset」値をコメント アウトします; 2. main.php ファイルを編集し、設定「'yii」を以下に追加しますフィールド「components」\web\JqueryAsset' => ['js' => [],'sourcePath' => null,]," を使用して jquery スクリプトを削除します。

MySQL Join の使用原理は何ですか? MySQL Join の使用原理は何ですか? May 26, 2023 am 10:07 AM

結合タイプ leftjoin は、左側のテーブルを駆動テーブルとして使用し、左側のテーブルを結果セットの基礎として使用します。右側のテーブルのデータは結果セットに接続されます。rightjoin は、右側のテーブルを駆動テーブルとして使用し、右側のテーブルを結果セットとして使用します。左側のテーブルを接続するための結果セットの基礎 データは結果セットの innerjoin に追加されます 結果セットは 2 つのテーブルの共通部分を取得します fulljoin 結果セットは 2 つのテーブルの結合を取得します MySQL にはfulljoin。union と Unionall の違いは、union がクロスジョインのデカルト積の重複を排除することです。where 条件が使用されていない場合、結果セットは、関連付けられた 2 つのテーブル行の積になります。違いは、クロスジョインが結果を作成するときの点です。設定されている場合は、on 条件に従って渡されます。

MySQLでJOINを使用する方法 MySQLでJOINを使用する方法 Jun 03, 2023 am 09:30 AM

はじめに A のユニーク + AB のパブリック B のユニーク + AB のパブリック AB のパブリック A のユニーク B のユニーク A のユニーク + B のユニーク + AB のパブリック A のユニーク + B のユニーク テーブル部門テーブルの作成の練習 DROPTABLEIFEXISTS`dept`;CREATETABLE`dept`(`dept_id`int( 11)NOTNULLAUTO_INCREMENT,`dept_name`varchar(30)DEFAULTNULL,`dept_number`int(11)DEFAULTNULL,PRIMARYKEY(`dept_id`))ENGINE =InnoDBAUT

mysqlの結合クエリと複数のクエリ方法とは何ですか? mysqlの結合クエリと複数のクエリ方法とは何ですか? Jun 02, 2023 pm 04:29 PM

結合クエリと複数のクエリを比較すると、MySQL の複数テーブル関連のクエリと複数の単一テーブルのクエリのどちらが効率的ですか?データの量が十分に大きくない場合、結合を使用しても問題ありませんが、通常はサービス層で実行されます。第一に、スタンドアロン データベースのコンピューティング リソースは非常に高価であり、データベースは書き込みと書き込みの両方に対応する必要があります。データベースを作成するために、スループットが高くなり、数百マイクロ秒からミリ秒の遅延ギャップを気にする必要がなくなり、ビジネスはより多くの計算をサービス層に投入するようになります。結局のところ、コンピューティングリソースは水平拡張が容易で、データベースは難しいので、ほとんどのビジネスは純粋なコンピューティング操作をサービス層に置き、データベースをトランザクション機能を備えたkvシステムとして使用する重いビジネスです。

MySQL の JOIN 関数を使用してテーブルを結合する MySQL の JOIN 関数を使用してテーブルを結合する Jul 26, 2023 am 08:37 AM

MySQL の JOIN 関数を使用してテーブルを結合する MySQL では、JOIN は非常に一般的な操作であり、テーブル間に関連付けられたフィールドに基づいて 2 つ以上のテーブルを結合できます。これにより、クエリを実行して複数のテーブルから関連データを取得することが容易になり、クエリの効率と柔軟性が向上します。この記事では、コード例を使用して、MySQL の JOIN 関数を使用してテーブルを結合する方法を示します。まず、学生とスコアの 2 つのサンプル テーブルを作成します。学生テーブルには学生が含まれています

いくつかの厳選された CTF 演習は、yii2 フレームワークの学習に役立ちます。 いくつかの厳選された CTF 演習は、yii2 フレームワークの学習に役立ちます。 Feb 23, 2022 am 10:33 AM

この記事では、yii2 フレームワークについて紹介し、いくつかの CTF 演習を共有し、それを使用して yii2 フレームワークを学習します。

YII2 フレームワークを使用して Redis 拡張機能をインストールする方法 YII2 フレームワークを使用して Redis 拡張機能をインストールする方法 May 26, 2023 pm 06:41 PM

1. yii2-redis のマスター ブランチの Windows バージョンを、composer でダウンロードする必要があります。 2. 解凍して、vendor/yiisoft にコピーします。 3. 'yiisoft/yii2-redis'=>array('name'=>'yiisoft) を追加します。 yiisoft /yii2-redis','version'=>'2.0 の extensions.php にコピーします。

See all articles