Laravel 保存后关系可用性()
Laravel Relationship availability after save()
我正在使用 Laravel 5 构建一个简单的时间跟踪应用程序,其中我有两个 Laravel 模型,一个称为 "User",一个称为 "Week"
关系很简单:
Week.php:
public function user()
{
return $this->belongsTo('App\User');
}
User.php:
function weeks()
{
return $this->hasMany('App\Week');
}
现在,User.php 文件还有一个名为 "getCurrentWeek()" 的简单辅助/新颖函数,顾名思义,return 是当前周
function getCurrentWeek()
{
$possibleWeek = $this->weeks->sortByDesc('starts')->all();
if(count($possibleWeek) != 0)
{
return $possibleWeek[0];
}
else
{
return null;
}
}
我的问题是:如果我为用户创建第一周并将其附加/关联到用户,如下所示:
$week = new Week;
//Omitted: Setting so attributes here ...
$week->user_id = $user->id;
$weeks->save()
$user->weeks()->save($week);
然后调用$user->getCurrentWeek();
方法,那个方法returns null
,虽然创建了新的周,但是和用户相关,已经保存到数据库.在我看来,预期的行为是 getCurrentWeek()
到 return 新创建的一周。
我对 Eloquent 有什么误解/做错了什么?
$user->weeks()->save($week);
不是必需的,因为您使用 $week->user_id = $user->id;
手动将周附加到用户并保存。
您实际上可以将整个函数重写为:
function getCurrentWeek()
{
return $this->weeks->sortByDesc('starts')->first();
}
或者
function getCurrentWeek()
{
return $this->weeks()->orderBy('starts', 'desc')->first();
}
编辑:
我做了一些概念验证,效果很好:
App\User.php
function weeks()
{
return $this->hasMany('App\Week');
}
function getCurrentWeek()
{
return $this->weeks->sortByDesc('starts')->first();
}
App\Week.php
public function user()
{
return $this->belongsTo('App\User');
}
routes/web.php or App/Http/routes.php
Route::get('poc', function () {
$user = App\User::find(1);
$week = new App\Week;
$week->user_id = $user->id;
$week->starts = Carbon\Carbon::now();
$week->save();
return $user->getCurrentWeek();
});
Result:
{
id: 1,
user_id: "1",
starts: "2016-09-15 21:42:19",
created_at: "2016-09-15 21:42:19",
updated_at: "2016-09-15 21:42:19"
}
关系属性在第一次访问时延迟加载。加载后,它们不会自动刷新关系中添加或删除的记录。
由于您的 getCurrentWeek()
函数使用关系属性,此代码将起作用:
$week = new Week;
// setup week ...
$user->weeks()->save($week);
// $user->weeks attribute has not been accessed yet, so it will be loaded
// by the first access inside the getCurrentWeek method
dd($user->getCurrentWeek());
但是,此代码将不起作用:
// accessing $user->weeks lazy loads the relationship
echo count($user->weeks);
// relate a new record
$week = new Week;
// setup week ...
$user->weeks()->save($week);
// $user->weeks inside the method will not contain the newly related record,
// as it has already been lazy loaded from the access above.
dd($user->getCurrentWeek());
您可以修改 getCurrentWeek()
方法以使用关系方法 ($this->weeks()
) 而不是属性 ($this->weeks
),这将始终访问数据库,或者您可以添加或删除记录后重新加载关系(使用 load()
方法)。
更改 getCurrentWeek()
方法以使用关系方法 weeks()
(@Bjorn 提供的更新方法)
function getCurrentWeek()
{
return $this->weeks()->orderBy('starts', 'desc')->first();
}
或者,使用 load()
方法刷新关系:
// accessing $user->weeks lazy loads the relationship
echo count($user->weeks);
// relate a new record
$week = new Week;
// setup week ...
$user->weeks()->save($week);
// reload the weeks relationship attribute
$user->load('weeks');
// this will now work since $user->weeks was reloaded by the load() method
dd($user->getCurrentWeek());
只是添加到@patricus 的回答中...
在save/create/update之后,您还可以像这样清空所有缓存的关系数据:
$user->setRelations([]);
或有选择地:
$user->setRelation('weeks',[]);
之后,只有在需要时才会再次延迟加载数据:
$user->weeks
这样你就可以继续使用延迟加载了。
我正在使用 Laravel 5 构建一个简单的时间跟踪应用程序,其中我有两个 Laravel 模型,一个称为 "User",一个称为 "Week"
关系很简单:
Week.php:
public function user()
{
return $this->belongsTo('App\User');
}
User.php:
function weeks()
{
return $this->hasMany('App\Week');
}
现在,User.php 文件还有一个名为 "getCurrentWeek()" 的简单辅助/新颖函数,顾名思义,return 是当前周
function getCurrentWeek()
{
$possibleWeek = $this->weeks->sortByDesc('starts')->all();
if(count($possibleWeek) != 0)
{
return $possibleWeek[0];
}
else
{
return null;
}
}
我的问题是:如果我为用户创建第一周并将其附加/关联到用户,如下所示:
$week = new Week;
//Omitted: Setting so attributes here ...
$week->user_id = $user->id;
$weeks->save()
$user->weeks()->save($week);
然后调用$user->getCurrentWeek();
方法,那个方法returns null
,虽然创建了新的周,但是和用户相关,已经保存到数据库.在我看来,预期的行为是 getCurrentWeek()
到 return 新创建的一周。
我对 Eloquent 有什么误解/做错了什么?
$user->weeks()->save($week);
不是必需的,因为您使用 $week->user_id = $user->id;
手动将周附加到用户并保存。
您实际上可以将整个函数重写为:
function getCurrentWeek()
{
return $this->weeks->sortByDesc('starts')->first();
}
或者
function getCurrentWeek()
{
return $this->weeks()->orderBy('starts', 'desc')->first();
}
编辑:
我做了一些概念验证,效果很好:
App\User.php
function weeks()
{
return $this->hasMany('App\Week');
}
function getCurrentWeek()
{
return $this->weeks->sortByDesc('starts')->first();
}
App\Week.php
public function user()
{
return $this->belongsTo('App\User');
}
routes/web.php or App/Http/routes.php
Route::get('poc', function () {
$user = App\User::find(1);
$week = new App\Week;
$week->user_id = $user->id;
$week->starts = Carbon\Carbon::now();
$week->save();
return $user->getCurrentWeek();
});
Result:
{
id: 1,
user_id: "1",
starts: "2016-09-15 21:42:19",
created_at: "2016-09-15 21:42:19",
updated_at: "2016-09-15 21:42:19"
}
关系属性在第一次访问时延迟加载。加载后,它们不会自动刷新关系中添加或删除的记录。
由于您的 getCurrentWeek()
函数使用关系属性,此代码将起作用:
$week = new Week;
// setup week ...
$user->weeks()->save($week);
// $user->weeks attribute has not been accessed yet, so it will be loaded
// by the first access inside the getCurrentWeek method
dd($user->getCurrentWeek());
但是,此代码将不起作用:
// accessing $user->weeks lazy loads the relationship
echo count($user->weeks);
// relate a new record
$week = new Week;
// setup week ...
$user->weeks()->save($week);
// $user->weeks inside the method will not contain the newly related record,
// as it has already been lazy loaded from the access above.
dd($user->getCurrentWeek());
您可以修改 getCurrentWeek()
方法以使用关系方法 ($this->weeks()
) 而不是属性 ($this->weeks
),这将始终访问数据库,或者您可以添加或删除记录后重新加载关系(使用 load()
方法)。
更改 getCurrentWeek()
方法以使用关系方法 weeks()
(@Bjorn 提供的更新方法)
function getCurrentWeek()
{
return $this->weeks()->orderBy('starts', 'desc')->first();
}
或者,使用 load()
方法刷新关系:
// accessing $user->weeks lazy loads the relationship
echo count($user->weeks);
// relate a new record
$week = new Week;
// setup week ...
$user->weeks()->save($week);
// reload the weeks relationship attribute
$user->load('weeks');
// this will now work since $user->weeks was reloaded by the load() method
dd($user->getCurrentWeek());
只是添加到@patricus 的回答中...
在save/create/update之后,您还可以像这样清空所有缓存的关系数据:
$user->setRelations([]);
或有选择地:
$user->setRelation('weeks',[]);
之后,只有在需要时才会再次延迟加载数据:
$user->weeks
这样你就可以继续使用延迟加载了。