laravel雄辩的“有”方法表现出意想不到的方式

时间:2019-12-16 20:59:09

标签: laravel eloquent laravel-5.8

如果它至少具有一个User,我想获得一个Section模型的集合。从文档中的has()方法可以做到这一点,很棒。检索到的集合中没有users关系。然而,当我遍历集合时,我可以获得users的属性。为什么?

class Section extends Model
{
    protected $guarded = [];

    public function users()
    {
        return $this->hasMany('App\User');
    }
}
class User extends Authenticatable
{
    protected $guarded = [];

    public function section()
    {
        return $this->belongsTo('App\Section');
    }
}

这是我做的:

$section = Section::where('id' , 1)->has('users')->get();

集合是这个:

Illuminate\Database\Eloquent\Collection {#3025
     all: [
       App\Section {#3015
         id: 1,
         class_id: 1,
         section_name: "A",
         created_at: "2019-12-14 18:26:01",
         updated_at: "2019-12-14 18:26:01",
       },
     ],
   }

现在奇怪的是,当我执行以下操作时,即使在集合中不存在users关系,它也提供了用户的属性。

为什么?

 @foreach ($section as $section)
   @foreach ($section->users as $student)
     <p>{{$student->name}}</p>
   @endforeach
@endforeach
solomon
uche
kene

3 个答案:

答案 0 :(得分:0)

好的,现在我明白了你的问题。

  1. 第一

has方法并不意味着它将包含User。这意味着将返回至少有一个用户的所有sections。我认为有Section id === 1的用户。因此,在带有has或不带有with的代码中,它没有任何区别。

如果要显式加载关系,则应使用Section::where('id' , 1)->with('users')->get();

blade。然后您应该在每个部分下收集用户。

  1. 第二

    您仍然可以访问lazy loading文件中的用户属性的原因是由于BeautifulSoup。即使原始数据库查询和结果中没有包含它,但是当您尝试访问它时,laravel仍会尝试为您获取这些内容。这可能会导致N + 1问题。

答案 1 :(得分:0)

看起来像您的第一个回声:

$section = Section::where('id' , 1)->has('users')->get();

仅打印它拥有用户的部分,但您并不是要明确地说给我用户。

在下一个循环中,您将循环遍历视图中的每个部分,并具体说来循环关系。此行可见:@foreach ($section->users as $student)

我在这里阅读文档:https://laravel.com/docs/6.x/eloquent-relationships#querying-relations

在打印部分时的第一次回声中,您可以像这样获得用户:echo $section-> users()

答案 2 :(得分:0)

这就是Laravel的工作方式。

在您的情况下$model->{relationship},访问$section->users是一个魔术函数,它检查您是否已通过类似Section::with('users')的方式显式加载了该关系,如果没有,则进行了加载然后。

在运行users时没有看到dd($section)的原因是您没有显式加载该关系,但这并不意味着该关系不可用。如果您在初始查询中包含with('users'),则会看到以下内容:

$section = Section::where('id' , 1)->has('users')->with('users')->get();

App\Section {#3015
   id: 1,
   class_id: 1,
   section_name: "A",
   created_at: "2019-12-14 18:26:01",
   updated_at: "2019-12-14 18:26:01",
   users: [
     0 => App\User {#3016}
       id: ...
       name: ...
   ]
 },

// Or similar

基本上,您没有加载该关系,因此在使用dd($section)时看不到该关系,但是由于Laravel的魔术方法,该关系在PHP中仍然可用。

我还应该注意,对查询使用正确的变量命名和闭包(->get()->first()等)。

使用$section时,

->get()是一个不好的名字,因为您将从数据库中获取多个记录。要么使用$sections,要么将闭包更改为->first(),如果使用foreach(),则不要使用->first()