Heim  >  Artikel  >  Backend-Entwicklung  >  Verwenden Sie Join und Join mit Multi-Table-Assoziationsabfragen in Yii2

Verwenden Sie Join und Join mit Multi-Table-Assoziationsabfragen in Yii2

高洛峰
高洛峰Original
2017-01-21 11:36:211610Durchsuche

Tabellenstruktur

Jetzt gibt es Kundentabelle, Bestelltabelle, Buchtabelle, Autorentabelle,

Kundentabelle Kunde (ID Kundenname)
Bestelltabelle Bestellung (ID Bestellname Kunden-ID Buch-ID )
Buchtabelle (ID Buchname Autor_ID)
Autorentabelle (ID Autorname)

Modelldefinition

Im Folgenden sind die Definitionen dieser vier Modelle aufgeführt. Schreiben Sie nur die Beziehungen auf

Kunde

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

Bestellung

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']);
}
}

Buch

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

Autor

class Autor extends \yii\db\ActiveRecord
{
}

hasMany und hasOne use

Es gibt zwei Arten von Zuordnungen zwischen Tabellen in Yii2, die zur Angabe der Beziehung zwischen zwei Modellen verwendet werden Verein.

Eins-zu-viele: hasMany

Eins-zu-eins: hasOne

Rückgabeergebnisse: Die Rückgabeergebnisse dieser beiden Methoden sind yiidbActiveQuery Objekte

Der erste Parameter: der Klassenname des zugehörigen Modells.

Der zweite Parameter: ist ein Array, wobei die Schlüssel die Attribute im zugehörigen Modell und die Werte die Attribute im aktuellen Modell sind.

Verwendung von Assoziationen

Jetzt erhalten wir alle Bestellinformationen eines Kunden

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

Die beiden obigen Codezeilen generieren Folgendes SQL-Anweisung

SELECT * FROM customer WHERE id=1;
SELECT * FROM order WHERE customer_id=1;

Assoziationsergebnis-Cache

Wenn sich die Bestellung des Kunden ändert, rufen wir sie erneut auf

$orders = $customer->orders;

Wenn Sie die Bestellung erneut erhalten, werden Sie feststellen, dass es keine Änderung gibt. Der Grund dafür ist, dass die Datenbank nur abgefragt wird, wenn $customer->orders zum ersten Mal ausgeführt wird, die Ergebnisse zwischengespeichert werden und SQL bei nachfolgenden Abfragen nicht ausgeführt wird.

Was ist, wenn ich SQL erneut ausführen möchte? Sie können

unset($customer->orders);
$customer->orders;

ausführen und dann Daten aus der Datenbank abrufen.

Mehrere Assoziationen definieren

Ähnlich können wir auch mehrere Assoziationen in „Kunde“ definieren.
Wenn die Gesamtzahl der zurückgegebenen Bestellungen mehr als 100 beträgt.

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');
}
}

Die beiden zugehörigen Zugriffsmethoden

sind wie oben, wenn Sie

$customer->bigOrders

Wird alle Bestellungen über 100 erhalten. Wenn Sie Bestellungen mit mehr als 200 zurückgeben möchten, können Sie so schreiben:

$orders = $customer->getBigOrders(200)->all();

Wie Sie oben sehen können, gibt es zwei Möglichkeiten, auf eine Zuordnung zuzugreifen


Wenn es als Funktion aufgerufen wird, wird ein ActiveQuery-Objekt ($customer->getOrders()->all()) zurückgegeben.


Wenn es als Attribut aufgerufen wird, Das Ergebnis des Modells wird direkt zurückgegeben ($ Kunde->Bestellungen)

mit Blick auf den folgenden Code, der die Bestellung eines Kunden entgegennehmen soll

// 执行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;

Wenn wir jetzt 100 Benutzer herausnehmen möchten, können wir, um auf die Bestellung jedes Benutzers zuzugreifen, aus dem obigen Verständnis den folgenden Code schreiben

// 执行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;
// 处理订单。。。
}

Allerdings, wenn wir es wirklich wollen Um es so zu schreiben, wird es in jeder Schleife von foreach ausgeführt. Führen Sie SQL einmal aus, um Daten in der Datenbank abzufragen. Weil jedes $customer-Objekt anders ist.

Um das oben genannte Problem zu lösen, können Sie yiidbActiveQuery::with() verwenden.

