php – Sort product collection by inserting flag

Question:

I have a model called Product that has, in addition to product data, a featured flag that says whether the product is featured or not. When setting up the view, the products must be displayed according to the following HTML structure: https://jsfiddle.net/efhhnbsj/1/

As can be seen the product with the featured flag has a larger grid. I've tried several ways and I can't find a logic for it, because I couldn't find a way to order the collection so that 1 product is highlighted followed by 4 other non-highlighted products, and so on.

Does anyone have any lights?

Answer:

Now my advice is to bring two sets of results from the database, remember that you can order them when you fetch them from 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, 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 products declared at the beginning, $feat and $no_feat will be empty:

DEMONSTRATION

But when seeing 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 that an array in this format gives you better use:

$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
Scroll to Top