Порядок Laravel по загруженному столбцу

#laravel

#laravel

Вопрос:

Я использую laravel eager loading для загрузки данных в таблицы данных jquery. Мой код выглядит следующим образом:

 $columns = array(
    0 => 'company_name',
    1 => 'property_name',
    2 => 'amenity_review',
    3 => 'pricing_review',
    4 => 'sqft_offset_review',
    5 => 'created_at',
    6 => 'last_uploaded_at'
);

$totalData = Property::count();

$limit = $request->input('length');
$start = $request->input('start');
$order = $columns[$request->input('order.0.column')];
$dir = $request->input('order.0.dir');


$query = Property::with(['company','notices']);
$company_search = $request->columns[0]['search']['value'];
if(!empty($company_search)){
    $query->whereHas('company', function ($query) use($company_search) {
        $query->where('name','like',$company_search.'%');
    });
}

$property_search = $request->columns[1]['search']['value'];
if(!empty($property_search)){
    $query->where('properties.property_name','like',$property_search.'%');
}
if(!Auth::user()->hasRole('superAdmin')) {
    $query->where('company_id',Auth::user()->company_id);
}
$query->orderBy($order,$dir);


if($limit != '-1'){
    $records = $query->offset($start)->limit($limit);
}
$records = $query->get();
  

С помощью этого метода я получил сообщение об ошибке: Column not found: 1054 Unknown column 'company_name' in 'order clause' .

Затем я попробовал выполнить следующее условие заказа:

 if($order == 'company_name'){
    $query->orderBy('company.name',$dir);
}else{
    $query->orderBy($order,$dir);
}
  

Однако он также возвращает аналогичную ошибку: Column not found: 1054 Unknown column 'company.name' in 'order clause'

Затем я попробовал с whereHas условием:

 if($order == 'company_name'){
    $order = 'name';
    $query->whereHas('company', function ($query) use($order,$dir) {
        $query->orderBy($order,$dir);
    });
}else{
    $query->orderBy($order,$dir);
}
  

Но и в этом случае та же проблема.

Для другой таблицы я справлялся с подобными ситуациями с помощью запроса к БД, однако в данном конкретном случае мне нужны уведомления в виде вложенных результатов, потому что я зациклил их на интерфейсе. Итак, мне нужно пройти через eloquent.

Кроме того, я видел другой ответ, в котором люди предлагали заказывать непосредственно в модели, например:

     public function company()
    {
        return $this->belongsTo('AppModelsCompany')->orderBy('name');
    }
  

Но я не хочу заказывать напрямую по модели, потому что я не хочу, чтобы она каждый раз заказывалась по имени. Я хочу оставить его по умолчанию.

Кроме того, в каком-то другом сценарии я видел, как люди использовали join объединение with , но я не очень впечатлен использованием обоих join и with для загрузки одной и той же модели.

Каков наилучший способ решить мою проблему?

У меня есть таблица типа: компании: id, name , свойства: id, property_name, company_id , уведомления: title, slug, body, property_id

Ответ №1:

Проблема здесь в том, что Property::with(['company','notices']); не будет присоединяться к таблицам companies или notices, а только извлекать данные и присоединять их к результирующему Collection . Следовательно, ни одна из таблиц не является частью выданного SQL-запроса, и поэтому вы не можете упорядочить его по какому-либо полю в этих таблицах.

Что Property::with(['company', 'notices'])->get() делает, так это в основном выдает три запроса (в зависимости от ваших настроек отношения и областей, это могут быть разные запросы):

  1. SELECT * FROM properties ...
  2. SELECT * FROM companies WHERE properties.id in (...)
  3. SELECT * FROM notices WHERE properties.id in (...)

В приведенном выше примере кода вы пытались добавить ORDER BY company_name или более позднюю версию ORDER BY companies.name к первому запросу. Область запроса, конечно, не знает ни одного company_name столбца в properties таблице, ни companies таблицы для поиска name столбца. company.name также не будет работать, потому что нет company таблицы, и даже если бы она была, она также не была бы объединена в первом запросе.

С моей точки зрения, лучшим решением для вас было бы отсортировать коллекцию результатов вместо упорядочивания через SQL путем замены $records = $query->get(); на $records = $query->get()->sortBy($order, $dir); , что является наиболее гибким способом для вашей задачи.

Чтобы это сработало, вам пришлось бы заменить 'company_name' на 'company.name' в вашем $columns массиве.

Единственный другой вариант, который я вижу, — это ->join('companies', 'companies.id', 'properties.company_id') , который присоединит таблицу companies к первому запросу.

Собираем все это вместе

Итак, учитывая, что остальная часть вашего кода работает так, как должна, это должно сработать:

 $columns = [
    'company.name',
    'property_name',
    'amenity_review',
    'pricing_review',
    'sqft_offset_review',
    'created_at',
    'last_uploaded_at',
];

$totalData      = Property::count();
$limit          = $request->input('length');
$start          = $request->input('start');
$order          = $columns[$request->input('order.0.column')];
$dir            = $request->input('order.0.dir');
$query          = Property::with(['company', 'notices']);
$company_search = $request->columns[0]['search']['value'];
$property_search = $request->columns[1]['search']['value'];

if (!empty($company_search)) {
    $query->whereHas(
        'company', function ($query) use ($company_search) {
        $query->where('name', 'like', $company_search . '%');
    });
}

if (!empty($property_search)) {
    $query->where('properties.property_name', 'like', $property_search . '%');
}

if (!Auth::user()->hasRole('superAdmin')) {
    $query->where('company_id', Auth::user()->company_id);
}

if ($limit != '-1') {
    $records = $query->offset($start)->limit($limit);
}

$records = $query->get()->sortBy($order, $dir);
  

Комментарии:

1. Это не работает. Та же ошибка: Column not found: 1054 Unknown column 'companies.name' in 'order clause' Я не знаю, как companies это будет работать, потому что результат будет вложен под именем модели company . Не так ли?

2. $query — это экземпляр конструктора запросов. Таким образом, вы пишете запрос к базе данных и должны использовать имя таблицы при полном уточнении столбца. Если построитель запросов не находит companies.name таблица companies не является частью запроса. Что вы можете сделать, так это заменить $records = $query->get(); на $records = $query->get()->sortBy('Company.name') и удалить все orderBy вызовы. Таким образом, вы выполняете сортировку по результирующей коллекции, что менее эффективно, но гораздо более гибко.

3. Я отредактировал ответ, чтобы обобщить его. Дайте мне знать, если это сработает для вас.

4. Я понимаю, что вы пытаетесь сказать. Не могли бы вы, пожалуйста, показать полный рабочий код с этим объединением, а также получить эти уведомления в виде вложенных результатов.

5. Трудно добиться полной работоспособности, не имея под рукой вашего приложения. Но я попробую…