Laravel 5 M2M多态关系没有设置?
Laravel 5 M2M Polymorphic relations not setting?
基本代码如下:
/**
* Post.php
*/
class Post extends Illuminate\Database\Eloquent\Model {
public function tags() {
return $this->morphToMany('Tag', 'taggable', 'taggable_taggables')
->withTimestamps();
}
}
/**
* Tag.php
*/
class Tag extends Illuminate\Database\Eloquent\Model {
protected $table = 'taggable_tags';
public function taggable() {
return $this->morphTo();
}
}
现在输入以下代码:
// assume that both of these work (i.e. the models exist)
$post = Post::find(1);
$tag = Tag::find(1);
$post->tags()->attach($tag);
到目前为止一切顺利。正在 taggable_taggables
枢轴 table 中创建关系。但是,如果我立即这样做:
dd($post->tags);
它returns 是一个空集合。 attach()
似乎在 数据库中创建关系 但不是在模型的当前实例中。
这可以通过再次加载模型来检查:
$post = Post::find(1);
dd($post->tags);
现在关系水化了。
我很确定这在 Laravel 4.2 中有效——即关系在 attach()
后立即更新。有什么办法可以推动 Laravel 5 做同样的事情吗?
Laravel无论是eager loaded还是lazy loaded,都会只加载一次关系属性。这意味着一旦加载了属性,除非显式重新加载关系,否则对关系的任何更改都不会反映在属性中。
您发布的确切代码应该按预期工作,所以我假设缺少了一部分。例如:
$post = Post::find(1);
$tag = Tag::find(1);
$post->tags()->attach($tag);
// This should dump the correct data, as this is the first time the
// attribute is being accessed, so it will be lazy loaded right here.
dd($post->tags);
对战:
$post = Post::find(1);
$tag = Tag::find(1);
// access tags attribute here which will lazy load it
var_dump($post->tags);
$post->tags()->attach($tag);
// This will not reflect the change from attach, as the attribute
// was already loaded, and it has not been explicitly reloaded
dd($post->tags);
要解决此问题,如果需要刷新关系属性,可以使用 load()
方法,而不是重新检索父对象:
$post = Post::find(1);
$tag = Tag::find(1);
// access tags attribute here which will lazy load it
var_dump($post->tags);
$post->tags()->attach($tag);
// refresh the tags relationship attribute
$post->load('tags');
// This will dump the correct data as the attribute has been
// explicitly reloaded.
dd($post->tags);
据我所知,没有任何参数或设置可以强制 Laravel 自动刷新关系。我也想不出您可以挂钩的模型事件,因为您实际上并没有更新父模型。我能想到的主要有三个选项:
在执行附加和重新加载的模型上创建一个方法。
public function attachTags($tags) {
$this->tags()->attach($tags);
$this->load('tags');
}
$post = Post::find(1);
$tag = Tag::find(1);
$post->attachTags($tag);
dd($post->tags);
创建一个扩展 BelongsToMany 关系 class 的新关系 class 并覆盖 attach
方法以执行您想要的逻辑。然后,创建一个扩展 Eloquent 模型 class 的新模型 class,并覆盖 belongsToMany
方法以创建新关系 class 的实例。最后,更新您的 Post 模型以扩展您的新模型 class,而不是 Eloquent 模型 class。
只需确保在需要时始终重新加载您的关系。
基本代码如下:
/**
* Post.php
*/
class Post extends Illuminate\Database\Eloquent\Model {
public function tags() {
return $this->morphToMany('Tag', 'taggable', 'taggable_taggables')
->withTimestamps();
}
}
/**
* Tag.php
*/
class Tag extends Illuminate\Database\Eloquent\Model {
protected $table = 'taggable_tags';
public function taggable() {
return $this->morphTo();
}
}
现在输入以下代码:
// assume that both of these work (i.e. the models exist)
$post = Post::find(1);
$tag = Tag::find(1);
$post->tags()->attach($tag);
到目前为止一切顺利。正在 taggable_taggables
枢轴 table 中创建关系。但是,如果我立即这样做:
dd($post->tags);
它returns 是一个空集合。 attach()
似乎在 数据库中创建关系 但不是在模型的当前实例中。
这可以通过再次加载模型来检查:
$post = Post::find(1);
dd($post->tags);
现在关系水化了。
我很确定这在 Laravel 4.2 中有效——即关系在 attach()
后立即更新。有什么办法可以推动 Laravel 5 做同样的事情吗?
Laravel无论是eager loaded还是lazy loaded,都会只加载一次关系属性。这意味着一旦加载了属性,除非显式重新加载关系,否则对关系的任何更改都不会反映在属性中。
您发布的确切代码应该按预期工作,所以我假设缺少了一部分。例如:
$post = Post::find(1);
$tag = Tag::find(1);
$post->tags()->attach($tag);
// This should dump the correct data, as this is the first time the
// attribute is being accessed, so it will be lazy loaded right here.
dd($post->tags);
对战:
$post = Post::find(1);
$tag = Tag::find(1);
// access tags attribute here which will lazy load it
var_dump($post->tags);
$post->tags()->attach($tag);
// This will not reflect the change from attach, as the attribute
// was already loaded, and it has not been explicitly reloaded
dd($post->tags);
要解决此问题,如果需要刷新关系属性,可以使用 load()
方法,而不是重新检索父对象:
$post = Post::find(1);
$tag = Tag::find(1);
// access tags attribute here which will lazy load it
var_dump($post->tags);
$post->tags()->attach($tag);
// refresh the tags relationship attribute
$post->load('tags');
// This will dump the correct data as the attribute has been
// explicitly reloaded.
dd($post->tags);
据我所知,没有任何参数或设置可以强制 Laravel 自动刷新关系。我也想不出您可以挂钩的模型事件,因为您实际上并没有更新父模型。我能想到的主要有三个选项:
在执行附加和重新加载的模型上创建一个方法。
public function attachTags($tags) { $this->tags()->attach($tags); $this->load('tags'); } $post = Post::find(1); $tag = Tag::find(1); $post->attachTags($tag); dd($post->tags);
创建一个扩展 BelongsToMany 关系 class 的新关系 class 并覆盖
attach
方法以执行您想要的逻辑。然后,创建一个扩展 Eloquent 模型 class 的新模型 class,并覆盖belongsToMany
方法以创建新关系 class 的实例。最后,更新您的 Post 模型以扩展您的新模型 class,而不是 Eloquent 模型 class。只需确保在需要时始终重新加载您的关系。