Closed herzmut closed 8 years ago
@dguhl You can use
$query->leftJoin('Grocery', 'Fruits.grocery_id = Grocery.id')
instead. It will provide something you expect.
Or use $query->leftJoin('Grocery', ['Fruits.grocery_id' => new \yii\db\Expression('Grocery.id')])
it will do the same expected result.
@cebe I think that this issue is main about a documentation. Because to find a solution I had to browse a lot of the source code.
@TriAnMan the second one is not correct. it will try to bind the expression as a parameter. only first is correct. and yes, this is more about documentation. thanks for checking.
@cebe sorry, but I've just double checked and an expression
$query->leftJoin('Grocery', ['Fruits.grocery_id' => new \yii\db\Expression('Grocery.id')])
does the join. At least on Yii 2.0.2
that's interesting, did not know that this works and I am not sure if the code was created to work this way :)
There are situations with multiple column-column and/or column-value where the string-based approach is not recommended. I want to share thoughts to enable using the array format in such cases:
join()
functions that tells it if the values in the arrays are column names or values. Or add new functions (e..g leftJoinColumns()
) that takes only columns while keeping the old functions dealing with values. This is not convenient when dealing with both types together as they will need to be batched by type.$query->leftJoin('Grocery', [
'Fruits.store_id' => 5, // Treated as in where(), this is the default.
'Fruits.grocery_id' => [ TYPE_COLUMN, 'Grocery.id'] ] // Explicitly set type to column
// or value and quote accordingly.
])
Now when you create a query condition we obtain the following sql query
$query = Order::find();
$query->from(['order' => Order::tableName()]);
$query->leftJoin([
'user' => User::tableName(),
], ['order.UserId' => 'user.Id']);
SELECT "order".* FROM "tbl_order" "order" LEFT JOIN "tbl_user" "user" ON "order"."UserId" = 'user.Id'
I think it is a good idea to add a condition to the 4th parameter
$query = Order::find();
$query->from(['order' => Order::tableName()]);
$query->leftJoin([
'user' => User::tableName(),
], ['=', 'order.UserId', 'user.Id', true]);
SELECT "order".* FROM "tbl_order" "order" LEFT JOIN "tbl_user" "user" ON "order"."UserId" = "user"."Id"
It will not break backward compatibility for existing code
For *join methods, there are two ways to use $on parameter: array and string. Using array lets the QueryBuilder parse that one as key value pair, and destroying the resulting SQL statement by tokenizing the second part of the array as string. While this is a wished behavior in (Query)->where(), the exception is in the ON statement where the link is made between two entity fields.
Resulting statement:
Using direct strings would work, although the developer would need to care for backtick enclosure of database entities:
Resulting statement: