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

Searching an accessor of eager-loaded relation from datatables

提问人:miken32 提问时间:11/21/2018 最后编辑:Communitymiken32 更新时间:10/2/2021 访问量:1382

问:

我有以下型号:

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

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

{data: "department.email"}

这将毫无问题地显示访问器属性。当我尝试搜索或根据此列进行排序时,问题就来了:email

DataTables 警告:table id=DataTables_Table_0 - 异常消息:

SQLSTATE[42S22]: 找不到列: 1054 “where 子句”中的未知列“departments.email”

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

我能找到的唯一解决方法是使用 filterColumn 方法,它允许您为特定列定义自定义子句。但据我所知,a) 需要您使用查询构建器手动定义列,并且 b) 仅直接对模型起作用,而不是对其关系之一起作用。WHERE

有没有办法可以像使用关系的“真实”属性一样搜索和排序此访问器属性?

php laravel yajra-datatable laravel-datatables

评论

0赞 waterloomatt 2/5/2020
你有没有找到解决这个问题的方法?遇到同样的问题。我没有使用关系,但仍然无法在访问器字段上搜索。
1赞 miken32 2/6/2020
@waterloomatt 是的,我确实让它工作了,就在我问这个问题大约一年后。请参阅下面的回答。

答:

0赞 Kenny Horna 11/21/2018 #1

尝试将附件追加到模型。

class Department extends Model {

    protected $appends = ['email'];

    // the rest of your code
}

注意:阵列中的属性也将遵循在模型上配置的和设置。appendsvisiblehidden

来源: 将值追加到 JSON

评论

0赞 miken32 11/21/2018
它已经被追加了;正如我所说,电子邮件显示得很好——只是由于 Laravel Datatables 的处理方式,它无法搜索。
1赞 miken32 2/6/2020 #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",
                fn ($q, $k) => $q->whereRaw("$concat LIKE ?", ["%$k%"]);
            )
            ->make();
    }
}

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