Foreach - show the number of items - php

I have this code to count the objects in the foreach loop (images in a gallery):
<?php $images = get_field('galerie'); if( $images ): ?>
<?php $i=1; foreach( $images as $image ): ?>
<?php echo $i++; ?>
<?php endforeach; ?>
<?php endif; ?>
So when i have 4 items (images) it gives me
1 2 3 4
But i need only the highest number like:
4
when i have 4 imgages. Any idea how do i get this number?

Why not just count the images ?
<?php
$images = get_field('galerie');
if($images && is_array($images)) { // in case get_galerie returns null or empty strings when no images...
echo count($images);
}
?>
Also, no need to put <?php ... ?> tags on each line.
Enclose a whole block of PHP code into this tag, it's far more readable, and works the same.

There is a count function.
$length = count($images);

it's simple, just do it like this:
<?php $images = get_field('galerie'); if( $images ): ?>
<?php $i=0; foreach( $images as $image ): ?> //$i=0 not 1
<?php $i++; ?>
<?php endforeach; ?>
<?php echo $i; ?>
<?php endif; ?>
L.E: just for those who down-voted my answer, I kept the users way of coding for 2 (I thought obvious) reasons:
He might actually need the foreach()
He might be new to PHP, and if the iterator method ($i = 1; $i++) is what he knows he should stick with it until he discovers something new. This is a algorithm method inherited from C, Pascal and other much "older" programming languages.
Of course, the count() method is faster and gives a way less pain in the behind, but this is NOT a bad way to code for a beginer.
Hope this helps! :D

Related

Getting the value outside the foreach php loop

