如何按父对象的关系过滤 laravel 中的数据

How to filter data in laravel by relationship of parent object

我有 3 个模型:ClientOrganizationIndustry。我想过滤和显示分配给所选行业中任何组织的客户。 关系:

Client N-N Organization N-N Industry

一个客户可以有多个组织,一个组织可以有多个行业。我使用带有 GET 方法的表单。

我的控制器:

class ClientListsController extends Controller
{
  public function index()
  {
      $clients = new Client;
      $queries = array();
      $columns = ['statuses'];

      foreach ($columns as $column) {
        if (request()->has($column)) {

          if ($column == 'industries') {
            // filter by industries
          }

          if ($column == 'statuses' && request($column) == 1 ) {
            $clients = optional($clients->has('organizations'))->paginate(100, ['*'], 'client_page');
          }else if($column == 'statuses' && request($column) == null ){
            $clients = Client::paginate(100, ['*'], 'client_page');
          }
          else{
            $clients = $clients->whereDoesntHave('organizations')->paginate(100, ['*'], 'client_page');
          }

          $queries[$column] = request($column);

        }else{
          $clients = Client::paginate(100, ['*'], 'client_page');
        }
      }

      $organizations = Organization::paginate(100, ['*'], 'org_page');
      return view('clientLists.index')->with(['clients' => $clients, 'organizations' => $organizations]);
  }
}

我已经尝试了多种方法,例如循环遍历组织的当前结果,但在使用 has() 时返回 true 或 false。 我也尝试过使用 $clients = Client::all() 但我的意思是进一步分页所以我使用 Client::where('id', '*') 所以我没有得到集合,但那导致 statuses 过滤器确实不行。

我正在与 Laravel 6 合作。你知道如何使用分页进行通用过滤吗?非常感谢!

编辑 详细相关关系(f.e。客户的枢轴 table - 组织是 client_organization),并定义了外键。

App\Client
    public function Organizations()
    {
      return $this->belongsToMany('App\Organization')->withTimestamps();
    }
App\Organization
  public function Clients()
  {
    return $this->belongsToMany('App\Client')->withTimestamps();
  }
  public function Industries()
  {
    return $this->belongsToMany('App\Industry')->withTimestamps();
  }
App\Industry
  public function Organizations()
  {
    return $this->belongsToMany('App\Organization')->withTimestamps();
  }

编辑 2: 我试图通过 SQL 查询来实现我的目标,但我被 JOINS 与多对多关系所困。

$clients = DB::table('clients')
->leftJoin('client_organization', 'client_organization.client_id', '=', 'clients.id')->leftJoin('industry_organization', 'industry_organization.organization_id', '=', 'organizations.id')
->whereIn('industry_organization.industry_id', request($column))
->paginate(100, ['*'], 'client_page');
}
select
  count(*) as aggregate
from
  `clients`
  left join `client_organization` on `client_organization`.`client_id` = `clients`.`id`
  left join `industry_organization` on `industry_organization`.`organization_id` = `organizations`.`id`
where
  `industry_organization`.`industry_id` in (2)` 

本次查询returnsColumn not found: 1054 Unknown column 'organizations.id' in 'on clause'

因此,如果您有 $industry,您可以使用您的关系找到其中的所有组织:

$organisations = $industry->organisations();

然后,您想要获取每个组织的所有客户:

$clients = [];

foreach ($organisations as $organisation) {
    $clients[$organisation] = $orgination->clients()->toArray();
}

或者,也可以在一个查询中试一试:

$industries = request($column);

$clients = DB::table('clients')
    ->leftJoin('client_organization', 'client_organization.client_id', '=', 'clients.id')
    ->leftJoin('organizations', 'organizations.id', '=', 'client_organization.id')
    ->leftJoin('industry_organization', 'industry_organization.organization_id', '=', 'organizations.id')
    ->whereIn('organisations.industry_id', $industries)
    ->paginate(10);

逐行尝试检查并轻松调试(在第一个 leftJoin 之后尝试 ->get() 并检查它是否有效;如果可以,在第二个之后尝试。

我是这样做的:

      if (request()->industries[0] != "") {
        $clients = $clients->with('organizations')->whereHas('organizations', function($query){
          $query->with('industries')->whereHas('industries', function($query2){
            $query2->whereIn('industry_id', request()->industries);
          });
        });
      }

感谢小伙伴们的帮助:)