Filtering pages problem

Hi to all, stuck a little with creating controller…

$bonuses = page('reviews')->children()->listed()->sortBy('rating')->flip()->filter(function ($child) {
	    return $child->bonus_offers()->isNotEmpty();
	});

Also I was trying to do this in other way

$collection = pages();

if ($bonuses) {
foreach ($bonuses as $bonus) {
	foreach ($bonus->bonus_offers()->toStructure() as $bonus_offer) {
		$collection->add($bonus);
	}
}
$bonuses = $collection;
}

the problem is some reviews could have 2-3 bonuses, and i wish to create listing that could repeat reivew logo, url but have different bonus options that is placed in bonus_offers structure field

Maybe preset more simple way how can I do it?

Right now I have only one review in listing, even if this review have more than one bonus…

For Example:

Review 1
- Bonus 1
- Bonus 2
- Bonus 3
Review 2
- Bonus 1
Review 3
- Bonus 1
- Bonus 2

The listing what I want to have is:
Review 1 (Bonus 1), Review 1 (Bonus 2), Review 1 (Bonus 3), Review 2 (Bonus 1), Review 3 (Bonus 1), Review 3 (Bonus 2)

Hm, I think you are on the right track, the controller part is OK (I’d modify it slightly):

$reviewsWithBonus = page('reviews')->children()->listed()->sortBy('rating')->flip()->filter(function ($child) {
	    return $child->bonus_offers()->toStructure()->count();
});

Then in your template, loop through the filtered reviews:

<?php
if ($reviewsWithBonus->count()):
  foreach ($reviewsWithBonus as $review):
    foreach ($review->bonus_offers()->toStructure() as $bonus):
      // echo the fields of bonus offer
    endforeach;
  endforeach;
endif;

1 Like

You superstar! As always :metal:

Last question is it possible to sort reviews by bonus_offer date that is placed in structure field?

I’d either use a page model or the map() method for this purpose.

$reviewsWithBonus = page('reviews')->children()->listed()->sortBy('rating')->flip()->filter(function ($child) {
	    return $child->bonus_offers()->toStructure()->count();
});

$sortedReviews = $reviewsWithBonus->map(function($item) {
  $item->sortDate = $item->bonus_offers()->toStructure()->sortBy('date', 'asc')->first()->date();
  return $item;

})->sortBy('sortdate', 'desc');

Depending on which date you want to sort by, here I sort the bonus offers in ascending order, get the first item’s date and set it as sortDate.

1 Like

seems it is not works (

Am I right that i need to change

<?php
if ($reviewsWithBonus->count()):
  foreach ($reviewsWithBonus as $review):
    foreach ($review->bonus_offers()->toStructure() as $bonus):
      // echo the fields of bonus offer
    endforeach;
  endforeach;
endif;

to this (after creating in controller $sortedReviews filter):

<?php
if ($sortedReviews->count()):
  foreach ($sortedReviews as $review):
    foreach ($review->bonus_offers()->toStructure() as $bonus):
      // echo the fields of bonus offer
    endforeach;
  endforeach;
endif;

The question is what exactly you want to achieve. We are sorting the reviews here, not the bonuses. If you want to sort all bonuses of all structure fields by date, then the code would have to be different.

You are right, I want to sort bonus offers by date.


Im add numbers of order that is should be correct…

In this example we have 2 reviews
every review is have 2 bonuses.

So list should be

Review 1 Bonus 1 / Review 1 Bonus 2 / Review 2 Bonus 1 / Review 2 Bonus 2

For example if we add to Review 3 Bonus with date 22/04/2019 it should be placed on second place

Ah, ok, that was not clear from your first explanation. To achieve this, you have to fetch all structure field entries from all review pages into one collection (like you tried in your first post), but not into a pages collection, but into a new structure.

Something like:

$reviewsWithBonus = page('reviews')->children()->listed()->sortBy('rating')->flip()->filter(function ($child) {
	    return $child->bonus_offers()->toStructure()->count();
});


$bonuses = new Structure();

foreach ($reviewsWithBonus as $review) {
  $offers = $review->bonus_offers()->toStructure();
  $bonuses->add($offers);
}

$bonuses = $bonuses->sortBy('date', 'asc');

You then loop through the bonuses in your template. If you need information from the page, you can access it via the parent() method:

foreach ($bonuses as $bonus) {
  echo $bonus->date()->toDate('d.m.Y');
  $p = $bonus->parent(); // get the page for each item
  echo $p->title();
}
1 Like

It’s absolutely great) sincerely thank you for your help!