ホームページ バックエンド開発 PHPチュートリアル Yii2 で join と joinwith multi-table association クエリを使用する

Yii2 で join と joinwith multi-table association クエリを使用する

Jan 21, 2017 am 11:36 AM

テーブル構造

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

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

モデル定義

以下はこれら 4 つのモデルの定義です。関係のみを書き出します

顧客

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

Order

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']);
}
}
ログイン後にコピー

著者

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

hasMany と hasOne は

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) の結果を直接返します

see を使用すると次のコードは、顧客の注文を取得するためのものです

// 执行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 が 1 回実行され、データベース内のデータをクエリします。 $customer オブジェクトはそれぞれ異なるためです。

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

幅パラメータはリレーションシップの名前です。つまり、getCustomer

// 先执行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...
}
ログイン後にコピー

のモデル、注文、顧客で定義されたgetOrdersです。selectを使用して返される列を指定する場合は、返される列に以下が含まれていることを確認してください。 all 関連モデルの関連フィールド。それ以外の場合、関連テーブルのモデルは返されません

$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();
ログイン後にコピー

with にフィルター条件を追加します

100 人を超える顧客の注文をクエリします

//首先执行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();
ログイン後にコピー

100 人の顧客をそれぞれクエリしますcustomer 注文の合計が 100 を超えています

// 下面的代码会执行sql语句:
// SELECT * FROM customer LIMIT 100
// SELECT * FROM order WHERE customer_id IN (1,2,...) AND subtotal>100
$customers = Customer::find()->limit(100)->with([
'orders' => function($query) {
$query->andWhere('subtotal>100');
},
])->all();
ログイン後にコピー

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

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

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

join を使用して次のことができることは誰もが知っています。テーブル間に複数の関連付けを書き込みます。まず、yii2

joinWith( $with, $eagerLoading = true, $joinType = 'LEFT JOIN' )
ログイン後にコピー

$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();
ログイン後にコピー

条件付き

関連付けを定義するときに条件付きを指定することもできます

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();
ログイン後にコピー

結合操作が使用されない場合、つまり結合操作を使用するか直接アクセスする場合属性の関連付けとして。このとき、where条件としてon条件が使用されます。

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

概要

まず、モデルで関連付けを定義する必要があります (たとえば、getOrders の Orders は関連付けです)。次に、モデルで定義された関連付けを with または joinWith で使用します。

関連付けを使用する場合は、コールバック メソッドを指定することもできます。

さらに、関連付け、with、joinWith の条件を指定できます。

この部分は実際には非常に多く、3 つのテーブルの関連付け、逆関連付けなど、まだ完成していない関数もあります。

最も基本的な操作は大体こんな感じです。他にもっと詳しく知りたいことがありましたら、投稿に返信してください。

上記は編集者が紹介した Yii2 のマルチテーブル関連のクエリ (join、joinwith) に関する知識です。ご質問があればメッセージを残してください。編集者が返信します。間に合うように。また、PHP 中国語 Web サイトをサポートしていただきありがとうございます。

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衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

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

SublimeText3 中国語版

SublimeText3 中国語版

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

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

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

PHPのカール:REST APIでPHPカール拡張機能を使用する方法 PHPのカール:REST APIでPHPカール拡張機能を使用する方法 Mar 14, 2025 am 11:42 AM

PHPクライアントURL(CURL)拡張機能は、開発者にとって強力なツールであり、リモートサーバーやREST APIとのシームレスな対話を可能にします。尊敬されるマルチプロトコルファイル転送ライブラリであるLibcurlを活用することにより、PHP Curlは効率的なexecuを促進します

Codecanyonで12の最高のPHPチャットスクリプト Codecanyonで12の最高のPHPチャットスクリプト Mar 13, 2025 pm 12:08 PM

顧客の最も差し迫った問題にリアルタイムでインスタントソリューションを提供したいですか? ライブチャットを使用すると、顧客とのリアルタイムな会話を行い、すぐに問題を解決できます。それはあなたがあなたのカスタムにより速いサービスを提供することを可能にします

PHPにおける後期静的結合の概念を説明します。 PHPにおける後期静的結合の概念を説明します。 Mar 21, 2025 pm 01:33 PM

記事では、PHP 5.3で導入されたPHPの後期静的結合(LSB)について説明し、より柔軟な継承を求める静的メソッドコールのランタイム解像度を可能にします。 LSBの実用的なアプリケーションと潜在的なパフォーマ

JSON Web Tokens(JWT)とPHP APIでのユースケースを説明してください。 JSON Web Tokens(JWT)とPHP APIでのユースケースを説明してください。 Apr 05, 2025 am 12:04 AM

JWTは、JSONに基づくオープン標準であり、主にアイデンティティ認証と情報交換のために、当事者間で情報を安全に送信するために使用されます。 1。JWTは、ヘッダー、ペイロード、署名の3つの部分で構成されています。 2。JWTの実用的な原則には、JWTの生成、JWTの検証、ペイロードの解析という3つのステップが含まれます。 3. PHPでの認証にJWTを使用する場合、JWTを生成および検証でき、ユーザーの役割と許可情報を高度な使用に含めることができます。 4.一般的なエラーには、署名検証障害、トークンの有効期限、およびペイロードが大きくなります。デバッグスキルには、デバッグツールの使用とロギングが含まれます。 5.パフォーマンスの最適化とベストプラクティスには、適切な署名アルゴリズムの使用、有効期間を合理的に設定することが含まれます。

フレームワークセキュリティ機能:脆弱性から保護します。 フレームワークセキュリティ機能:脆弱性から保護します。 Mar 28, 2025 pm 05:11 PM

記事では、入力検証、認証、定期的な更新など、脆弱性から保護するためのフレームワークの重要なセキュリティ機能について説明します。

フレームワークのカスタマイズ/拡張:カスタム機能を追加する方法。 フレームワークのカスタマイズ/拡張:カスタム機能を追加する方法。 Mar 28, 2025 pm 05:12 PM

この記事では、フレームワークにカスタム機能を追加し、アーキテクチャの理解、拡張ポイントの識別、統合とデバッグのベストプラクティスに焦点を当てています。

PHPのCurlライブラリを使用してJSONデータを含むPOSTリクエストを送信する方法は? PHPのCurlライブラリを使用してJSONデータを含むPOSTリクエストを送信する方法は? Apr 01, 2025 pm 03:12 PM

PHP開発でPHPのCurlライブラリを使用してJSONデータを送信すると、外部APIと対話する必要があることがよくあります。一般的な方法の1つは、Curlライブラリを使用して投稿を送信することです。

See all articles