Foreach and 2D Array in PHP - php

$mainMenu['Home'][1] = '/mult/index.php';
$mainMenu['Map'][1] = '/mult/kar.php';
$mainMenu['MapA'][2] = '/mult/kara.php';
$mainMenu['MapB'][2] = '/mult/karb.php';
$mainMenu['Contact'][1] = '/mult/sni.php';
$mainMenu['Bla'][1] = '/mult/vid.php';
This is a menu, 1 indicates the main part, 2 indicates the sub-menu. Like:
Home
Map
-MapA
-MapB
Contat
Bla
I know how to use foreach but as far as I see it is used in 1 dimensional arrays. What I have to do in the example above?

You would need to nest two foreach BUT, there is nothing about your data structure that easily indicates what is a sub-item. Map vs. MapA? I guess a human could figure that out, but you'll have to write a lot of boilerlate for your script to sort that.. Consider restructuring your data so that it more closely matches what you are trying to achieve.
Here's an example. You can probably come up with a better system, though:
$mainMenu = array(
'Home' => '/mult/index.php',
'Map' => array(
'/mult/kar.php',
array(
'MapA' => '/mult/kara.php',
'MapB' => '/mult/karb.php'
)
),
'Contact' => '/mult/sni.php',
...
);

You nest foreach statements; Something like this should do the work.
foreach($mainMenu as $key=>$val){
foreach($val as $k=>$v){
if($k == 2){
echo '-' . $key;
}else{
echo $key;
}
}
}

Foreach can just as easily be used in multi-dimensional arrays, the same way you would use a for loop.
Regardless, your approach is a little off, here's a better (but still not great) solution:
$mainMenu['Home'][1] = '/mult/index.php';
$mainMenu['Map'][1] = '/mult/kar.php';
$mainMenu['Map']['children']['MapA'] = '/mult/kara.php';
$mainMenu['Map']['children']['MapB'] = '/mult/karb.php';
$mainMenu['Contact'][1] = '/mult/sni.php';
$mainMenu['Bla'][1] = '/mult/vid.php';
foreach($mainMenu as $k => $v){
// echo menu item
if(isset($v['children'])){
foreach($v['children'] as $kk => $vv){
// echo submenu
}
}
}
That said, this only does 1-level of submenus. Either way, it should help you get the idea!

Related

Combine more than 2 Smarty Arrays

When using array_combine I'm able to combine two array and use the loop through. In the example below I can us $title in my HTML.
{foreach array_combine($p_titles, $p_prices) as $title => $price}<!--SOME HTML-->{/foreach}
However if I try to add another array to this solution it breaks. My local host isn't displaying an error other than "Page not Working "localhost is currently unable to handle this request."
{foreach array_combine($p_titles, $p_prices, $p_ids) as $title => $price => $id}<!--SOME HTML-->{/foreach}
How do I combine 3 or more arrays using this method.
First of all, you tagged Javascript however what you have shown in you question is PHP.
Second, the array_combine only accepts two parameters. Documentation.
To use array_combine for three arrays do this:
$combinedArray = array_combine($p_titles, $p_prices);
$combinedArray = array_combine($combinedArray, $p_ids);
Edit: Answer that matches your code in normal PHP syntax.
$result = array();
foreach($p_titles as $key => $value)
{
$result[$value] = array('price' => $p_prices[$key], 'id' => $p_ids[$key]);
}
echo($result);
You can access this data like these: $result['title']['price'] or $result['title']['id'];
Edit 2: And the Smarty code.
I'm not that familiar with Smarty syntax so this might not work:
{ $result = array(); }
{ foreach from=$p_titles key=key item=value }
{ $result[$value] = array('price' => $p_prices[$key], 'id' => $p_ids[$key]) }
{ /foreach }

php - Find array for which a key have a given value

