Jump to content

Novice filter() issue…


celfred
 Share

Recommended Posts

Hello,

I can't understand how this destructive filter() work.

Here's my code (with annotations to explain my issue) :

  $teamPlayers = $pages->find("parent.name=players, team=$team");
  bd($monster->name.':'.$teamPlayers->count()); // There should be 24 players in my team (which is the case on first call)
  foreach ($teamPlayers as $p) {
    $result = $p->child("name=tmp")->tmpMonstersActivity->get("monster=$monster, bestTime>0");
    if ($result) {
      $p->bestTime = $result->bestTime;
    } else {
      $p->bestTime = 0;
    }
  }
  $teamPlayers->filter("bestTime>0")->sort("bestTime"); // I want to return only the list of players having a best time on this monster
  return $teamPlayers;

 

My problem is that after several calls (for all monsters) the number of players in the team is not 24 but 1… I guess the $teamPlayers never resets and I can't understand why line 1 doesn't start with 24 again…

If I code this for the 2 last lines, it works :

  $teamMates = $teamPlayers->find("bestTime>0")->sort("bestTime");
  return $teamMates;

But I would like to understand what's going on with my 1st version (I guess it is the destructive aspect of filter()) 😞

So if someone could take a little time to explain, I would appreciate 🙂

Link to comment
Share on other sites

  • 2 weeks later...

sorry too big fingers... let's resume 🙂

there you assign a value to $teamPlayers

when afterwards you apply a method to this var, well, you apply a method but don't store the result of this method in a var which is exactly what you eventually do with your

$teamMates = $teamPlayers->find("bestTime>0")->sort("bestTime");
return $teamMates;

there you apply a method on $teamPlayers and store the result in $teamMates 🙂

hope it helps

have a nice day

  • Thanks 1
Link to comment
Share on other sites

  • 3 weeks later...

Hello @virtualgadjo

Thanks a lot for your answer. I thought I subscribed to the thread but it didn't work so I am seeing this answer just now. Sorry…

I understand your point and tried to look at my issue again. If I got it well, I tested :

$teamPlayers = $teamPlayers->filter("bestTime>0")->sort("bestTime");

and this should work the same as what I did with teh $teamMates var, but…

It doesn't because my $teamPlayers var seems to be gradually destroyed by the filter() method. And that is exactly what I don't understand : why doesn't it come back to 24 when I repeat line 1 :

On 9/29/2021 at 10:54 AM, celfred said:
$teamPlayers = $pages->find("parent.name=players, team=$team");

