Controller for filtering modification help

Hi Guys,

I have multifilter listing http://99bookmakers.com/bookmakers
In first version of site it works perfect
when Star rating was a part of children item bookmaker->rating() and controller looks like this:

return function($site, $pages, $page) {

  // get all articles and add pagination
  $bookmakers = page('bookmakers')->children()->visible();
  

  if($query_rating = get('rating')) {
  		$bookmakers = $bookmakers->search($query_rating, 'rating');
	}
  if($query_market = get('market')) {
  		$bookmakers = $bookmakers->search($query_market, 'market');
	}
  if($query_country = get('country')) {
  		$bookmakers = $bookmakers->search($query_country, 'excluded_countries');
	}
  if($query_payment = get('payment')) {
  		$bookmakers = $bookmakers->search($query_payment, 'deposit|withdrawal');
	}
  if($query_language = get('language')) {
  		$bookmakers = $bookmakers->search($query_language, 'language');
	}
  if($query_currency = get('currency')) {
  		$bookmakers = $bookmakers->search($query_currency, 'currency');
	}
  
  $bookmakers = $bookmakers->paginate(20);

  // create a shortcut for pagination
  $pagination = $bookmakers->pagination();

  // pass $articles and $pagination to the template
  return compact('bookmakers', 'query_market', 'query_rating', 'query_country', 'query_payment', 'query_language', 'query_currency', 'pagination');

};

Right now rating is user generated and added from form http://take.ms/YKZGx creating children for other page http://take.ms/lBgiq

When user add scores it generate overall score
So in loop I can easy get average score for bookmaker:

<div class="bookmaker-rating">
    <?php $collection = page('user-scores')->children()->visible()->filterBy('bookmaker_name', '==', $bookmaker->slug());?>
    <?php $rating = $collection->pluck('rating_10',',', false) ?>
    <?php if(a::average($rating) >= '5'): ?>
    <i class="fa fa-star"></i>
    <i class="fa fa-star"></i>
    <i class="fa fa-star"></i>
    <i class="fa fa-star"></i>
    <i class="fa fa-star"></i>
    <?php elseif(a::average($rating) >= '4'): ?>
    <i class="fa fa-star"></i>
    <i class="fa fa-star"></i>
    <i class="fa fa-star"></i>
    <i class="fa fa-star"></i>
    <i class="fa fa-star-o"></i>
    <?php elseif(a::average($rating) >= '3'): ?>
    <i class="fa fa-star"></i>
    <i class="fa fa-star"></i>
    <i class="fa fa-star"></i>
    <i class="fa fa-star-o"></i>
    <i class="fa fa-star-o"></i>
    <?php elseif(a::average($rating) >= '2'): ?>
    <i class="fa fa-star"></i>
    <i class="fa fa-star"></i>
    <i class="fa fa-star-o"></i>
    <i class="fa fa-star-o"></i>
    <i class="fa fa-star-o"></i>
    <?php elseif(a::average($rating) >= '1'): ?>
    <i class="fa fa-star"></i>
    <i class="fa fa-star-o"></i>
    <i class="fa fa-star-o"></i>
    <i class="fa fa-star-o"></i>
    <i class="fa fa-star-o"></i>
    <?php elseif(a::average($rating) < '1'): ?>
    <i class="fa fa-star-o"></i>
    <i class="fa fa-star-o"></i>
    <i class="fa fa-star-o"></i>
    <i class="fa fa-star-o"></i>
    <i class="fa fa-star-o"></i>
    <?php endif ?>
    <span>(<?php echo page('user-scores')->children()->visible()->filterBy('bookmaker_name', '==', $bookmaker->uid())->count() ?> reviews)</span>

But how can I filter bookmakers throw controller I don’t know. I think It possible if I create array of all user scores based on bookmaker name, and average rating, then I must megre average score for every uniq bookmaker name and then compare score with get param from filter…

Any Ideas?

You could use the filter($callback) method:

if($query_rating = get('rating')) {
  $bookmakers = $bookmakers->filter(function($bookmaker) use ($query_rating) {
    // your code here
  });
}

Thanks, it works, but not correctly

  if($query_rating = get('rating')) {
	  $bookmakers = $bookmakers->filter(function($bookmaker) use ($query_rating) {
		    $collection = page('user-scores')->children()->visible()->filterBy('bookmaker_name', '==', $bookmaker->slug());
		    $rating = $collection->pluck('rating_10',',', false);
		    if($query_rating == array(a::average($rating))) {
			   return $bookmaker;
			}
	  });
	}

I have add this code, but it works only with one option (for example 5) if I select (4 and 5) this function didn’t works. If I change == to >= it didn’t show anything. Also about score… average score could be 3.4 or 4.3 from, how can I add some range to $query_rating. If $query_rating is = 4 I need to filter all bookmakers that have average score >= 3.5 && < 4.5

If query rating is an array, you can use array_intersect(): http://php.net/manual/de/function.array-intersect.php

Yep, this is almost that what I need…

  if($query_rating = get('rating')) {
	  $bookmakers = $bookmakers->filter(function($bookmaker) use ($query_rating) {
		    $collection = page('user-scores')->children()->visible()->filterBy('bookmaker_name', '==', $bookmaker->slug());
		    $rating = $collection->pluck('rating_10',',', false);
		    if(array_intersect($query_rating, array(a::average($rating)))) {
			   return $bookmaker;
			}
	  });
	}

Final question is how can I add some range to $query_rating. If $query_rating is = 4 I need to filter all bookmakers that have average score >= 3.5 && < 4.5

Found :slight_smile: I could use round(a::average($rating))

Thx for big help!

1 Like

Final code is…

  if($query_rating = get('rating')) {
	  $bookmakers = $bookmakers->filter(function($bookmaker) use ($query_rating) {
		    $collection = page('user-scores')->children()->visible()->filterBy('bookmaker_name', '==', $bookmaker->slug());
		    $rating = $collection->pluck('rating_10',',', false);
		    if(array_intersect($query_rating, array(round(a::average($rating))))) {
			   return $bookmaker;
			}
	  });
	  $bookmakers = $bookmakers->sortBy($query_rating, $direction='asc');
	}