Here is the code used to get the ids of a images in a gallery
<?php $images = get_field('photogallery');?>
<?php foreach( $images as $image ): ?>
<?php echo $image['ID']; ?>
<?php echo ','; ?>
<?php endforeach; ?>
I get the output
1102 , 3380 , 3348 , 3354 , 3355 ,
I would like to get this outside the loop because the result must be used in other shortcode also I see there is a whitespace after every number.
the result must be
1102,3380,3348,3354,3355
Please help me.. thanks
You don't need to put <?php ... ?> everytime everywhere for each statement. Keep in mind that each time you close with ?> all characters are sent to the client until the next opening <?php, that's why you obtain spaces around each comma:
<?php foreach( $images as $image ): ?>#
#####<?php echo $image['ID']; ?>#
#####<?php echo ','; ?>#
<?php endforeach; ?>
(I changed white-spaces to #, this way you can see characters sent to the client (the browser)).
You can use array_map to "filter" only ID items and implode to join them , then you only need to store the result in a variable ($result here).
<?php
$images = get_field('photogallery');
$result = implode(',', array_map(function ($i) { return $i['ID']; }, $images));
echo $result;
?>
Now you can use $result later everywhere you want.
Much simpler:
<?php echo implode(',' array_column($images, 'ID')); ?>
extract the ID values using array_column()
implode() those array values using a comma

Wordpress multiple loops and general loop

I need creating custom multiple loops for my blog home.php in order to show 3 different content layout of defined category then proceed with the general loop excluding posts ID within the first 3 loops.
So far I made the the 3 different content layout of defined category category_name=arts:
<?php $posts = get_posts('numberposts=1&offset=0'); foreach ($posts as $post) : start_wp(); ?>
<?php static $count1 = 0; if ($count1 == "1") { break; } else { ?>
<?php the_title(); ?>
<?php $count1++; } ?>
<?php endforeach; ?>
<?php query_posts('category_name=arts&showposts=1'); ?>
<?php $posts = get_posts('numberposts=1&offset=1'); foreach ($posts as $post) : start_wp(); ?>
<?php static $count2 = 0; if ($count2 == "1") { break; } else { ?>
<?php the_title(); ?>
<?php $count2++; } ?>
<?php endforeach; ?>
<?php query_posts('category_name=arts&showposts=1'); ?>
<?php $posts = get_posts('numberposts=1&offset=2'); foreach ($posts as $post) : start_wp(); ?>
<?php static $count3 = 0; if ($count3 == "1") { break; } else { ?>
<?php the_title(); ?>
<?php $count3++; } ?>
<?php endforeach; ?>
I did get stuck to proceed with the general loop. Any suggestions are much appreciated.
You have serious issues here
For each loop you are running two queries, one withget_posts() and one with query_posts
You are making use of query_posts which you should never ever use. This adds a huge overhead on your query as you rerun the main query, so you are actually running 3 queries to get 1 post for each loop. This slows your page down which costs you dearly when it comes to SEO
Furthermore, query_posts breaks the main query object which breaks thousands of functions an plugins that relies on the main query object. You should really spent time and read this post on just how really bad query_posts is.
start_wp() was already depreciated in WordPress version 1.5. This means your code has bugs, and one should avoid bugs at all costs. You should really turn on debug while developing as debug will immediately throw a debugging message telling you that you are using a depreciated function. Here is an article from the codex on how to work with the debugging feature in WordPress. You should be using setup_postdata( $post )
Still on the debugging part, showposts was dropped in favor of posts_per_page
You are running a foreach loop without making sure you have posts to display. ALWAYS ALWAYS make sure you have valid values before you try to do anything with a dynamic variable. This will avoid numerous bugs should your variable return an empty value.
You should really work on your formatting as your code is quite hard to read when everything is packed into one line. Use proper indentation. Properly indented and formatted code does help a lot with readability and debugging. Also, drop the : and endforeach syntax. Although it is valid, it is not supported by code editors which make debugging a nightmare should your code fail. I always tell everyone to use the old style curly brackets as all code editors support them. They make debugging very easy
ALWAY ALWAYS, VERY IMPORTANT, always reset custom queries. Use wp_reset_postdata() to reset the $post global whenever you call setup_postdata() or the_post() in a custom query. Just for interest, because I have already stated to never use query_posts, you should use wp_reset_postdata() to reset custom queries created with query_posts
Lastly, you can do what you need with the specified category in only one loop, not three. Simply make use of your counters. If this is purely for styling, you can simply use the :nth child() selector in css3
The following is untested, but you can try the following
$special_cat_args = [
'category_name' => 'art',
'posts_per_page' => 3,
//Add extra arguments here
];
$art_posts = get_posts( $special_cat_args );
// Setup a variable to store the post ID's so we can exclude them in the 'main' query
$ids_array = [];
// Check if we have posts before we continue
if ( $art_posts ) {
// Start our counter
$counter = 0;
// Start the loop
foreach ( $art_posts as $post ) {
// Setup postdata, must use $post
setup_postdata( $post );
// Store the post id in an array to exclude in "main" query
$ids_array[] = $post->ID;
// Do something separate for every post
if ( 0 == $counter ) {
// Do something for post one
} elseif ( 1 == $counter ) {
// Do something for post two
} elseif ( 2 == $counter ) {
// Do something for post three
}
// Update the counter
$counter++;
} //endforeach $art_posts
wp_reset_postdata(); // VERY VERY IMPORTANT
} //endif $art_posts
// Now we can do our "main" query and exclude the three posts from the special category
$args = [
'post__not_in' => $ids_array, // Exclude the three post from previous query
// Rest of your arguments
];
$q = get_posts( $args );
// Run your loop

Iterating through foreach loop - group sorting effiiceny

I have a loop running in my project that I am not happy with and wondered if there is a more efficient way of achieving this?
I have an array like so
$myarray = ["value1", "value2", "value3"];
Then I want to go through another object ($sponsors) and only print out values on that has a field that matches the value in $myarray[]. Like so:
<?php foreach ($myarray as $value): ?>
<?php foreach ($sponsors as $post) : setup_postdata( $post );?>
<?php if($post['someValue'] == $value): ?>
//Do the work
<?php endif; ?>
<?php endforeach; ?>
<?php endforeach; ?>
This is working fine, but it might mean 50-60 loops just to grab and print out a few bits of markup. Is there a better way to do this?
EDIT NOTE: (based on initial replies) The order of the $myarray is important, this allows me to group the 'value1' together and then 'value2' etc
You can get rid of outer foreach loop
<?php foreach ($sponsors as $post) : setup_postdata( $post );?>
<?php if(in_array($post['someValue'], $myarray)): ?>
//Do the work
<?php endif; ?>
<?php endforeach; ?>
UPDATE
Given $sponsers is an array of posts, You can improve peformance by filterig posts based on some value by native array_filter() function So there are less posts for foreach to iterate over.
After this there is no need for if statement which will also improve performance.
<?php foreach ($myarray as $value): ?>
<?php $filteredPosts = array_filter($sponsors, function($post) use ($value) { return $post['someValue'] == $value; }); ?>
<?php foreach ($filteredPosts as $post) : setup_postdata( $post );?>
// do something
<?php endforeach; ?>
<?php endforeach; ?>
use in_array
ref in_array from here
<?php
foreach ($sponsors as $post) {
setup_postdata( $post );
if(in_array($post['someValue'],$myarray){
//Do the work
}
}
?>
Use in_array function
it takes three parameter but one is optional
for e.g. :
in_array($value, $myarray )

How to skip the first instance in a foreach loop and limit to 8?

I was wondering if anyone could give me a hand with this...
Basically I am trying to modernize the news system of my site but I can't seem to limit the amount of posts showing in the foreach loop that is on my blog part of the site. I need to skip the first instance as it is already promoted at the top of the page. I've tried various google searches but im getting results for C++ Perl and python, what is really irritating. I just need a simple PHP solution. I'll pop my code below and see if anyone can help. Thanks for any help in-advance. And please remember to leave your responses as an answer so I can mark them up if they helped ;)
<div class="view22 full" style="margin-top:0;">
<h3>Recent News and Announcements</h3>
<?php foreach ($articles as $article) {
?>
<div class="ah7_ clearfix">
<p class="date"><?php echo date('F j', $article['article_timestamp']); ?>, <?php echo date('Y', $article['article_timestamp']); ?></p>
<h3><?php echo $article['article_title']; ?></h3>
</div>
<?php
}
?>
</div>
I assume that the $articles array has keys starting with 0. How about modifying the loop like this:
foreach ($articles as $key => $article)
and checking if $key is 0 at the beginning?
if($key == 0)
continue;
If the array keys are different: Create a new variable $i, set it to 0 and increase the value by 1 in every foreach loop iteration.
$i = 0;
foreach ($articles as $article) {
$i++;
if($i == 1)
continue;
elseif($i > 8)
break;
//the other code goes here
}
In case it is based on a SQL query, using "limit" might help to reduce load!
There are a few things you can do:
If you $articles is an array of array, having continous indexes, use a for loop instead of foreach and do something like
for ($i = 1; $i < 8 : $i++ ) {
// and access it like
$articles[$i]['some_index'] ...
}
If it is not then you can use an external counter
Say
$counter = -1;
foreach ( $articles as $article) {
$counter++;
if (!$counter) continue;
if ($counter > 7 ) break;
...// your code //
}
You can change your Mysql query to give you only the desired data, using LIMIT and OFFSET
To remove the first instance you can manually unset the item ($articles[0]) after making a copy of it or printing it as a featured news.
To limit the number of post you can use the mysql LIMIT Clause;
Or you can do something like this
foreach($articles as $key => $article){
if($key===0)
continue;
if($key===8)
break;
echo $article;// or_do_whatever_youwant_with($article);
}

php foreach even and odd but vice versa after printing 2 rows

In my application I have to loop images with two sizes. Lets call them large and small.. These images are in two columns like below.
large small
large small
large small
I produce the larage/small image by a class by doing this now like this:
<?php $count = 0; ?>
<?php foreach ($posts as $post) : ?>
<div class=" <?=(++$count%2 ? "col-7 pr-10" : "col-5 pl-10");?> mt-15">
<?php endforeach; ?>
What I would like to do here by now is to produce this list;
large small
small large
large small
etc..
In what kind of way can I do this? I guess I have to create a kind of reset after each 2 entries and set odd to eve and vise versa ?
In general if you need A B; B A; A B; etc in consecutive loops, you could do this:
$row = 0;
foreach ($posts as $post) {
if ($row%2) echo "A, B\n"; else echo "B, A\n";
$row++;
}
This looks quite a bit like your codeā€¦
If instead you really mean that you need to do
A
B
B
A
(pattern repeating every 4th row, in essence), then a clear and reasonable approach is:
$row = 0;
foreach ($posts as $post) {
$temp = $row%4;
if ($temp == 0 || $temp == 3 ) echo "A\n"; else echo "B\n";
$row++;
}
This can obviously be made more compact - but I usually find that "explicit" is easier to read six months later - and the performance impact is negligible.
Try replacing
<div class=" <?=(++$count%2 ? "col-7 pr-10" : "col-5 pl-10");?> mt-15">
with
<div class=" <?=($count%4 == 1 || ? $count%4 == 2)"col-7 pr-10" : "col-5 pl-10"; $count++;?> mt-15">
<?php $count = 0; $flag = 0;?>
<?php foreach ($posts as $post) : ?>
<?php $flag = $count%2 == 0 ? $flag + 1 : $flag;?>
<div class=" <?=(($count++ +$flag)%2 ? "col-7 pr-10" : "col-5 pl-10");?> mt-15">
<?php endforeach; ?>

Categories