Как фильтровать данные в laravel по отношениям родительского объекта - PullRequest
0 голосов
/ 27 сентября 2019

У меня есть 3 модели: Client, Organization nad Industry.Я хочу фильтровать и отображать клиентов, которые назначены на любую организацию в выбранной отрасли.Отношения:

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 ().Я также пытался использовать $clients = Client::all(), но моя цель состоит в том, чтобы разбить его на страницы, чтобы я работал с Client::where('id', '*'), поэтому я не получил коллекцию, но это привело к тому, что фильтр statuses не работает.

Я работаю с Laravel 6. У вас есть идеи, как сделать универсальную фильтрацию с нумерацией страниц?Большое спасибо!

РЕДАКТИРОВАТЬ соответствующие отношения в деталях (например, сводная таблица для клиента - организации 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)` 

Этот запрос возвращает Column not found: 1054 Unknown column 'organizations.id' in 'on clause'

Ответы [ 2 ]

1 голос
/ 27 сентября 2019

Итак, если у вас есть $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);

Попробуйте эту строку за строкой, чтобы проверить и легко отладить ее (попробуйте ->get() после первого leftJoin и убедитесь, что он работает, если все в порядке, попробуйте после второго.

0 голосов
/ 30 сентября 2019

Мне удалось сделать это так:

      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);
          });
        });
      }

Спасибо за вашу помощь, мальчики:)

...