英文:
Laravel select column and join table based on input
问题
以下是您的翻译:
我有一个类似这样的查询:
```php
$query = Merchant::select(
'merchants.*',
'users.name as rm_name',
'users.employee_id as rm_emp_id',
'stU.name as status_updated_by_name',
'rUsers.name as team_lead',
'tmU.name as territory_manager',
'amU.name as area_manager',
'rmU.name as regional_manager',
'districts.name as district_name',
'areas.name as area_name',
'producers.name as producer_name',
'markets.market_name',
'markets.code as market_code',
'categories.name as category_name',
'divisions.name as division_name',
'thanas.name as thana_name',
'merchants.merchant_uid as merchant_uid'
)
->join('users', 'users.id', '=', 'merchants.rm_id')
->join('users as rUsers', 'rUsers.id', '=', 'users.reporting_to')
->leftJoin('users as tmU', 'tmU.id', '=', 'rUsers.reporting_to')
->leftJoin('users as amU', 'amU.id', '=', 'tmU.reporting_to')
->leftJoin('users as rmU', 'rmU.id', '=', 'amU.reporting_to')
->leftJoin('users as stU', 'stU.id', '=', 'merchants.status_updated_by')
->leftJoin('markets', 'markets.id', '=', 'merchants.market_id')
->leftJoin('categories', 'categories.id', '=', 'merchants.category_id')
->leftJoin('producers', 'producers.id', '=', 'merchants.producer_id')
->leftjoin('divisions', 'divisions.id', '=', 'merchants.division_id')
->leftjoin('districts', 'districts.id', '=', 'merchants.district_id')
->leftjoin('thanas', 'thanas.id', '=', 'merchants.thana_id')
->leftjoin('new_areas as areas', 'areas.id', '=', 'merchants.area_id')
->get();
在这里,用户可以通过 UI 选择一个 district
,也可以将其保留为未选择状态。
我通过 $request
获取用户输入(尚未使用)。我可以通过 $request->district_id
获取一个地区(district)。
如果选择了 district
,我想选择 districts.name as district_name
并与 districts
表进行连接。
否则,每次连接到地区都是不必要的。实际上,对于其他列也是如此。
我应该如何实现这一点?
英文:
I have a query like this:
$query = Merchant::select(
'merchants.*',
'users.name as rm_name',
'users.employee_id as rm_emp_id',
'stU.name as status_updated_by_name',
'rUsers.name as team_lead',
'tmU.name as territory_manager',
'amU.name as area_manager',
'rmU.name as regional_manager',
'districts.name as district_name',
'areas.name as area_name',
'producers.name as producer_name',
'markets.market_name',
'markets.code as market_code',
'categories.name as category_name',
'divisions.name as division_name',
'thanas.name as thana_name',
'merchants.merchant_uid as merchant_uid'
)
->join('users', 'users.id', '=', 'merchants.rm_id')
->join('users as rUsers', 'rUsers.id', '=', 'users.reporting_to')
->leftJoin('users as tmU', 'tmU.id', '=', 'rUsers.reporting_to')
->leftJoin('users as amU', 'amU.id', '=', 'tmU.reporting_to')
->leftJoin('users as rmU', 'rmU.id', '=', 'amU.reporting_to')
->leftJoin('users as stU', 'stU.id', '=', 'merchants.status_updated_by')
->leftJoin('markets', 'markets.id', '=', 'merchants.market_id')
->leftJoin('categories', 'categories.id', '=', 'merchants.category_id')
->leftJoin('producers', 'producers.id', '=', 'merchants.producer_id')
->leftjoin('divisions', 'divisions.id', '=', 'merchants.division_id')
->leftjoin('districts', 'districts.id', '=', 'merchants.district_id')
->leftjoin('thanas', 'thanas.id', '=', 'merchants.thana_id')
->leftjoin('new_areas as areas', 'areas.id', '=', 'merchants.area_id')
->get();
Here, a user can select a district
or can leave it as unselected from the UI.
I get a user input via $request
(I have not used it yet). I can fetch a district by $request->district_id
.
I want to select districts.name as district_name
and join with districts
table only if district
is selected.
Otherwise, it will be unnecessary to join with district each time. In fact, it is true for other columns also.
How can I achieve this?
答案1
得分: 1
Sure, here is the translated part:
所以,您想要使用的是->when()
,它允许您在表达式为true
时将某些内容添加到查询中。它就像一个if
语句,但不会在代码中“打断”,而是允许您在同一个调用中链接它(非常有用)。
$query = Merchant::select(
'merchants.*',
'users.name as rm_name',
'users.employee_id as rm_emp_id',
'stU.name as status_updated_by_name',
'rUsers.name as team_lead',
'tmU.name as territory_manager',
'amU.name as area_manager',
'rmU.name as regional_manager',
'areas.name as area_name',
'producers.name as producer_name',
'markets.market_name',
'markets.code as market_code',
'categories.name as category_name',
'divisions.name as division_name',
'thanas.name as thana_name',
'merchants.merchant_uid as merchant_uid'
)
->join('users', 'users.id', '=', 'merchants.rm_id')
->join('users as rUsers', 'rUsers.id', '=', 'users.reporting_to')
->leftJoin('users as tmU', 'tmU.id', '=', 'rUsers.reporting_to')
->leftJoin('users as amU', 'amU.id', '=', 'tmU.reporting_to')
->leftJoin('users as rmU', 'rmU.id', '=', 'amU.reporting_to')
->leftJoin('users as stU', 'stU.id', '=', 'merchants.status_updated_by')
->leftJoin('markets', 'markets.id', '=', 'merchants.market_id')
->leftJoin('categories', 'categories.id', '=', 'merchants.category_id')
->leftJoin('producers', 'producers.id', '=', 'merchants.producer_id')
->leftjoin('divisions', 'divisions.id', '=', 'merchants.division_id')
->leftjoin('thanas', 'thanas.id', '=', 'merchants.thana_id')
->leftjoin('new_areas as areas', 'areas.id', '=', 'merchants.area_id')
->when($request->district_id, function (Builder $query, int $id) {
return $query->addSelect('districts.name as district_name')
->leftjoin('districts', 'districts.id', '=', 'merchants.district_id')
->where('districts.id', $id); // I am assuming you want to filter by ID, else remove this where
})
->get();
I hope this helps! If you have any more questions or need further assistance, feel free to ask.
英文:
So, what you want to use is ->when()
, it allows you to add something to the query if an expression is true
. It is exactly an if
, but instead of "breaking" your code in parts, it just allows you to chain it in the same call (very useful).
$query = Merchant::select(
'merchants.*',
'users.name as rm_name',
'users.employee_id as rm_emp_id',
'stU.name as status_updated_by_name',
'rUsers.name as team_lead',
'tmU.name as territory_manager',
'amU.name as area_manager',
'rmU.name as regional_manager',
'areas.name as area_name',
'producers.name as producer_name',
'markets.market_name',
'markets.code as market_code',
'categories.name as category_name',
'divisions.name as division_name',
'thanas.name as thana_name',
'merchants.merchant_uid as merchant_uid'
)
->join('users', 'users.id', '=', 'merchants.rm_id')
->join('users as rUsers', 'rUsers.id', '=', 'users.reporting_to')
->leftJoin('users as tmU', 'tmU.id', '=', 'rUsers.reporting_to')
->leftJoin('users as amU', 'amU.id', '=', 'tmU.reporting_to')
->leftJoin('users as rmU', 'rmU.id', '=', 'amU.reporting_to')
->leftJoin('users as stU', 'stU.id', '=', 'merchants.status_updated_by')
->leftJoin('markets', 'markets.id', '=', 'merchants.market_id')
->leftJoin('categories', 'categories.id', '=', 'merchants.category_id')
->leftJoin('producers', 'producers.id', '=', 'merchants.producer_id')
->leftjoin('divisions', 'divisions.id', '=', 'merchants.division_id')
->leftjoin('thanas', 'thanas.id', '=', 'merchants.thana_id')
->leftjoin('new_areas as areas', 'areas.id', '=', 'merchants.area_id')
->when($request->district_id, function (Builder $query, int $id) {
return $query->addSelect('districts.name as district_name')
->leftjoin('districts', 'districts.id', '=', 'merchants.district_id')
->where('districts.id', $id); // I am assuming you want to filter by ID, else remove this where
})
->get();
See that I have introduced ->when
(the position does not matter, only that it is added before you execute the query). It will require the first parameter to be an expression that can be interpreted as boolean, if district_id
is null
because there is no selection, then it is evaluated as false
so nothing else happens (the function is not executed).
If district_id
has any content that is not falsy (a string or integer that is not 0
or false
) it will be evaluated as true
and the function (second parameter) will be executed, in our case adding an extra select (because I have removed it from the main select as you said, due to not having the join), adding the join, and I also added a filter (where
) so you filter by the $request->district_id = $id
, feel free to remove that one or leave it as it is.
Super personal recommendation: It is not usual to end up with a huge query and custom query like yours. Depending on your case (that you did not mention at all), I do think your query is hyper overengineered. I would recommend to use relationships, else you are literally making the relationships on this part of the code and if any of them changes later, you have to edit this, if it was a literal eager loaded relationship, then nothing should change. So, this is not exactly the larave way, it is not standard, I would try to avoid it unless you have a very good and exceptional case.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论