Laravel eloquent 和数据表中的 oneToMany 访问器用法

Laravel oneToMany accessor usage in eloquent and datatables

在我的用户模型上,我有以下内容:

public function isOnline()
{
    return $this->hasMany('App\Accounting', 'userid')->select('rtype')->latest('ts');
}

会计 table 有 activity 条记录,我希望在使用时 return 字段 'rtype' 的最新值用于用户 ID。

在我的控制器中,我正在执行以下操作:

    $builder = App\User::query()
        ->select(...fields I want...)
        ->with('isOnline')
        ->ofType($realm); 

    return $datatables->eloquent($builder)
        ->addColumn('info', function ($user) {
            return $user->isOnline;
        }
    })

但是我没有为 table 中的用户获取 'rtype' 的值并且没有错误。

看来你没有正确定义你们的关系。您的 isOnline 方法创建一个 HasMany 关系,但运行 select 方法,然后在其上运行 latest 方法,最终将 returning 一个 Builder object.

正确的方法是仅 return 来自您的方法的 HasMany object,它将被视为关系。

public function accounts()
{
    return $this->hasMany('App\Accounting', 'userid');
}

然后如果你想在你的 App\User class 中使用 isOnline 辅助方法,你可以像这样添加一个:

public function isOnline()
{
    // This gives you a collection of \App\Accounting objects
    $usersAccounts = $this->accounts;

    // Do something with the user's accounts, e.g. grab the last "account"
    $lastAccount = $usersAccounts->last();
    if ($lastAccount) {
        // If we found an account, return the rtype column
        return $lastAccount->rtype;
    }

    // Return something else
    return false;
}

然后在你的控制器中你可以预先加载关系:

$users = User::with('accounts')->get(['field_one', 'field_two]);

然后你可以对每个App\Userobject做任何你想做的事情,比如调用isOnline方法。


编辑

经过进一步挖掘,问题似乎是你们关系中的 select。我在我自己的一个项目中做了类似的事情,发现我的关系没有结果 returned。不过添加 latest 似乎没问题。

所以你应该至少在你的关系定义中删除 select 部分。当你只想在急切加载你的关系时检索某些字段时,你应该能够在使用 with 时指定它们,如下所示:

// Should bring back Accounting instances ONLY with rtype field present
User::with('accounts:rtype');

至少Laravel 5.5是这样的,我不确定以前的版本。有关详细信息,请参阅 here,在标有 预先加载特定列

的标题下

谢谢乔纳森

用户模型

public function accounting()
{
    return $this->hasMany('App\Accounting', 'userid', 'userid');
}

public function isOnline()
{
    $rtype = $this->accounting()
        ->latest('ts')
        ->limit(1)
        ->pluck('rtype')
        ->first();

    if ($rtype == 'Alive') {
        return true;
    }
    return false;
}

控制器

$builder = App\User::with('accounting:rtype')->ofType($filterRealm);

return $datatables->eloquent($builder)
    ->addColumn('info', function (App\User $user) {

    /*
    THIS HAS BEEN SUCCINCTLY TRIMMED TO BE AS RELEVANT AS POSSIBLE.
    ARRAY IS USED AS OTHER VALUES ARE ADDED, JUST NOT SHOWN HERE
    */

    $info[];

    if ($user->isOnline()) {
        $info[] = 'Online';
    } else {
        $info[] = 'Offline';
    }

    return implode(' ', $info);
})->make();