Laravel仅属于一个结果,属于ToMany关系

时间:2019-04-09 11:15:44

标签: laravel eloquent relationship

我在两个表之间有一个关系,而一个联接表只有一个结果。

当我定义Laravel的归属关系时,我不希望只返回一个元素,而只返回一个元素。

有没有办法在Laravel中对此建模?

先谢谢了。

[ EDIT ]

我将使用经典的“用户/角色”示例来解释我想要的内容。除了de usersroles表之外,我们还有一个users_roles数据透视表,该数据透视表将存储用户拥有的所有角色。用户在任何给定时间只能拥有一个活动角色(由active属性为true标识)。

class User {
    function role() {
        return $this->belongsToMany('App\Role')->wherePivot('active', 'true');
    }
}

有了这个关系定义,当我访问$user->role时,我将获得一组Roles(仅包含一个元素)。我想直接拥有那个Role实例。

5 个答案:

答案 0 :(得分:2)

如果您只需要一种关系,我不知道您为什么拥有belongsToMany,但是下面的代码将为您提供帮助:

   func employeeByFirstName(fName: String) -> [Employee]{

    let viewContext = self.persistentContainer.viewContext

    var substitutionVariables: [String: Any] = [String : Any]()
    substitutionVariables["FIRSTNAME"] = fName
    let fetchRequest = fetchRequestBy(name: "fetchByFirstName", variables: substitutionVariables) as! NSFetchRequest<Employee>

    do {
        let objects = try viewContext.fetch(fetchRequest)
        return objects
    } catch  {
        let nserror = error as NSError
        fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
    }
}


   func fetchRequestBy(name: String, variables: [String : Any]) -> NSFetchRequest<NSFetchRequestResult>? {
      let model = self.persistentContainer.managedObjectModel
      let fetchRequest = model.fetchRequestFromTemplate(withName: name, substitutionVariables: variables)
      return fetchRequest
   }

OR

public function products()
{
    return $this->belongsToMany('App\Product');
}

public function specific_product()
{
    return $this->products()
                ->where('column','value')->first();
}

答案 1 :(得分:0)

我面临着完全相同的问题,让我向您展示我是如何处理的。

在我的情况下,物料和customer_types之间具有belongsToMany关系,数据透视表包含特定客户类型的物料价格,因此,数据透视表中的记录(价格)与customer_types一样多。

我的期望:当请求某个特定customer_type的价格时,我想获取该特定customer_type的范围价格作为嵌套元素

我所得到的:只有1个元素的集合。

这是我刚开始使用模型时所拥有的:

class Material extends Model
{
    public function customer_types(){
        return $this->belongsToMany('App\CustomerType', 'customertype_material', 'material_id', 'customertype_id')->withPivot('price');
    }
}

当然,当我为特定的customer_type请求customer_types时,结果不是预期的:

$resources = Material::with(['customer_types' => function($query) use ($customer_type_id){
                        $query->where('customertype_id', $customer_type_id);
                       }])->get();

它返回的是一个带有customer_types嵌套集合且具有1个元素的Material模型,这迫使我使用first()或循环1个元素。

解决方案:创建一个扩展数据透视表并为其添加关系的模型。

创建了一个扩展枢轴的新模型:

use Illuminate\Database\Eloquent\Relations\Pivot;

class CustomertypeMaterial extends Pivot
{
    protected $table    = 'customertype_material';
    protected $fillable = ['price', 'customertype_id', 'material_id'];
}

现在,在我的材料模型中添加了一个指向该新模型的关系:

public function scoped_price(){
    return $this->belongsTo('App\CustomertypeMaterial', 'id','material_id');
}

最后,查询加载了这个新的关系:

$resources = Material::with(['scoped_price' => function($query) use ($customer_type_id){
                        $query->where('customertype_id', $customer_type_id);
                       }])->get();

结果是一个Material模型,其上嵌套有scoped_price元素,并由customer_type_id过滤

我不确定这是否是正确的方法,但是它对我有用。

希望有帮助!

答案 2 :(得分:0)

我遇到了这个问题,并且找到了一种非常干净的解决方法。

首先,更改返回belongsToMany结果的访问器函数的名称,以反映这些函数返回多个结果的事实。在您的情况下,这意味着使用roles而不是role

function roles() {
  return $this->belongsToMany('App\Role')->wherePivot('active', 'true');
}

然后将以下内容添加到您的模型中:

protected $appends = ['role'];

public function getRoleAttribute() {
  return $this->roles()->first();
}

现在,当您致电$user->role时,您将获得第一项。

答案 3 :(得分:0)

就我而言,这是最直接的解决方案:

class User extends Model {

    public function services()
    {
        return $this->belongsToMany(Service::class, 'service_user')
                    ->using(ServiceUser::class)
                    ->withPivot('user_id', 'service_id', 'is_main_service');
    }

    public function mainService()
    {
 
        return $this->hasOneThrough(Service::class, ServiceUser::class, 'user_id', 'id', 'id', 'service_id')
                    ->where('is_main_service', 1);
    }
}

数据透视表类:

use Illuminate\Database\Eloquent\Relations\Pivot;

class ServiceUser extends Pivot
{
    
}

答案 4 :(得分:-1)

拉威尔(Laravel)口才是魔幻原理。您可以覆盖魔术方法git lfs fetch --all。如果没有属性,则调用__get方法:

(在您的模型中)

__get

如果您的 public function __get ($name) { $answer = parent::__get($name); if($name=='your_prop'){ $answer=!empty($answer)?$answer[0]:null; } return $answer; } 对多关系返回任何东西,则以数组中的第一个为例。