【问题标题】:Laravel 5 M2M Polymorphic relations not setting?Laravel 5 M2M多态关系未设置?
【发布时间】:2015-02-18 04:45:01
【问题描述】:

这是基本代码:

/**
 * 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 数据透视表中创建。但是,如果我立即这样做:

dd($post->tags);

它返回一个空集合。 attach() 似乎在 数据库 中创建了关系,但在模型的当前实例中没有。

这可以通过再次加载模型来检查:

$post = Post::find(1);
dd($post->tags);

现在这段关系已经水合了。

我很确定这在 Laravel 4.2 中有效——即关系在 attach() 之后立即更新。有没有办法推动 Laravel 5 做同样的事情?

【问题讨论】:

  • 我现在不太确定这在 Laravel 4.2 中是否有效。但我仍然想知道是否可以推动 Laravel(4.2 和/或 5)这样做。

标签: php laravel laravel-5 eloquent polymorphic-associations


【解决方案1】:

Laravel 只会加载一次关系属性,无论是急切加载还是延迟加载。这意味着一旦加载了属性,对关系的任何更改都不会反映在属性中,除非明确重新加载关系。

您发布的确切代码应该按预期工作,所以我假设缺少一部分。例如:

$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 自动刷新关系。我也想不出你可以挂钩的模型事件,因为你实际上并没有更新父模型。我能想到三个主要选项:

  1. 在模型上创建一个执行附加和重新加载的方法。

    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);
    
  2. 创建一个新的关系类来扩展 BelongsToMany 关系类并覆盖 attach 方法以执行您想要的逻辑。然后,创建一个扩展 Eloquent Model 类的新模型类,并重写 belongsToMany 方法以创建新关系类的实例。最后,更新您的 Post 模型以扩展您的新模型类,而不是 Eloquent 模型类。

  3. 只要确保始终在需要时重新加载您的关系。

【讨论】:

  • 感谢您的详细解释。实际上,我是在附加之前加载标签,这可以解释为什么我在强制重新加载之前看不到它们。最后,我按照您在第一个建议中的建议进行了操作:在附加后手动运行->load('tags')
猜你喜欢
  • 2016-05-26
  • 2018-04-25
  • 2017-02-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-20
相关资源
最近更新 更多