Laravel - 当你有多对多关系时如何查询

时间:2016-06-12 19:55:00

标签: php mysql laravel eloquent

所以我有两个型号:产品和尺寸。一种产品可能有许多尺寸,一种尺寸可能有许多具有这种尺寸的产品。我使用product_size数据透视表在它们之间建立了许多关系。现在我需要查询具有一定大小的所有产品。这是我的代码:

编辑:

    $minPrice = $request['min'];
    $maxPrice = $request['max'];
    $colors = $request['color'];
    $sizes = $request['size'];

    if (count($request->all()) != 0) {

        $query = Product::with(['sizes' => function($query) use($request) {
            $sizeArray = $request->get('size');
            $query->whereIn('sizes.size', $sizeArray);
        }]);

        if(isset($minPrice) && isset($maxPrice)) {
            $query->whereBetween('price', array($minPrice, $maxPrice));
        }

        if(isset($colors)) {
            $query->whereIn('color_id', $colors);
        }

        $products = $query->get();
    }

以下是我的模特:

class Product extends Model
{
    public function color()
    {
        return $this->belongsTo('App\Color');
    }

    public function sizes()
    {
        return $this->belongsToMany('App\Size', 'product_size')->withTimestamps();
    }
}

尺寸:

class Size extends Model
{
    public function products()
    {
        return $this->belongsToMany('App\Product', 'product_size')->withTimestamps();
    }
}

形式:

<form id="filterOptions" method="get" action="{{ URL::current() }}">
    <button type="submit" class="btn-color">Filter</button>

    <div class="clearfix space20"></div>
    <h5>Color</h5>
    <ul class="color-list">
        @foreach($availableColors as $color)
            <li><input type="checkbox" name="color[]" value="{{ $color->id }}"><a href="#"><span class="{{ $color->name }}"></span> {{$color->name_bg}}</a></li>
            {{ $color->name }}
        @endforeach
    </ul>
    <div class="clearfix space20"></div>

    <h5>Price</h5>
    <div id="slider-container"></div>
    <p>
        <span class="{{--pull-right--}} sc-range">
            <input class="pull-left" name="min" type="text" id="min" style="border: 0; color: #333333; font-weight: bold;"/>
            <input class="pull-right" name="max" type="text" id="max" style="border: 0; color: #333333; font-weight: bold;"/>
        </span>
    </p>

    <div class="clearfix space30"></div>
    <h5>Size</h5>
    <ul class="size-list">
        @foreach($availableSizes as $size)
            <li><input type="checkbox" name="size[]" value="{{ $size->id }}">{{ $size->size }}</li>
        @endforeach
    </ul>
</form>

这是我目前的代码。除了查询尺寸外,一切都有效。它不输出任何错误。但是,它不会根据大小查询产品。

3 个答案:

答案 0 :(得分:2)

您需要的是“Querying Relationship Existence”和whereIn()方法的组合:

$products = Product::whereHas('size', function ($query) {
    // In the following line, replace "name" with the appropriate
    // field that relates to $request['size'].
    $query->whereIn('name', (array)$request['size']);
})->get();

答案 1 :(得分:0)

试试这个

    $criteria = array(
        "prices" => array(
            $request['min'] ? $request['min'] : false,
            $request['max'] ? $request['max'] : false
        ),
        "colors" => $request['color'] ? $request['color'] : false,
        "sizes" => $request['size'] ? $request['size'] : false
    );



    $products = Product::with(['sizes' => function ($query) use ($criteria) {

        if($criteria['sizes']) {
            foreach ($criteria['sizes'] as $size) {
                $query->where('size', '=', $size);
            }
        }

    }])->where(function ($query) use ($criteria) {

        if($criteria['colors']) {
            foreach ($criteria['colors'] as $color) {
                $query->where('color_id', '=', $color);
            }
        }

        if( $criteria['prices'][0] && $criteria['prices'][1] ) {
            $query->whereBetween('price', $criteria['prices'] );
        }

    })->get();

答案 2 :(得分:0)

问题不够明确,我可能错了,但无论如何。你可以试试这个。因此,首先,您不需要使用以下内容:

$minPrice = $request['min'] ? $request['min'] : null;

相反,您可以使用以下内容:

$minPrice = $request->min;

如果存在则返回一个值,否则返回NULL值。因此,在您的示例中,您可以简单地使用:

$minPrice = $request->min; // Or  : $request->get('min', 'default value if null');
$maxPrice = $reques->max;  // Also: $request->input('max');
$colors = $request->color;
$sizes = $request->size;

但是,在您的情况下,由于您根据输入有条件地构建查询,因此您可以使用类似:$request->has('String|Array')的内容,例如,让我们尝试以下方法有条件地构建查询:

// Begin query: No need to check for the size, query will work if
// there is no size available, hence 'sizes' will an be empty collection
$query = Product::with(['sizes' => function($query) use($request) {
    $sizeArray = $request->get('size'); // Make sure it's an array
    $query->whereIn('size', $sizeArray); // if null, the query'll work
}]);


// Now check min & max and make query
$minAndMaxKeys = ['min', 'max'];
if($request->has($minAndMaxKeys)) {
    // This'll return, ex: ['min' => 10, 'max' => 20]
    $minAndMaxArray = $request->only($minAndMaxKeys);

    // Build query using min and max values from the array
    $query->whereBetween('price', array_values($minAndMaxArray));
}

// Now check colors and make query
if($colors = $request->get('colors')) {
    $query->whereIn('color_id', $colors);
}

现在,只需执行查询:

$result = $query->get();

$result将包含Product模型的集合,其中price范围与colors相匹配,其中每个Product模型将包含相关尺寸(尺寸集合)如果找不到匹配项,则为空sizes集合。

如果您只想在尺寸可用时获取结果,请将whereHaswith一起使用。检查另一个答案。

由于您的问题信息较少,因此无法准确回答。查看Laravel文档以便更好地理解。