从数据表中搜索预加载关系的访问器

Searching an accessor of eager-loaded relation from datatables

我有以下型号:

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

我正在提取用户列表,包括他们的部门,并在服务器端 pagination/sorting/searching:

的数据表中显示(使用 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();
    }
}

在数据表设置中,我的其中一列定义如下:

{data: "department.email"}

这会毫无问题地显示 email 访问器 属性。当我尝试搜索或基于此列排序时出现问题:

DataTables warning: table id=DataTables_Table_0 - Exception Message:

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'departments.email' in 'where clause'

显然,datatables 并不知道这是一个访问器,并试图将其包含在查询中——结果可预测。

我能找到的唯一解决方法是使用 the filterColumn method,它允许您为特定列定义自定义 WHERE 子句。但据我所知,a) 要求您使用查询生成器手动定义列,而 b) 仅适用于模型直接,不是它的关系之一。

有什么方法可以搜索和排序此访问器 属性,就像我可以使用关系的“真实”属性一样?

尝试将访问器附加到模型。

class Department extends Model {

    protected $appends = ['email'];

    // the rest of your code
}

注意:appends 数组中的属性也将遵循模型上配置的 visiblehidden 设置。

来源:Appending Values To JSON

这就是我最终解决这个问题的方法。这不是一个理想的解决方案,但基本上我在 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",
                fn ($q, $k) => $q->whereRaw("$concat LIKE ?", ["%$k%"]);
            )
            ->make();
    }
}

然后我将生成的列包含在我的 table 定义中,搜索按预期工作。