To try and be exhaustive in my explanations, My structure is like this :

  • in my template, I have a foreach($allMonsters as $m) listing all 'monsters'
  • for a particular monster ($m), I call the method getPosPlayer() trying to get the position of a player according to his or her best time
  • In the getPosPlayer() method, I call getAllTeamTimes() method in which there is the code I mentioned in my first post (hence the part responsible for finding all team players (which doesn't return 24 after a few loops using filter()…which seems to degrade $teamPlayers var although on line 1 of that method I initialize it - or at least I wish I could initialize it 🙂)

Anyway, if I don't use filter() it works, but I wish I could understand what's going on…

Thanks again for helping !

Link to comment
Share on other sites

hi,

hard to answer without testing completely but i think the problem stays the same as above, you first define $teamplayer and then apply a foreach to it and then again a filter to it keeping the same var name

honestly, just php thinking, pw or not, what i would do for debug purpose in your case woud be a print_r of $teamplayer just after its first setting, one more after the foreach, nbot sure it would be any difference... and, again, use a new var name for your last call, something like this
 

$teamPlayers = $pages->find("parent.name=players, team=$team");
//first one
print_r($teamPlayers);

  bd($monster->name.':'.$teamPlayers->count()); // There should be 24 players in my team (which is the case on first call)
  foreach ($teamPlayers as $p) {
    $result = $p->child("name=tmp")->tmpMonstersActivity->get("monster=$monster, bestTime>0");
    if ($result) {
      $p->bestTime = $result->bestTime;
    } else {
      $p->bestTime = 0;
    }
  }

//second one, not sure it will different from the first one as you don't seem to replace the value in $teamPlayers
print_r($teamPlayers);
// and here, what seems the most logical way to do it imho would be
$teammates = $teamPlayers->filter("bestTime>0")->sort("bestTime"); // I want to return only the list of players having a best time on this monster
return $teammates;
// a print_r($teammates); would also be a good way to see if anything happens

but honestly, without kowing exactly the page structure, i just try to guess what those $p->child are... and i must say, usually when using a foreach i first set an empty var and feed it with the first array elements including those i've modified
afterwards you can play with ne new array knowing you haven't modified the base one

hope it helps in terms of debugging path 🙂

have a nice day

Link to comment
Share on other sites

Thanks again for the explanations which is somehow what I do for debugging. I 'follow' my var using bd() and that's what surprises me when I use filter() as explained mentionned above : first loop : $teamPlayers->count() is 24 filter() reduces it to 3 $teamMates, 2nd loop, $teamPlayers initializes back to 24 (as expected) and filter() reduces $teamMates to 3, 3rd loop, $teamPlayers initialize at 3 (???). And after a couple of other loops, when filter() reduces $teamMates to 1, $teamPlayers stays at 1…

And I can't explain this 'destructive' mode that never comes back to the initial value.

The 'child' thing is just the page where I save the bestTime field for a player.

Anyway, I think you've spent enough time trying to help me and I, again, thank you very much for this. I guess I'll have to further dig this filter() method (which I thought I eventually grasped since I use it somewhere else in my code ;)). Maybe things will get better as my skills improve with time.

 

Link to comment
Share on other sites

Hi again 🙂

wow, funny behavior you describe here!!!

in this kind of situation, first thing i would check is if this $teamPlayers var doesn't appear in another place it should not and where it stores something causing this surprising thing...
of course, be sure not to use any cache as it could be your enemy here 🙂

hope you'll figure this out

have a nice day

  • Like 1
Link to comment
Share on other sites

Ok. So one thing you've just written triggered an idea and made me closer to understanding the issue 🙂

I added :

  $pages->unCacheAll();

in my template just before calling my method getPosPlayer() and now the weird behavior I related is back to normal : 24 players initialized all the time and my initial filter() way of doing things worked as expected.

So it is a cache issue ! But I (for the moment) don't know where it comes from. So I'll dig this cache thing and try to find a way to explore what is being cached (and why).

Thanks a lot for your help.

Link to comment
Share on other sites

Hi,

great news! 🙂

have you looked at your template cache settings (or procache if you use it) some pages containing dynamic content, pagination, forms, and so on are better not to be cached sometimes, depending on what you cache or not

the main thing is now you'll stop loosing your hair 😄

and my pleasure

have a nice day (better now :))

Link to comment
Share on other sites

1 hour ago, virtualgadjo said:

have you looked at your template cache settings (or procache if you use it) some pages containing dynamic content, pagination, forms, and so on are better not to be cached sometimes, depending on what you cache or not

