doubi7496 2019-04-24 10:02 采纳率: 0%
浏览 161
已采纳

Laravel中三个表的复杂查询

I have a problem what I can’t solve with Laravel. I have three table:

Users, Properties, Offers

Users haveMany Properties and Offers Properties and Offers belongsTo a User

  1. Properties table:
  2. id
  3. user_id
  4. contract_start_date
  5. other_date
  6. created_at
  7. updated_at
  8. Offers table:
  9. id
  10. user_id
  11. created_at
  12. updated_at

I would like give a table that is like this (I use two date filter: startDate and endDate):

  1. Users name || Properties count (They are filtered by contract_start_date) || Properties count (They are filtered by other_date) || Offers count
  2. ———
  3. user1 || 5 || 2 || 12
  4. user2 || 0 || 1 || 0
  5. user3 || 0 || 0 || 0

I try with union, leftJoin, etc but I can’t solve this… Thanks, if you can help

  • 写回答

1条回答 默认 最新

  • dongshi1102 2019-04-24 11:37
    关注

    Quick and Dirty

    First, get your users eager loading their properties' dates and all the offers.

    1. $users = Users::with([
    2. 'property'=>function($query){
    3. $query->select('contract_startdate','otherdate');
    4. },
    5. 'offer'=>function($query){
    6. $query->select('id');
    7. },
    8. );

    Assuming you've properly set the $dates array in your model to include your contract_startdate and other_date. We can use carbon to filter the collection to get the properties we're interested in counting. In your view, you can:

    1. <table>
    2. <thead>
    3. <tr>
    4. <th>User</th>
    5. <th>Property (start date)</th>
    6. <th>Property (other date)</th>
    7. <th>Offers</th>
    8. </tr>
    9. </thead>
    10. <tbody>
    11. @foreach($users as $user)
    12. <tr>
    13. <td>{{$user->name}}</td>
    14. <td>{{$user->properties
    15. ->filter(function($item) use ($filter_start,$filter_end){
    16. return $item->contract_startdate->between($filter_start,$filter_end);
    17. })->count() }}</td>
    18. <td>{{$user->properties
    19. ->filter(function($item) use ($filter_start,$filter_end){
    20. return return $item->other_date->between($filter_start,$filter_end);
    21. })->count() }}</td>
    22. <td>{{$user->offers->count()}}</td>
    23. </tr>
    24. @endforeach
    25. </tbody>
    26. </table>

    Cleaning that up

    You should likely refactor the filter out of the view for cleanness, but doing so will add another loop over collection. But you might be able to remove a loop by doing something like this in your controller.

    1. $users = Users::with([
    2. 'property'=>function($query){
    3. $query->select('contract_startdate','otherdate');
    4. },
    5. 'offer'=>function($query){
    6. $query->select('id');
    7. },
    8. );
    9. $byContractDate = collect();
    10. $byOtherDate = collect();
    11. foreach($users as $user){
    12. foreach($properties as $property){
    13. $contractCounter = 0;
    14. $otherCounter = 0;
    15. if($propery->contract_startdate->between($filter_start,$filter_end){
    16. $contractCounter++;
    17. }
    18. if($propery->contract_startdate->between($filter_start,$filter_end){
    19. $otherCounter++;
    20. }
    21. }
    22. $byContractDate->put($user->id,$contractCounter);
    23. $byOther->put($user->id,$otherCounter);
    24. }

    And in your view:

    1. <table>
    2. <thead>
    3. <tr>
    4. <th>User</th>
    5. <th>Property (start date)</th>
    6. <th>Property (other date)</th>
    7. <th>Offers</th>
    8. </tr>
    9. </thead>
    10. <tbody>
    11. @foreach($users as $user)
    12. <tr>
    13. <td>{{$user->name}}</td>
    14. <td>{{$byContract->get($user->id)}}</td>
    15. <td>{{$byOther->get($user->id)}}</td>
    16. <td>{{$user->offers->count()}}</td>
    17. </tr>
    18. @endforeach
    19. </tbody>
    20. </table>

    展开全部

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
编辑
预览

报告相同问题?

手机看
程序员都在用的中文IT技术交流社区

程序员都在用的中文IT技术交流社区

专业的中文 IT 技术社区,与千万技术人共成长

专业的中文 IT 技术社区,与千万技术人共成长

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

客服 返回
顶部