Reputation: 214
I've got 3 models: Client
, Organization
nad Industry
. I want to filter and display clients, that are assigned to any organization in choosen Industry.
Relations:
Client N-N Organization N-N Industry
One client can have multiple organizations and one organization can have multiple industries. I use form with GET
method.
My controller:
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]);
}
}
I've tried multiple things, such as looping through current result with organizations, but that returned true or false whe using has().
I've also tried using $clients = Client::all()
but my point is to paginate it further so I've worked with Client::where('id', '*')
so I didn't get collection, but that caused, that statuses
filter does not work.
I'm working with Laravel 6. Do you have any idea how to make universal filtering with pagination? Thanks a lot!
EDIT
relevant relationship in details (f.e. pivot table for Client - Organization is client_organization
) with foreign keys defined.
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();
}
EDIT 2:
I'm trying to achieve my goal through SQL query, but I'm stuck with JOINS
with many-to-many relationships.
$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)`
This query returns Column not found: 1054 Unknown column 'organizations.id' in 'on clause'
Upvotes: 1
Views: 1704
Reputation: 214
I managed to do it this way:
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);
});
});
}
Thanks for your help boys :)
Upvotes: 1
Reputation: 1871
So, if you have the $industry
you can find all of the Organisations within it using your relationships:
$organisations = $industry->organisations();
Then, you want to get all clients for each organisation:
$clients = [];
foreach ($organisations as $organisation) {
$clients[$organisation] = $orgination->clients()->toArray();
}
Or, alternatively, to give it a go all in one query:
$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);
Try this line by line to check it out and debug it easily (try ->get()
after the first leftJoin
and check that it works; if that's okay, try it after the second.
Upvotes: 1