Well, after some more research, I still don't get it. My page template's cache is set to 'disabled' (I don't use Procache) and I can't find any place where I would set some cache for this part in my code, but when I do $pages->unCacheAll(), it gets rid of about 100 things and then my code works…

So I guess I'll keep losing my hair, but now I know where they go : it's a cache issue 😉 I'll try to find some resources explaining how that works.

Bye !

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Similar Content

    • By Ksenia
      Hello all! I am pretty new to PW and now trying to figure out how to build a filter that uses AND logic and includes many fields. With help I have figured out Page Reference fields and Repeaters, but simple Text Filed with dropdown text tags makes me confused.
      As I think of it, first I need to get the array of given fixed options of Text Tags here:

      And then I just need to print it out as checkbox form and circle through each page to see if they have the checked value in place of this field. 
      Like what I have with page references:

      But for the life of me I cannot figure out how to get this list...So if you have suggestions, I would really appreciate it!
      Best,
      Kseniia
    • By Saleena Jhon
      Hello There, I have saw a post that was covering event-calendar with php, ajax and js. That was showing a monthly overview when I click on a "month" button or when I switch the month. And show the events on one particular date when I pick a day. Also, most events are kind of exhibitions and so they have a start date and an end date much later, and occur on each day in-between as well. So on the template I put two date picking fileds date_start and date_end. Is there an elegant way to select the events using the API? If yes, kindly help me out.
      Thanks in Advance
      Regards: 
       
    • By Flashmaster82
      Hi, i need some help with the filtering based on the Skyscrapers demo/func. I´m not that great with php so be patient.
      My structure looks like this
      Youtube videos > Youtube channel > Video
      on the video template (youtube_channel_video) i have multiple drop down fields and other fields that i would like to filter on the front end. I also have other pages that need this functions with search/filter etc but with different filters.
       
      This is the code i have in my search-form.php. Right now i experimenting with the field/option (category) that every video have in their template. The first filter (youtube_channel) works but im trying to get the category filter to work.
      <div id='skyscraper-search' class='uk-panel uk-panel-box xuk-panel-box-primary uk-margin-bottom'> <h3 class='h3'>Youtube videos</h3> <form class='uk-form uk-form-stacked' method='get' action='<?php echo $config->urls->root?>search/'> <div class='row'> <label class='uk-form-label' for='search_keywords'>Keywords</label> <div class='uk-form-controls'> <input type='text' class='uk-form-width-large' name='keywords' id='search_keywords' value='<?php if($input->whitelist('keywords')) echo $sanitizer->entities($input->whitelist('keywords')); ?>' /> </div> </div> <div class='col-6'> <div class='row'> <label class='uk-form-label' for='youtube_channel'>Youtube channel</label> <div class='uk-form-controls'> <select id='youtube_channel' name='youtube_channel' class='uk-form-width-large'> <option value=''></option> <?php // generate the youtube_channel options, checking the whitelist to see if any are already selected foreach($pages->find("template=youtube_channel_page") as $youtube_channel) { $selected = $youtube_channel->name == $input->whitelist->youtube_channel ? " selected='selected' " : ''; echo "<option$selected value='{$youtube_channel->name}'>{$youtube_channel->title}</option>"; } ?> </select> </div> </div> </div> <div class='col-6'> <div class='row'> <label class='uk-form-label' for='category'>Category</label> <div class='uk-form-controls'> <select id='category' name='category' class='uk-form-width-large'> <option value=''></option> <?php // generate the category options, checking the whitelist to see if any are already selected foreach($pages->find("template=youtube_channel_video") as $category) { $selected = $category->youtube_video_category == $input->whitelist->youtube_video_category ? " selected='selected' " : ''; echo "<option$selected value='{$category->youtube_video_category}'>{$category->youtube_video_category->title}</option>"; } ?> </select> </div> </div> </div> <div class='uk-margin-top'> <button type='submit' id='search_submit' class='uk-button uk-button-primary' name='submit' value='1'> <i class='uk-icon-search'></i> Search </button> </div> </form> </div>  
      This is my search.php
      <?php namespace ProcessWire; $selector = ''; $summary = array( "title" => "", "youtube_channel" => "", "category" => "", "country" => "", ); if($input->get('youtube_channel')) { $youtube_channelName = $sanitizer->pageName($input->get('youtube_channel')); $youtube_channel = pages("/youtube-videos/$youtube_channelName/"); if($youtube_channel->id) { $selector .= "parent=$youtube_channel, "; $summary['youtube_channel'] = $youtube_channel->title; $input->whitelist('youtube_channel', $youtube_channel->name); } } foreach(array('category') as $key) { if(!$value = $input->get($key)) continue; else { $value = (int) $value; $selector .= "$key=$value, "; $summary[$key] = $value; $input->whitelist($key, $value); } } if($input->get('keywords')) { $value = $sanitizer->selectorValue($input->get('keywords')); $selector .= "title|body|category%=$value, sort=title"; $summary["keywords"] = $sanitizer->entities($value); $input->whitelist('keywords', $value); } $videos = findSkyscrapers($selector); $browserTitle = 'Youtube video search - '; foreach($summary as $key => $value) { if($value) { $key = ucfirst($key); $browserTitle .= ucfirst($key) . ": $value, "; } else { unset($summary[$key]); } } region('browserTitle', rtrim($browserTitle, ', ')); region('content', files()->render('./includes/search-summary.php', array('items' => $summary)) . renderSkyscraperList($videos) );  
      This is my skyscraper-list-item.php file
       
      <?php echo " <div class='col-12 col-sm-12 col-md-6 col-lg-6 col-xl-4 col-xxl-4 col-xxxl-4 bmar10'> <div class='youtube_search_holder'> <a data-fancybox data-autoclose='true' data-width='1500' data-height='844' data-height='360' href='{$skyscraper->youtube}autoplay=1'> <div class='youtube_thumbnail_placeholder'><img src='{$skyscraper->youtube_thumbnail->url}' class='youtube_thumbnail_image w-100'> <div class='playicon'></div></div></a> <div class='youtube_search_thumbnail_content'> <div class='h6 text-uppercase green tmar3 title'><a href='{$skyscraper->parent->channel_url}' target='_blank' title='{$skyscraper->parent->title}'>{$skyscraper->parent->title}</a></div><div class='text-uppercase white h3 limit'><a href='{$skyscraper->youtube}' data-fancybox data-width='1500' data-height='844' data-height='360'>{$skyscraper->title}</a></div> <div class='h5 text-uppercase gray date'>{$skyscraper->youtube_video_publishdate}</div> <span class='white h7'> {$skyscraper->youtube_video_category->title} {$skyscraper->countries->title} {$skyscraper->competition->title} {$skyscraper->competition->parent->parent->title} {$skyscraper->armwrestler_competition_gender->title} {$skyscraper->armwrestler_arm->title} {$skyscraper->armwrestler_age_category->title} {$skyscraper->competition_weight_class->title} {$skyscraper->competition_video_match->title} {$skyscraper->videotags} </span> </div></div></div> "; ?> This is the front end right now (no styling 🙂

      In the category filter, right now there is multiple categories with the same name, i would also like to restrict it to just one result per category.
      Please help!
    • By Bacelo
      Hi there,
      I have a bit of trouble on filtering correctly some event pages by some selectors...
      I do have the following 2 date fields:
      - start date (fieldname = date)
      - end date (fieldname = enddate)

      Some events are a single day event (only start date) - some are a multi day event (end date).
      Past single day events should not show up.
      Current multi day events should show up (even if start day is in the past, but end date is future).
      So I have the following selector:
      if ($standort == '') { $termine = $page->children("sort=date, limit=10, (date>=today, enddate=''), (enddate>=today)"); } else { $termine = $page->children( "(standort_reference~=$standort), (standort_alle=1), (date>=today, enddate=''), (enddate>=today), sort=date, limit=10"); } This selector
      $termine = $page->children("sort=date, limit=10, (date>=today, enddate=''), (enddate>=today)"); works fine, but the follwing does not work (all past entries are also shown):
      $termine = $page->children( "(standort_reference~=$standort), (standort_alle=1), (date>=today, enddate=''), (enddate>=today), sort=date, limit=10"); I have no clue what I'm missing - any ideas?
    • By Moritz Both
      Greetings,
      when I give users the user-admin-* permission to administer users who have a certain role, they can indeed see and edit those users. However the filter / column panel does not show in the admin interface. How can I enable the filter functionality for user-admin-* members?
      ProcessWire 3.0.123
      Moritz
×
×
  • Create New...