【问题标题】:Laravel Model getting only one related modelLaravel 模型只获得一个相关模型
【发布时间】:2020-10-22 08:37:20
【问题描述】:

我得到了一个与工作条款相关的用户模型,它与此类服务相关:

 users      working_terms    services
 id    ->    user_id
             service_id  <-    id 
            active(1 or 0)

我在我的用户模型中创建了一个方法,以便像这样检索活动工作期限的服务

public function service()
    {
        return $this
            ->belongsToMany(Service::class,'working_terms')
            ->where('active','=',1);

    }

问题是我必须像在视图 $user->service[0] 中那样使用它,我认为它应该是 $user->service。 我能做什么?

【问题讨论】:

  • 我只想要一个基于布尔标准而不是数组的记录
  • 如果用户无法与多个服务相关联(例如,通过在数据透视表中添加具有相同 user_id 但不同 service_id 的另一行),那么您需要审查您的数据库设计并制作一对多或一对一的用户服务关系
  • 一个用户在一段时间内可以有多个工作期限但只有一个处于活动状态,每个工作期限都有一项服务,我认为不是数据库设计问题。 working_terms 实际上是一个数据透视表

标签: php laravel eloquent


【解决方案1】:

当 Laravel 评估 $user-&gt;service 时,首先它会确定 $user-&gt;service() 的返回值是否是 Illuminate\Database\Eloquent\Relation\Relation 类的实例,如果不是,那么它会给你错误。您的 service() 方法返回 Illuminate\Database\Query\Builder 而不是 Relation,这就是为什么您的 sn-p $user-&gt;service 没有返回您想要的服务模型。

更多详情,请查看此链接; https://github.com/laravel/framework/blob/8.x/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php#L432

【讨论】:

    【解决方案2】:

    belongsToMany 关系返回 Eloquent Collection,无论您是否提供 where 子句作为关系的一部分。因此,您需要使用first() 来获取第一个(也是唯一一个?)记录。

    顺便说一句,Laravel 有一个数据透视表的命名约定(尽管我相信你有理由选择你拥有的名称)。

    User.php

    public function services()
    {
      return $this->belongsToMany(Service::class)
                  ->withTimestamps();
    }
    
    public function getActiveServiceAttribute()
    {
      return $this->services()
                  ->wherePivot('active', 1)
                  ->first();
    }
    

    以上假设我遵循 Laravel 命名约定,其中 usersservices 表之间的数据透视表命名为 service_user

    create_service_user_table.php

    public function up()
    {
      Schema::create('service_user', function(Blueprint $table) {
        $table->id();
        $table->timestamps();
    
        $table->foreignId('user_id');
        $table->foreignId('service_id');
        $table->unsignedTinyInteger('active')->default(0);
    
        $table->foreign('user_id')->references('id')->on('users');
        $table->foreign('service_id')->references('id')->on('services');
      });
    }
    

    由于您没有遵循 Laravel 命名约定,您需要在 services() 函数中将数据透视表的名称作为第二个参数提供给 belongsToMany 关系(或者如果可能,更改数据透视表名称并遵守约定)。

    您现在应该能够执行以下操作:

    // obtain a collection of all services the User has been associated with
    User::find(1)->services
    
    // obtain the currently active service for the User
    User::find(1)->activeService
    

    【讨论】:

      猜你喜欢
      • 2020-05-25
      • 2020-02-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-12
      • 2017-02-16
      • 2019-07-27
      • 2016-05-04
      相关资源
      最近更新 更多