Order collection of products interleaving according to flag

3

I have a model called Product which has, in addition to the product data, a featured flag that says whether the products are highlighted or not. At the time of mounting the view the products should be displayed according to the following HTML structure: link

As you can see the product with the flag featured has a larger grid. I have tried a number of ways and I can not find a logic for this, as I have not found a way to sort the collection so that 1 featured product is followed by 4 other products without highlighting, so on.

Does anyone have any light?

    
asked by anonymous 25.01.2017 / 15:58

1 answer

2

Well, my advice is to bring two sets of results from the database, remember that you can sort them when you go to the database, eg: ...->orderBy('preco', 'DESC');

$feat = Product::where('feature', 1)->get(); // array com os produtos featured
$no_feat = Product::where('feature', 0)->get(); // array com os produtos não featured

Then following the logic below, you do:

$feat = ['featured', 'featured', 'featured']; // produtos featured
$no_feat = ['brrh', 'brrh', 'brrh', 'brrh','brrh', 'brrh', 'brrh', 'brrh', 'brrh', 'brrh', 'brrh', 'brrh', 'brrh', 'brrh', 'brrh', 'brrh']; // produtos não featured
$all = [];
$all_len = count($feat) + count($no_feat);
for($i = 0; $i < $all_len; $i++) {
    if($i%5 == 0 && count($feat) > 0) {
        $all[] = array_shift($feat);
        continue;
    }
    if(count($no_feat) > 0) {
        $all[] = array_shift($no_feat);
    }
    else {
        $all[] = array_shift($feat);
    }
}

echo '<pre>', print_r($all), '</pre>';

Output:

Array
(
    [0] => featured
    [1] => brrh
    [2] => brrh
    [3] => brrh
    [4] => brrh
    [5] => featured
    [6] => brrh
    [7] => brrh
    [8] => brrh
    [9] => brrh
    [10] => featured
    [11] => brrh
    [12] => brrh
    [13] => brrh
    [14] => brrh
    [15] => brrh
    [16] => brrh
    [17] => brrh
    [18] => brrh
)

At the end of this, the arrays of the products declared at the beginning, $feat and $no_feat will be empty:

DEMONSTRATION

But when you see your jsfiddle:

  <div class="row">
    <div class="col-xs-6 featured"></div>
    <div class="col-xs-6">
      <div class="col-xs-6 box"></div>
      <div class="col-xs-6 box green"></div>
      <div class="col-xs-6 box red"></div>
      <div class="col-xs-6 box blue"></div>
    </div>
  </div>

I imagine an array in this format will give you the best way:

$feat = ['featured', 'featured', 'featured'];
$no_feat = ['brrh', 'brrh', 'brrh', 'brrh','brrh', 'brrh', 'brrh', 'brrh', 'brrh', 'brrh', 'brrh', 'brrh'];
$all = [];
$h = 0;
$all_len = count($feat) + count($no_feat);
for($i = 0; $i < $all_len; $i++) {
    if($i%5 == 0 && count($feat) > 0) {
        $all[] = array_shift($feat);
        $h++;
        continue;
    }
    if(count($no_feat) > 0) {
        $all['no_feat' .$h][] = array_shift($no_feat);
    }
    else {
        $all[] = array_shift($feat);
    }
}
echo '<pre>', print_r($all), '</pre>';

Output:

Array
(
    [0] => featured
    [no_feat1] => Array
        (
            [0] => brrh
            [1] => brrh
            [2] => brrh
            [3] => brrh
        )

    [1] => featured
    [no_feat2] => Array
        (
            [0] => brrh
            [1] => brrh
            [2] => brrh
            [3] => brrh
        )

    [2] => featured
    [no_feat3] => Array
        (
            [0] => brrh
            [1] => brrh
            [2] => brrh
            [3] => brrh
        )

)

DEMONSTRATION

Then on the blade you could do:

@foreach($all as $prod)
    @if(!is_array($prod))
        <div class="col-xs-6 featured"></div>;
        <?php continue; ?>
    @endif
    <div class="col-xs-6">;
    @foreach($prod as $no_feat_prod)
        <div class="col-xs-6 box no-featured"></div>
    @endforeach
    </div>
@endforeach
    
25.01.2017 / 16:31