I have an array of dictionnaries like:
$arr = array(
array(
'id' => '1',
'name' => 'machin',
),
array(
'id' => '2',
'name' => 'chouette',
),
);
How can I find the name of the array containing the id 2 (chouette) ?
Am I forced to reindex the array ?
Thank you all, aparently I'm forced to loop through the array (what I wanted to avoid), I thought that it were some lookup fonctions like Python. So I think I'll reindex with id.
Just find the index of array that contains the id you want to find.
SO has enough questions and answers on this topic available.
Assuming you have a big array with lots of data in your real application, it might be too slow (for your taste). In this case, you indeed need to modify the structure of your arrays, so you can look it up faster, e.g. by using the id as an index for the name (if you are only interested in the name).
As a for loop would be the best way to do this, I would suggest changing you array so that the id is the arrays index. For example:
$arr = array(
1 => 'machin',
2 => 'chouette',
);
This way you could just get the name for calling $arr[2]. No looping and keeping your program running in linear time.
$name;
foreach ($arr as $value){
if ( $value['id'] == 2 ){
$name = $value['name'];
break;
}
}
I would say that it might be very helpful to reindex the information. If the ID is unique try something like this:
$newarr = array();
for($i = 0;$i < count($arr);$i++){ $newarr[$arr[$i]['id']] = $arr[$i]['name']; }
The result would be:
$newarr = array('1'=>'machin','2'=>'chouette');
Then you can go trough the array with "foreach" like this:
foreach($newarr as $key => $value){
if($value == "machin"){
return $key;
}
}
But of course the same would work with your old array:
foreach($arr as $item){
if($item['name'] == "machin"){
return $item['id'];
}
}
It depends on what you are planning to do with the array ;-)
array_key_exist() is the function to check for keys. foreach will help you get down in the multidimensional array. This function will help you get the name element of an array and let you specify a different id value.
function findKey($bigArray, $idxVal) {
foreach($bigArray as $array) {
if(array_key_exists('id', $array) && $array['id'] == $idxVal) {
return $array['name'];
}
}
return false;
}
//Supply your array for $arr
print(findKey($arr, '2')); //"chouette"
It's a bit crude, but this would get you the name...
$name = false;
foreach($arr as $v) {
if($v['id'] == '2') {
$name = $v['name'];
break;
}
}
echo $name;
So no, you are not forced to reindex the array, but it would make things easier.

Need help to grouping php arrays to make it better

First of all, my grouping is working but I feel it is dirty. Need someone to make it looks
clean and better.
I have following foreach
$data['new_array'] = array(); //I have to use $data['new_array'] because I need to pass it to template.
foreach ($get_topics as $topic) {
//Is that possible to make these 4 lines shorter?
$data['new_array'][$topic['tid']]['tid'] = $topic['tid'];
$data['new_array'][$topic['tid']]['title'] = $topic['title'];
$data['new_array'][$topic['tid']]['yes'] = $topic['yes'];
$data['new_array'][$topic['tid']]['no'] = $topic['no'];
//The belows are subarray grouping, it actually works but I need better solutions
//$new_array[$topic['tid']]['vid'][$topic['vid']][] = $topic['vid'];
//$new_array[$topic['tid']]['vid'][$topic['vid']][] = $topic['yesno'];
}
I wouldn't even try to make it shorter, but here's your code in a good looking version.
$data['new_array'] = array();
foreach ($get_topics as $topic) {
$data['new_array'][$topic['tid']] = array(
'tid' => $topic['tid'],
'title' => $topic['title'],
'yes' => $topic['yes'],
'no' => $topic['no']
);
}
Not sure what type is $topic['tid'] but you should be careful when using non-consecutive numbers as array keys.

PHP Multidimensional Arrays

