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\User
object做任何你想做的事情,比如调用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();
在我的用户模型上,我有以下内容:
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\User
object做任何你想做的事情,比如调用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();