From dc720d9bf4fb8a07f2c7d08012952644ad85e794 Mon Sep 17 00:00:00 2001 From: Qiang Xue Date: Tue, 24 Dec 2013 09:29:05 -0500 Subject: [PATCH] more docs about joinwith() --- docs/guide/active-record.md | 45 +++++++++++++++++++++++++++++++++++++--- framework/yii/db/ActiveQuery.php | 10 ++++++--- 2 files changed, 49 insertions(+), 6 deletions(-) diff --git a/docs/guide/active-record.md b/docs/guide/active-record.md index 6498dfc..0996331 100644 --- a/docs/guide/active-record.md +++ b/docs/guide/active-record.md @@ -400,14 +400,53 @@ $orders = Order::find()->joinWith('books')->all(); // find all orders that contain books, and sort the orders by the book names. $orders = Order::find()->joinWith([ 'books' => function ($query) { - $query->orderBy('tbl_item.name'); + $query->orderBy('tbl_item.id'); } ])->all(); ``` Note that [[ActiveQuery::joinWith()]] differs from [[ActiveQuery::with()]] in that the former will build up -and execute a JOIN SQL statement. For example, `Order::find()->joinWith('books')->all()` returns all orders that -contain books, while `Order::find()->with('books')->all()` returns all orders regardless they contain books or not. +and execute a JOIN SQL statement for the primary model class. For example, `Order::find()->joinWith('books')->all()` +returns all orders that contain books, while `Order::find()->with('books')->all()` returns all orders +regardless they contain books or not. + +Because `joinWith()` will cause generating a JOIN SQL statement, you are responsible to disambiguate column +names. For example, we use `tbl_item.id` to disambiguate the `id` column reference because both of the order table +and the item table contain a column named `id`. + +You may join with one or multiple relations. You may also join with sub-relations. For example, + +```php +// join with multiple relations +// find out the orders that contain books and are placed by customers who registered within the past 24 hours +$orders = Order::find()->joinWith([ + 'books', + 'customer' => function ($query) { + $query->where('tbl_customer.create_time > ' . (time() - 24 * 3600)); + } +])->all(); +// join with sub-relations: join with books and books' authors +$orders = Order::find()->joinWith('books.author')->all(); +``` + +By default, when you join with a relation, the relation will also be eagerly loaded. You may change this behavior +by passing the `$eagerLoading` parameter which specifies whether to eager load the specified relations. + +Also, when the relations are joined with the primary table, the default join type is `INNER JOIN`. You may change +to use other type of joins, such as `LEFT JOIN`. + +Below are some more examples, + +```php +// find all orders that contain books, but do not eager loading "books". +$orders = Order::find()->joinWith('books', false)->all(); +// find all orders and sort them by the customer IDs. Do not eager loading "customer". +$orders = Order::find()->joinWith([ + 'customer' => function ($query) { + $query->orderBy('tbl_customer.id'); + }, +], false, 'LEFT JOIN')->all(); +``` Working with Relationships diff --git a/framework/yii/db/ActiveQuery.php b/framework/yii/db/ActiveQuery.php index 714ff61..a71b1cf 100644 --- a/framework/yii/db/ActiveQuery.php +++ b/framework/yii/db/ActiveQuery.php @@ -220,9 +220,13 @@ class ActiveQuery extends Query implements ActiveQueryInterface * ])->all(); * ``` * - * @param bool $eagerLoading - * @param string $joinType - * @return $this + * @param boolean|array $eagerLoading whether to eager load the relations specified in `$with`. + * When this is a boolean, it applies to all relations specified in `$with`. Use an array + * to explicitly list which relations in `$with` need to be eagerly loaded. + * @param string|array $joinType the join type of the relations specified in `$with`. + * When this is a string, it applies to all relations specified in `$with`. Use an array + * in the format of `relationName => joinType` to specify different join types for different relations. + * @return static the query object itself */ public function joinWith($with, $eagerLoading = true, $joinType = 'INNER JOIN') {