Jump to content

Counting number of pages in foreach


louisstephens
 Share

Recommended Posts

So I have a bit of code for ad management :

<?php
    $ads = $pages->find("parent.template=client, sort=expiration_date");
        $alert_count = 0;
        
        foreach ($ads as $ad) {
            $todaysdate = date("F j, Y H:i");
            $today = strtotime($todaysdate);
            $expireson = $ad->expiration_date;
            $expires = strtotime($expireson);
            $fiveaway = $expires - 432000;
                                
            if ($today > $expires) {
                $alert = $alert_count=+1;
                echo $alert;
            }
        } //end FOREACH 
?>

It currently finds all the pages with a parent of "client" and then I can drill down to the pages that have "Expired" in my if statement. I wanted to get a "count" of the pages that met the if statement requirements so I could output that number in an alert at the top of the page. When it runs, it currently just prints out "1 1 1 1..." and not the total count of pages. Does anyone know of a way possibly achieving my desired output? I tried count(), but that did not quite produce my desired output.

 

I should note that I have several other if statements dealing with the date/time for outputting other alerts as well (just didn't think they were needed for this case).

Link to comment
Share on other sites

Ah, thanks @flydev for catching my typo. I guess because it is in a "foreach", it just keeps counting so I get "1 2 3..." . I guess I didnt know how to handle putting the if outside the foreach since I dont know how to access $ad->expiration_date. Is there a better way of doing this?

 

 

Edit** : Just moved echoing the $alert outside the foreach which gave me the count. However, if anyone had a better solution I welcome it. I seem to be using 3 foreach loops with an if inside each one just to accomplish this (so I can wrap a div column around them.).

Link to comment
Share on other sites

One thing to make your foreach loop a bit smaller and faster is to move these lines of code (below). Just set them before the foreach loop. As far as I can see you are checking the date for each ad, but it's always the same so it's faster to define it once.

$todaysdate = date("F j, Y H:i");
$today = strtotime($todaysdate);

So that results in this:

$ads = $pages->find("parent.template=client, sort=expiration_date"); // === Get $ads
$alert_count = 0; // === Set alert count
$todaysdate = date("F j, Y H:i"); // === Get the date
$today = strtotime($todaysdate); // === Make a string from the date
        
foreach ($ads as $ad) { // === Start foreach
	$expireson = $ad->expiration_date;
	$expires = strtotime($expireson); // === I think you can also shorten this to $expires = strtotime($ad->expiration_date); Maybe you can even try $fiveaway = strtotime($ad->expiration_date) - 432000;
	$fiveaway = $expires - 432000;

	if ($today > $expires) {
		$alert_count += 1;
	}
} // === End Foreach 

echo $alert_count; // === Echo the counter result 

Hope this helps...

  • Like 2
Link to comment
Share on other sites

Quote

a better solution

Checking expiration_date in the selector should do the trick.

$todaysdate = date("F j, Y H:i");
$today = strtotime($todaysdate);
$ads = $pages->find("parent.template=client, expiration_date<$today, sort=expiration_date");
echo count($ads);

 

  • Like 2
Link to comment
Share on other sites

There's also $pages->count(selector) method available. 

<?php
$today = strtotime('today');
// $today = strtotime('now'); is also available

// count pages that have expired before today
$alertCount = $pages->count("parent.template=client, expiration_date<=$today");

https://processwire.com/api/ref/pages/count/

FYI, you dont have to convert date back and forth, strtotime returns UNIX timestamp, and PW understands it perfectly.

  • Like 3
Link to comment
Share on other sites

Thank you everyone for all the help!  Is something like this possible, or am I reaching :P? (sorry, still trying to learn my way through php and some things are still a bit intimidating) 

$ads = wire('pages')->find("parent.template=manufacturer, $today < expiration_date && expiration_date-432000 > $today, sort=expiration_date");

 

Link to comment
Share on other sites

27 minutes ago, louisstephens said:

Is something like this possible

You can use AND operator for that.

https://processwire.com/api/selectors/#and-selectors

<?php
$today = new \DateTime(); // set to now
$inFiveDays = $today->modify('+5 days');

$tsToday = $today->getTimestamp();
$tsInFiveDays = $inFiveDays->getTimestamp();

// selectors are built in the order: field<operator>value
// repeat a field for AND operation 
$ads = $pages->find("parent.template=manufacturer, expiration_date>=$tsToday, expiration_date<=$tsInFiveDays, sort=expiration_date");

 

  • Like 3
Link to comment
Share on other sites

44 minutes ago, abdus said:

You can use AND operator for that.

https://processwire.com/api/selectors/#and-selectors


<?php
$today = new \DateTime(); // set to now
$inFiveDays = $today->modify('+5 days');

$tsToday = $today->getTimestamp();
$tsInFiveDays = $inFiveDays->getTimestamp();

// selectors are built in the order: field<operator>value
// repeat a field for AND operation 
$ads = $pages->find("parent.template=manufacturer, expiration_date>=$tsToday, expiration_date<=$tsInFiveDays, sort=expiration_date");

 

Thanks abdus! I guess I was unclear of how to add to the find() in processwire. However, knowing this now, this really helps me condense a lot of my code that I have already written. My head was starting to spin trying to figure out ways (sometimes it was a roller coaster) to deal with my foreachs.

  • Like 1
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

×
×
  • Create New...