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 )
Related
I would like to add a list of categories to my conditional statement, how should I add multiple categories id ?
Using like 123,124,125 or 123 || 124
I have a big list of categories so I am looking for the cleanest way to achieve that
thanks
<?php
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$product = $objectManager->get('Magento\Framework\Registry')->registry('current_product');
$categories = $product->getCategoryIds(); /*will return category ids array*/
foreach($categories as $category){
$cat = $objectManager->create('Magento\Catalog\Model\Category')->load($category);
echo $cat->getId();
}
?>
<?php if($cat->getId()==123): ?>
<?php echo $block->getLayout()->createBlock('Magento\Cms\Block\Block')->setBlockId('myblockid')->toHtml();?>
<?php endif; ?>
Use in_array PHP function:
<?php if(in_array($cat->getId(), [123, 124, 125])): ?>
The best solution is to use in_array function
<?php
if(in_array($cat->getId(), $your_array){
$block->getLayout()->createBlock('Magento\Cms\Block\Block')->setBlockId('myblockid')->toHtml();
}
?>
Use in_array() : This Checks if a value exists in an array or not.Return true if exist.
<?php
if(in_array($cat->getId(), $categories ):
echo $block->getLayout()->createBlock('Magento\Cms\Block\Block')->setBlockId('myblockid')->toHtml();
endif;
?>
So I have this foreach loop that looks like this:
Well, I need to pass into the same foreach loop another variable that unfortunately I can't get it through the getCategories() function;
So I have another function with another variable, that is passed through this template by a controller from a class function, is there a way I can use another variable into the same foreach? e.i:
Example:
$template->countries=$className->functionFromClass();//returns =something;
//getCategories() returns=thing;
how do I use countries variable in the same foreach bellow?
The template:
<!--how do I add $countries variable in this foreach?-->
<?php foreach(getCategories() as $category && $countries as $country) : ?>//this is not working
<?php echo $category->name; ?>&<?php echo $country->name;?>
<?php endforeach;?>
The result that I am looking for:
thing&something
I've made research and there are indeed questions and responses about foreach but with arrays,I don't have arrays here, my variables are returned as a single word and they come from 2 different tables, can someone help me in this problem?
Try something like this:
<?php $countries = getCountries(); // function that return countries array ?>
<?php foreach(getCategories() as $i=>$category) : ?>
<?php $country = isset($countries[$i]) ? $countries[$i] : end($countries); ?>
<?php echo $category->name; ?>&<?php echo $country->name; ?>
<?php endforeach;?>
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
Can someone tell me what is wrong with this code :
foreach ($data as $region ):
foreach ($region as $type):
foreach ($type as $type2):
foreach ($type2 as $key=>$val):
if ($val=='background-color: FFFFFF;' || $val=='') unset($type2[$key]);
endforeach;
endforeach;
endforeach;
endforeach;
After print_r($data) seems that the data array is the same and unset is not working
Your loop is operating on copies of the original elements; changes to $type2 will not be visible in $data because $type2 is a copy.
You can solve this by iterating over all arrays by key, then indexing into $data with those keys to remove the value:
foreach ($data as $k1 => $region ):
foreach ($region as $k2 => $type):
foreach ($type as $k3 => $type2):
foreach ($type2 as $k4 =>$val):
if ($val=='background-color: FFFFFF;' || $val=='') {
unset($data[$k1][$k2][$k3][$k4]);
}
endforeach;
endforeach;
endforeach;
endforeach;
Of course this is ugly, but that's four nested loops will do. There is also the option if iterating by reference instead of grabbing keys, but personally I dislike that because of the nice opportunity to write bugs by reusing the abandoned references after the loop has ended. Especially in this case I dislike it to the fourth power.
use this, it should work:
foreach ($data as &$region ):
foreach ($region as &$type):
foreach ($type as &$type2):
foreach ($type2 as $key=>$val):
if ($val=='background-color: FFFFFF;' || $val=='') unset($type2[$key]);
endforeach;
endforeach;
endforeach;
endforeach;
the array values are passed as reference because of the & i put before the value variables. The unset will work this way
Basically I have a set of object values I want render in 2 separate html lists
I figure the simplest way to do this is by displaying evens only in one list, and odd only in the other
Here is the current code for displaying a single list
<ul>
<?php foreach ($values as $value) : ?>
<li><?php echo $value->value; ?></li>
<?php endforeach; ?>
</ul>
Try this:
<ul>
<?php
/* read the index key */
foreach ($values as $key => $value) :
/* skip the current element if it doesn't have an even index */
if($key % 2 == 1) continue;
?>
<li><?php echo $value->value; ?></li>
<?php endforeach; ?>
You didn't specify if the array has integer index. So I use a separate index pivot. This will do.
$v=array();
$index = 1;
foreach ($values as $value){
$v[($index++)%2][]=$value->value;
}
list ($evens, $odds) = $v;
echo "<ul><li>".implode("</li><li>", $odds)."</li></ul>"; // show list of odds
echo "<ul><li>".implode("</li><li>", $evens)."</li></ul>"; // shows list of even