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

У меня есть следующие модели:

<?php
class User extends Model {
    public function department() {
        return $this->hasOne(Department::class);
    }
}

class Department extends Model {
    protected $appends = ["email"];
    public function getEmailAttribute() {
        return "$this->name@$this->domain";
    }
    public function user() {
        return $this->belongsTo(User::class);
    }
}

Я собираю список пользователей, включая их отделы, и показываю это (используя пакет Laravel DataTables) в виде данных с разбивкой на страницы на сервере / сортировкой / поиском:

<?php
class UserController extends Controller {
    public function dt() {
        $users = User::with("department")
            ->where("location_id", session("current_location"));
        return DataTables::of($users)->make();
    }
}

В настройке datatables один из моих столбцов определяется следующим образом:

{data: "department.email"}

Это отображает email свойство accessor без проблем. Проблема возникает, когда я пытаюсь выполнить поиск или сортировку по этому столбцу:

Предупреждение DataTables: идентификатор таблицы =DataTables_Table_0 - Сообщение об исключении:

SQLSTATE [42S22]: Столбец не найден: 1054 Неизвестный столбец "partments.email"в" предложении where "

Очевидно, datatables не знает, что это средство доступа, и пытается включить его в запрос - с предсказуемыми результатами.

Единственный обходной путь, на который я мог найти ссылку, - это использование filterColumn метод, который позволяет определить пользовательский WHERE предложение для конкретного столбца. Но, насколько я могу судить, а) требует, чтобы вы определяли столбец вручную с помощью построителя запросов, и б) работает только с моделью напрямую, а не с одним из ее отношений.

Есть ли способ, которым я могу искать и сортировать это свойство аксессора так же, как я могу с "реальными" свойствами отношения?

2 ответа

Итак, вот как я решил это. Это не идеальное решение, но в основном я воссоздал аксессор в SQL, вручную построил запрос, а затем использовал Datatables'filterColumn функциональность.

<?php
class UserController extends Controller {
    public function dt() {
        $concat = "CONCAT(departments.name, '@', departments.domain)";

        $users = User::select(["users.*", DB::raw("$concat AS dept_email")])
            ->leftJoin("departments", "users.department_id", "=", "departments.id")
            ->whereNull("departments.deleted_at")
            ->where("location_id", session("current_location"))
            ->with("departments");

        return DataTables::of($users)
            ->filterColumn(
                "dept_email",
                function($q, $k) use ($concat) {
                    return $q->whereRaw("$concat LIKE ?", ["%$k%"]);
                }
            )
            ->make();
    }
}

Затем я просто включил сгенерированный столбец в определение своей таблицы, и поиск работал должным образом.

Вы можете попробовать установить: https://github.com/babenkoivan/scout-elasticsearch-driver

Этот пакет предлагает возможность определения пользовательских правил для SQL-запросов.

Увидеть:

Попробуйте добавить аксессуар к модели.

class Department extends Model {

    protected $appends = ['email'];

    // the rest of your code
}

Примечание: атрибуты в appends массив также будет уважать visible а также hidden Настройки настроены на модель.

Источник: Добавление значений в JSON

Другие вопросы по тегам