I'm trying to make a universal script that adds keywords to my individual pages (since header is in an include file) so I am getting the end of the url (multi.php) and retrieving the desc etc. from it's array. For some reason instead of returning keywords or descriptions it instead just returns "m" . . . it's kind of random and has me scratching my head. Here's what I got
<html>
<head>
<title>Multi-Demensional Array</title>
<?php
$path = pathinfo($_SERVER['PHP_SELF']);
$allyourbase = $path['basename'];
$pages = array
(
"multi.php" => array
(
"keywords" => "index, home, test, etc",
"desc" => "This is the INDEX page",
"style" => "index.css"
),
"header.php" => array
(
"keywords" => "showcase, movies, vidya, etc",
"desc" => "SHOWCASE page is where we view vidya.",
"style" => "showcase.css"
)
);
?>
</head>
<body>
<?php
foreach($pages as $key => $value)
{
if($key == $allyourbase)
{
echo $key['desc'];
}
}
?>
</body>
</html>
The reason why this is happening is because in PHP if I had the following code:
$hello = 'world';
and I attempted to do the following:
echo $hello[0];
PHP Would treat the string as an array and return me whatever is in position 0, which would result in w, when your using a foreach your asking PHP to set the key of the array to $key, and it's value to $value.
you then echo echo $key['desc'];, as the value is a string, php sees it as an integer based index, so it will ignore your call for desc and then return the first index, if you were to change echo $key['desc'] to echo $value['desc'] which is a hash based array it will return the desired results.
You should just be able to do this:
if(isset($pages[$allyourbase]))
{
echo $pages[$allyourbase]['desc'];
}
No need for the loop
try
echo $key['desc'];
replace with
echo $value['desc'];
Other people have provided some great solutions, but it's important that you understand exactly what is happening here, so you don't make the same mistake again. Pay careful attention to the comments, and you will be on your way to successful coding!
Here's what is happening:
foreach ($pages as $key => $value) {
if ($key == $allyourbase) {
// At this point: $key = 'multi.php'
// Also: $value = array( ... );
// Keep in mind: $key['desc'] = $key[0] = 'm';
// You are grabbing the first letter of the 'multi.php' string.
// When dealing with strings, PHP sees $key['desc'] as $key[0],
// which is another way to grab the very first character of 'multi.php'
echo $key['desc'];
// You really want $pages[$key]['desc'], but below
// is a better way to do it, without the overhead of
// the loop.
}
}
If you kept the loop, which is really unnecessary, it would look like this:
foreach ($pages as $key => $value) {
if ($key == $allyourbase) {
echo $value['desc'];
}
}
The best solution is to replace the loop with the following code:
if (isset($pages[$allyourbase])) {
echo $pages[$allyourbase]['desc'];
} else {
// error handling
}
If I'm reading this right, echo $key['desc']; should be echo $value['desc'];.

How do I have a more advanced array?

Basically I currently put a bunch of values into an array like so:
$flavors = array('Original','Cherry','Chocolate','Raspberry','Mango');
and from this I might execute a foreach like so:
foreach($flavors as $flav) {
echo doSomething($flav);
}
This all works a treat, until I get to the next stage of my learning which is to perhaps put 2 variables into doSomething().
For example, say I want to include the ingredients of Cherry e.g
echo doSomething($flav, $ingredient_of_this_flav);
I'm not sure if there is any way to go about doing this... I imagine I might need a second array entirely where I use the values above as my keys? e.g
$ingredients = array('Original' => 'boring stuff', 'Cherry' => 'cherries and other stuff') etc
And then I would doSomething() like so
foreach($flavors as $flav) {
echo doSomething($flav, $ingredients[$flav]);
}
I suppose I should go try this now. Is this the best approach or is there a better way to go about this? Ideally I would just have the one array not have to set $flavors and $ingredients.
Thanks for your time.
Arrays in php are associative, as you've noticed. And if I understand correctly, you're looking for the syntax to loop through each key/value pair?
foreach($ingredients as $flav => $ingredient) {
echo doSomething($flag, $ingredient);
}
Is this what you're looking for?
If you're looking to have complex values for each key, than you might want to look into objects, or the more brutal version, arrays of arrays.
$ingredients = array('Cherry' => array('Cherries', 'Other stuff'));
And your $ingredient in the loop above will be an array.
You can foreach over the keys and values of an array.
foreach ($ingredients as $flav => $ingredients)
{
echo doSomething($flav, $ingredients);
}
I would use an associative array (aka hash table) with a flavor => ingredients approach. Something like this:
$flavors = array ('Cherry' => array('stuff1', 'stuff2'),
'Mango' => array('stuff1', 'stuff3'));
echo $flavors['Cherry'][0]; // stuff1
foreach($flavors as $flavor => $ingredients)
{
print $flavor;
// $ingredients is an array so we need to loop through it
foreach($ingredients as $ingredient)
{
print $ingredient;
}
}
This is known as a nested loop and will print the flavor and each ingredient.
You are nearly there. I would set the array to be something like:
$ingredients = array('Original' => array('boring stuff', 'boring stuff2'), 'Cherry' => array('cherries', 'other stuff'));
And then loop as follows:
foreach($flavors as $flav => $ingredient) {
echo doSomething($flav, $ingredient);
}
Of course, it all depends on what you do in "doSomething()"

Categories