Laravel:根据可选条件从variouos表中获取数据

时间:2016-10-12 06:35:02

标签: laravel eloquent

我想根据可选条件编写一个查询,该查询将从不同的表中获取数据。我的架构看起来像

myboxes表

 id,
 type_id    --> foreign key to box_type table
 postal_code  
 po_box
 created_at
 updated_at

mybox_access表

 id
 mybox_id   -> foreign key to myboxes table
 email

box_type表

id
type_name

这是我的模特 MyBox.php

class MyBox extends Model {
    public function type() {
        return this->hasOne(BoxType::class, 'id', 'type_id');
    }

    public function access() id
        return this->hasOne(MyBoxAccess::class, 'mybox_id', 'type_id');
    }
}

MyBoxType.php有以下关系

  public function mybox() {
        return this->hasOne(MyBox::class, 'id', 'type_id');
    }

MyBoxAccess.php有以下关系

  public function vbox() {
      return $this->belongsTo(MyBox::class, 'id', 'mybox_id');
  }

现在我希望得到以下条件 我有必要的电子邮件param和postal_code和po_box作为可选参数(但其中一个必须,两者也可以存在)。

所以我想获取所有my_box的数据,这些my_box拥有type_id 3或者所有我的mybox都与mybox_access表中的电子邮件匹配,而postal_code或po_box与myboxes表中的params匹配

对于params邮政编码和po_box的简单匹配,我可以写一些像

这样的东西
 $result = new MyBox();
 if(!empty($request['postal_code'])) {
     $result->where('postal_code', like, '%'.$request['postal_code']);
 }
 if(!empty($request['po_box'])) {
     $result->where('po_box', like, '%'.$request['po_box']);
 }
 $result = $result->get();

但我不知道如何获取上述条件的数据。当我尝试使用with()之类的

MyBox::with(['access' => function(Builder $query) use ($request){
     $query->where('mybox_id',$request['id']);
}])->get();

我得到了

`Argument 1 Passed to {closure} () must be an instance of Illuminat\Database\Query\Builder, instance of Illuminate\Databaase\Eloquent\Relation\HasOne given`

任何人都可以告诉我如何根据上述条件获取数据

2 个答案:

答案 0 :(得分:1)

$query是一种关系,而不是构建器实例。

所以这不应该抛出任何异常。

MyBox::with(['access' => function ($query) {
    $query->where('mybox_id', $request['id']);
}])->get();

但我不认为它会解决您的问题,因为您的Box< =>访问关系不对。它应该是HasMany。

// MyBox.php
public function type()
{
    return $this->hasOne(BoxType::class, 'id', 'type_id');
}
public function access()
{
    return $this->hasMany(MyBoxAccess::class, 'mybox_id', 'id');
}

然后在您的控制器中,您可以这样做。

// $results where type_id is 3
$results = MyBox::where('type_id', 3)->get();

// List of boxes accessible by email
$results = MyBox::whereHas('access', function ($query) {
    $query->where('email', request()->input('email'));
})->get();

// Results where postal_code and po_box matches the request
$results = MyBox::with('access')->where(function ($query) {
    if (request()->has('postal_code')) {
        $query->where('postal_code', 'like', '%' . request()->input('postal_code'));
    }
    if (request()->has('po_box')) {
        $query->where('po_box', 'like', '%' . request()->input('po_box'));
    }
})->get();

如果你想合并所有条件:

$results = MyBox::where(function ($query) {
    if (request()->has('type_id')) {
        $query->where('type_id', request()->input('type_id'));
    }
    if (request()->has('email')) {
        $query->whereHas('access', function ($query) {
            $query->where('email', request()->input('email'));
        });
    }
    if (request()->has('postal_code')) {
        $query->where('postal_code', 'like', '%' . request()->input('postal_code'));
    }
    if (request()->has('po_box')) {
        $query->where('po_box', 'like', '%' . request()->input('po_box'));
    }
})->get();

在封闭中使用时,我始终使用request()外观,对我来说感觉更干净。

答案 1 :(得分:0)

尝试此查询:

MyBox::with('access')->get();