【问题标题】:How to insert existing model into relation如何将现有模型插入到关系中
【发布时间】:2021-10-13 14:49:06
【问题描述】:

我经常有两个模型处于 1:x 关系:

class Child extends Model 
{
  public function parent() 
  {
    return $this->belongsTo(Parent::class);
  }
}

现在有时我已经在函数中拥有一个相关模型的实例:

function f(Parent $parent): Child
{
  // ...
  $child = $parent->createChild();
  // ...
  return $child
}

不同的函数将Child 作为参数并需要Parent 类的属性:

function g(Child $child)
{
  $child->update([
    'attribute' => h($child->parent->attribute)  
  ]);
}

现在如果使用从f 返回的Child 实例调用g,那么将从数据库中检索两次Parent 实例。除非我们添加Parent 参数并将实例传递给g,或者修改f 如下:

function f(Parent $parent): Child
{
  // ...
  $child = $parent->createChild();
  // ...
  $child->parent = $parent;
  return $child
}

我更喜欢第二种方法来添加另一个参数,因为调用g 的上下文可能无法访问Parent 实例。它通常工作正常。但是,它在g 中的更新语句上失败:

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'parent' in 'field list' (SQL: update `children`...

所以我的问题是:

有没有办法将现有模型实例插入到适当的关系中,而无需模型将分配注册为列更新?

【问题讨论】:

  • ->setRelation ?
  • ^^ 我的想法完全是另外->associate($model) 用于多态
  • 这是真的public function child()吗? child belongsTo child 或 child belongsTo paren
  • @A.ANoman 不,很好,已修复。

标签: php laravel eloquent laravel-8 database-relations


【解决方案1】:

调用$child->parent = $parent 会尝试在$child 对象上设置parent 字段 属性。但是,您想设置 parent relationship 属性。为此,您需要使用setRelation() 方法:

function f(Parent $parent): Child
{
    // ...
    $child = $parent->createChild();
    // ...
    $child->setRelation('parent', $parent);
    return $child;
}

但是,此时您需要注意不要创建循环引用。如果$parent->child 关系设置为$child 实例,然后您将$child->parent 关系设置为$parent 实例,则您创建了一个循环引用,如果您尝试将任一实例转换为json(或数组)。

也就是说,如果$parent->child->parent === $parent,则存在循环引用,为此创建json/数组将是一个无限循环。

在这种情况下,如果你想格外小心,可以使用withoutRelations() 方法将关系分配给父级的克隆,它不会加载任何关系。

function f(Parent $parent): Child
{
    // ...
    $child = $parent->createChild();
    // ...
    $child->setRelation('parent', $parent->withoutRelations());
    return $child;
}

此后,$parent->is($parent->child->parent) 为真,但$parent->child->parent === $parent 为假,因此没有循环引用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-25
    • 1970-01-01
    • 2019-08-31
    • 1970-01-01
    • 2016-10-15
    • 1970-01-01
    • 2021-04-24
    相关资源
    最近更新 更多