#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()
делает, так это в основном выдает три запроса (в зависимости от ваших настроек отношения и областей, это могут быть разные запросы):
SELECT * FROM properties ...
SELECT * FROM companies WHERE properties.id in (...)
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. Трудно добиться полной работоспособности, не имея под рукой вашего приложения. Но я попробую…