Laravel - Yajra Datatable сортировка и поиск столбца отношений

Я изо всех сил пытаюсь выполнить сортировку и поиск для работы в столбцах отношений в Laravel / Yajra Datatables < / а>.

У меня есть Metro модель, которая связана с Station. Вот мой код.

столбцы таблицы метро

id, name, number, origin_id, destination_id, created_at, updated_at

столбцы таблицы станций

id, name, code, info, photo, created_at, updated_at

Модель Метро

/**
 * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
 */
public function origin()
{
    return $this->belongsTo(Station::class, 'origin_id');
}

/**
 * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
 */
public function destination()
{
    return $this->belongsTo(Station::class, 'destination_id');
}

Метроконтроллер JSON

/**
 * DataTable json data request
 *
 * @param \App\Metro $metro
 *
 * @return mixed
 * @throws \Exception
 */
public function jsonData(Metro $metro)
{
    return DataTables::of($metro::select('id', 'name', 'number', 'origin_id', 'destination_id', 'created_at', 'updated_at'))
                     ->addColumn('action', function ($metro) {

                         $show    = route('admin.metros.show', $metro);
                         $edit    = route('admin.metros.edit', $metro);
                         $destroy = route('admin.metros.destroy', $metro);
                         $attr    = 'onclick=metroDelete(' . $metro->id . ')';

                         return view('admin.components.action', compact([
                             'show',
                             'edit',
                             'destroy',
                             'attr',
                         ]));

                     })
                     ->editColumn('origin_id', function ($metro) {
                         return '<a href="'.route('admin.stations.show', $metro->origin->id).'">' . $metro->origin->name . '</a>';
                     })
                     ->editColumn('destination_id', function ($metro) {
                         return '<a href="'.route('admin.stations.show', $metro->destination->id).'">' . $metro->destination->name . '</a>';
                     })
                     ->editColumn('created_at', function ($metro) {
                         return $metro->created_at->diffForHumans();
                     })
                     ->escapeColumns([])
                     ->make(TRUE);
}

Просмотр - Javascript

$(document).ready(function () {

    let metroDataTable = $('#metroDataTable');

    metroDataTable.DataTable({
        serverSide  : true,
        processing  : true,
        autoWidth   : false,
        ajax        : '{!! route('admin.metros.json') !!}',
        lengthMenu  : [[25, 50, 75, 100, -1], [25, 50, 75, 100, "All"]],
        columns     : [
            {data: 'id', name: '{{__('admin.metro.id')}}', width: '50px'},
            {data: 'name', name: '{{__('admin.metro.name')}}', width: '100px'},
            {data: 'number', name: '{{__('admin.metro.number')}}', width: '100px'},
            {data: 'origin_id', name: '{{__('admin.metro.origin')}}', width: '200px'},
            {data: 'destination_id', name: '{{__('admin.metro.destination')}}', width: '200px'},
            {data: 'created_at', name: 'created_at'},
            {
                data      : 'action',
                name      : '{{__('admin.action')}}',
                orderable : false,
                searchable: false,
                className : 'text-center'
            },
        ],
        initComplete: function () {
            this.api().columns().every(function () {
                var column = this;
                var input  = document.createElement("input");
                $(input).appendTo($(column.footer()).empty())
                    .on('change', function () {
                        column.search($(this).val(), false, false, true).draw();
                    });
            });
        }

    }); // end of DataTables

}); // end of jQuery Document

Когда я пытаюсь отсортировать столбец Origin или Destination или искать столбец, я получаю следующую ошибку.

введите здесь описание изображения

Вопрос:

Как сделать столбцы originanddestination доступными для сортировки и поиска?


person Code Lover    schedule 17.06.2020    source источник
comment
Почему вы переводите name в опции dataTables columns? Он используется только API-интерфейсом dataTable, поэтому его не нужно переводить. Попробуйте изменить name: '{{__('admin.metro.origin_id')}}' на name: 'origin_id'.   -  person Remul    schedule 17.06.2020
comment
Понятно. Так что я немного неправильно понял. Спасибо, чтобы прояснить это. Ценить :)   -  person Code Lover    schedule 17.06.2020
comment
Хорошо, круто, это решило проблему с ошибкой, но это не сокращение по имени станции, а по идентификатору, который я сохраняю в таблице metros.   -  person Code Lover    schedule 17.06.2020
comment
Подробнее о сортировке / фильтрации отношений можно узнать здесь. Вам нужно будет загрузить отношение $metro::with('origin'), а затем вы можете изменить имя на name: 'origin.name'   -  person Remul    schedule 17.06.2020
comment
@Remul Я еще не эксперт в Laravel, поэтому я следую этому, прежде чем размещать здесь запрос. Проблема, с которой я столкнулся, следуя руководству, - это функция map. return $user->posts->map(function($post) .... Давая мне что-то вроде ошибки, не обнаруженной функцией. Так что мне нужно написать map функцию где-нибудь в моем контроллере? Извините, если это глупый вопрос.   -  person Code Lover    schedule 17.06.2020
comment
Нет, вам это не нужно, это только для отображения всех сообщений, которые есть у пользователя, это не нужно для сортировки / фильтрации. Я добавлю ответ, который должен сработать для вас.   -  person Remul    schedule 17.06.2020


Ответы (1)


Вам не нужно переводить name в опции columns, это значение используется только API dataTables, поэтому вам не следует переводить его:

Изменять

{data: 'origin_id', name: '{{__('admin.metro.origin')}}', width: '200px'},

to

// If data and name are the same you can remove the name altogether
{data: 'origin_id', width: '200px'},

Чтобы разрешить фильтрацию / сортировку по имени источника, вам необходимо сделать следующее.

Нетерпеливо загрузить отношения в ваш контроллер:

// Not sure why are passing a model instance here
return DataTables::of($metro::with('origin', 'destination')

// This should be the same but in my opinion cleaner
return DataTables::of(Metro::with('origin', 'destination')

Измените атрибут имени в опции столбцов:

{data: 'origin_id', name: 'origin.name', width: '200px'},

Подробнее об отношениях для таблиц данных можно узнать здесь.

person Remul    schedule 17.06.2020
comment
Ты гений. Проблема решается всего в нескольких строках. Спасибо большое. Еще одна вещь, чтобы узнать, что, если я хочу получить определенные поля из таблицы? Как теперь я заменил ::of на ::with? - person Code Lover; 17.06.2020
comment
Не следует заменять ::of на ::with. Я не понимаю, почему вы вообще передаете экземпляр модели. Должно получиться что-то вроде DataTables::of(Metro::with('origin', 'destination')->select('your columns')); - person Remul; 17.06.2020
comment
Круто ... понял. Спасибо за разъяснение. - person Code Lover; 17.06.2020