简体   繁体   English

Laravel Eloquent有条件的地方

[英]Conditional wherehas with Laravel Eloquent

I have one similar ( area ) value in two tables one and two and these two tables has relation with main table master . 我在两个表onetwo有一个相似的( area )值,这两个表与主表master表有关。 At a time, the master table will be having data in one relation only and the other one will be null . 一次, master表将仅具有一种关系的数据,而另一种将为null

With this architecture, I have a search page where user can search any values related to these tables and the search fields are placed with AND condition. 使用这种体系结构,我有一个搜索页面,用户可以在其中搜索与这些表相关的任何值,并且将搜索字段放置为AND条件。

Here, if user enters some value for area I need to check the area value exists in any one of the tables ( one or two ) without breaking the AND condition. 在这里,如果用户输入area某个值,我需要检查任何一个表( onetwo )中存在的面积值,而不会破坏AND条件。 Tried the below code but it is breaking AND rule and considering OR . 尝试了以下代码,但它违反了AND规则并考虑了OR Any suggestions to fix? 有什么建议可以解决吗?

$result =  Master::where(function ($query) use ($request) {
    if ($request->filter == true) {
        $query->where('user_id', Auth::user()->id);
    }
    // other conditions here
    if (!empty($request->area_from) && !empty($request->area_to)) {
        $query->whereHas('one', function ($query) use ($request) {
            $query->whereBetween('area', [$request->area_from, $request->area_to]);
        });
        $query->orWhereHas('two', function ($query) use ($request) {
            $query->whereBetween('area', [$request->area_from, $request->area_to]);
        });
    }
    // other conditions here

})->with(['one', 'two'])->paginate($request->item);

You are wrapping all of your where statements in brackets. 您将所有where语句包装在方括号中。 I think what you want to do is pull your first part of the query out of the where clause so that you can easily wrap the whereHas part in brackets. 我认为您想要做的是将查询的第一部分从where子句中拉出,以便您可以轻松地将whereHas部分包装在方括号中。

// Initialise the model
$query = new Master;

// Start building the query
if ($request->filter == true) {
    $query->where('user_id', Auth::user()->id);
}

if (!empty($request->area_from) && !empty($request->area_to)) {
    // Wrap these in brackets so we don't interfare with the previous where
    $query->where(function($query2) use ($request) {
        $query2->whereHas('one', function ($query3) use ($request) {
            $query3->whereBetween('area', [$request->area_from, $request->area_to]);
        });
        $query2->orWhereHas('two', function ($query3) use ($request) {
            $query3->whereBetween('area', [$request->area_from, $request->area_to]);
        });
    }
}

$query->with(['one', 'two'])->paginate($request->item);

You can create a merged relationship refer this link 您可以创建合并关系, 请参考此链接

public function mergedOneAndTwo($value)
{
    // There two calls return collections
    // as defined in relations.
    $onedata= $this->one;
    $twodata= $this->two;

    // Merge collections and return single collection.
    return $onedata->merge($twodata);
}


and use whereHas('mergedOneAndTwo') 并使用whereHas('mergedOneAndTwo')

Using a closer where and making the conditional inside may work fine 在更近的地方使用闭环并使其有条件

$master = Master::with('one')->with('two');
$result = $master->where(function($subQuery)
{   
    $subQuery->whereHas('one', function ( $query ) {
        $query->whereBetween('area', [$request->area_from, $request->area_to] ); //assuming  $request->area_from, $request->area_to is range of value
    })
    ->orWhereHas('two', function ( $query ) {
        $query->whereBetween('area', [$request->area_from, $request->area_to] );
    });
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM