Laravel oneToMany访问器在eloquent和datatables中的使用

时间:2018-01-29 18:32:56

标签: laravel datatables eloquent laravel-datatables

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

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

会计表有活动记录,我希望在使用时返回用户ID的字段'rtype'的最新值。

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

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

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

但是我没有为表中的用户获取'rtype'的值,也没有错误。

2 个答案:

答案 0 :(得分:1)

看起来你没有正确定义你的关系。您的isOnline方法会创建HasMany关系,但会运行select方法,然后运行latest方法,最终会返回Builder个对象。< / p>

正确的方法是只返回方法中的HasMany对象,它将被视为关系。

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

然后,如果您想在isOnline课程中使用App\User辅助方法,可以添加以下内容:

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\User对象执行任何操作,例如调用isOnline方法。

修改

经过一些进一步的挖掘,你的关系似乎是导致问题的select。我在自己的一个项目中做了类似的事情,发现我的关系没有返回任何结果。虽然添加latest似乎没有问题。

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

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

至少Laravel 5.5是这种情况,我不确定以前的版本。有关详情,请参阅标有预先加载特定列

的标题下的here

答案 1 :(得分:0)

感谢Jonathon

用户模型

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

CONTROLLER

$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();