Der Breitenparameter ist der Name der Beziehung, d. h. im Modell definierte getOrders, Bestellungen und Kunden in 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...
}

Wenn select verwendet wird, geben Sie an Stellen Sie sicher, dass die zurückgegebenen Spalten die zugehörigen Felder des zugehörigen Modells enthalten. Andernfalls wird das Modell

$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();

nicht zum Filtern zurückgegeben. Bedingungen

Bestellungen mit mehr als 100 Kunden abfragen

//首先执行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();

Bestellungen mit 100 Kunden abfragen, die Summe jedes Kunden beträgt mehr als 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();

Hier ist der Breitenparameter ein Array, der Schlüssel ist der zugehörige Name und der Wert ist die Rückruffunktion.

Das heißt, für die ActiveQuery, die von der Auftragszuordnung zurückgegeben wird, führen Sie $query->andWhere('subtotal>100') aus;

Verwenden Sie „joinWith“ für die Tabellenzuordnung

Wir alle wissen, dass wir Join-On verwenden können, um Assoziationen zwischen mehreren Tabellen zu schreiben. Schauen Sie sich zunächst die Deklaration von joinWit in yii2 an

joinWith( $with, $eagerLoading = true, $joinType = 'LEFT JOIN' )

$with Der Datentyp ist eine Zeichenfolge oder ein Array. Wenn es sich um eine Zeichenfolge handelt, ist es der Name der in definierten Zuordnung das Modell (kann eine Unterassoziation sein).

Wenn es sich um ein Array handelt, ist der Schlüssel die im getXXX-Format im Modell definierte Assoziation und der Wert die weitere Rückrufoperation für diese Assoziation.


$eagerLoading Ob die Daten des in $with verknüpften Modells geladen werden sollen.

$joinType-Verbindungstyp, verfügbare Werte sind: LEFT JOIN, INNER JOIN, der Standardwert ist 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();

In der Implementierung wird Yii zuerst ausgeführt JOIN, das die SQL-Anweisung der Abfragebedingung erfüllt, füllt die Ergebnisse in das Hauptmodell, führt dann eine Abfrageanweisung für jede Assoziation aus und füllt das entsprechende Assoziationsmodell.

// Order和books关联 inner join ,但不获取books关联对应的数据
$orders = Order::find()->innerJoinWith('books', false)->all();

Einschaltbedingung

Beim Definieren der Zuordnung können Sie auch die Einschaltbedingung angeben

class User extends ActiveRecord
{
public function getBooks()
{
return $this->hasMany(Item::className(), ['owner_id' => 'id'])->onCondition(['category_id' => 1]);
}
}

in joinWith Verwenden Sie

//先查询主模型(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();

, wenn die Join-Operation nicht verwendet wird, auch wenn Sie with verwenden oder direkt auf die Assoziation mit Attributen zugreifen. Zu diesem Zeitpunkt wird die Ein-Bedingung als Wo-Bedingung verwendet.

// SELECT * FROM user WHERE id=10
$user = User::findOne(10);

Zusammenfassung

Zuerst müssen Sie die Zuordnung im Modell definieren (z. B. „Orders“ in getOrders ist eine Zuordnung)

Dann with oder joinWith verwendet die im Modell definierte Assoziation.

Sie können bei Verwendung der Assoziation auch eine Rückrufmethode angeben.

Außerdem können Sie angeben, wo oder unter welchen Bedingungen die Assoziation, mit und beitretenMit

Dieser Teil ist tatsächlich sehr umfangreich und etwas verwirrend, wie zum Beispiel die Drei-Tabellen-Assoziation , Inverse Korrelation usw.


Die grundlegendsten Vorgänge sind ungefähr die folgenden. Wenn es noch etwas gibt, worüber Sie mehr wissen möchten, antworten Sie bitte auf den Beitrag.

Das Obige ist das relevante Wissen über Multi-Table-Abfragen (Join, Joinwith), das vom Herausgeber eingeführt wurde. Ich hoffe, es wird Ihnen hilfreich sein. Wenn Sie Fragen haben, hinterlassen Sie mir bitte eine Nachricht Ich werde rechtzeitig antworten. Ich möchte mich auch bei Ihnen allen für Ihre Unterstützung der chinesischen PHP-Website bedanken!

Weitere Artikel zur Verwendung von Join und Join mit Multi-Table-Assoziationsabfragen in Yii2 finden Sie auf der chinesischen PHP-Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn