Error I'm receiving Invalid argument supplied for foreach()
The offending portions is this:
foreach($subs[$id] as $id2 => $data2)
Strange cause I'm using the same construct elsewhere and it works fine.. I'm using it to generate sub-categories and it works but I want to get rid of the error
This is more context
foreach($parents as $id => $data)
{
if($x == 0)
{
$html .= "<tr width='25%' class='row2'>";
}
$shtml = "";
$i = 0;
***foreach($subs[$id] as $id2 => $data2)***
{
$i++;
if($i == 15)
{
$shtml .= $this->ipsclass->compiled_templates[ 'skin_businesses' ]->portal_categories_sub_row( $id2, $data2['cat_name'], 1 ) . "";
break;
}
else
$shtml .= $this->ipsclass->compiled_templates[ 'skin_businesses' ]->portal_categories_sub_row( $id2, $data2['cat_name'], 0 ) . "";
}
It may be that $subs[$id] is not consistently an array. That is, $subs[0] may be an array, but $subs[1] is a scalar.
Try casting it to be an array:
foreach((array)$subs[$id] as $id2 => $data2)
If $subs[1] is a scalar, then casting it forms an ephemeral array of one element for purposes of iterating over it.
The variable that you pass to the loop is probably not an array. Try to debug your code to find out where it being assigned an value just before being fed into the loop.
If you assinged a single value to that variable somewhere, assign it like this:
$subs[1] = array('somevalue');
PHP is a dynamically typed language but knowing what type a variable has at any given moment is still very important.
Related
To my understanding Input::post(); with no parameters returns an array containing all the data from a specific POST..
I am doing this $all_input = Input::post();
But then I am iterating through the array Java-like (is that how you even do it?)
for ($i=0; $i<count($all_input); $i++)
{
if (strpos($all_input[$i], 'something') == true) // ERROR...
but the application crashes with error Undefined offset: 0 which I believe means that the index was not found?
I have also tried adding this to no avail:
if (!isset($all_input))
{
return;
}
If so how can you access the data to iterate through them? I know it contains data cause I can see them when I press the button during the debugging on the browser if I remove that code.
If you didn't already figure it out I am coming from Java developer and I have just started learning php so bear with me please.
According to this: https://fuelphp.com/docs/classes/input.html#/method_post Input::post(); will return $_POST which is an assoc array.
Here is the source code, because the fuelphp's documentation doesn't cover it exactly.
/**
* Fetch an item from the POST array
*
* #param string $index The index key
* #param mixed $default The default value
* #return string|array
*/
public static function post($index = null, $default = null)
{
return (func_num_args() === 0) ? $_POST : \Arr::get($_POST, $index, $default);
}
You need to refer with your input names, so if you have an input which you call 'name', in that case you need to refer $all_input['name']. You can get your keys by using array_keys() function. Also it's better if you use foreach in this situation. Like:
foreach($all_input as $key => $value) {
echo 'Input key: ' . $key . ' value: ' . $value;
}
If you left the $key => you will get only the value, you can left it, if you doesn't use it inside the foreach.
If you don't want to use foreach somewhy:
$all_input = Input::post();
$keys = array_keys($all_input);
for ($i = 0; $i < count($keys); $i++) {
if (strpos($all_input[$keys[$i]], 'something') == true) {
// Do your stuff here.
}
}
But I still recommend foreach if possible, it's less overhead and cleaner code.
This won't work because you are dealing with an Object (Input) not an array.
I recommend using a foreach loop vice a for loop. To verify the contents/structure of the Input Object you can also do a dd() to see the Input Object in its entirety.
Basically,
$input = Input::post();
foreach($input as $i) {
echo $i; //this is a property of the Input Object. if you have arrays or other objects store inside of it, you may need to go deeper into the oject either with a foreach loop again or by calling the property directly ($i->property)
};
Firstly, look my example json output.
I have next question. I have some fields in json code like 'counter_87' or 'coutner_88' in countersData part. It is a variable. I need to get access to this variable class field.
Ofc, I can write:
foreach($objCounter->countersData as $data)
{
print $data->counter_87;
}
It is working fine. But...
I have counters ID and I need to get access to fields which are named depending on this ID's.
Full code, which will show what I want:
foreach($objCounter->countersData as $data)
{
$row = "<td width=100px>$data->month $data->year</td>";
foreach($objCounter->counters as $counter)
{
$counterId = $counter->id;
$counterValue = "$data->counter_$counterId";
$row .= "<td>$counterValue</td>";
}
$table .= "<tr>$row</tr>";
}
I need same:
$foo = 'bar';
$bar = 'foobar';
echo $$foo; // foobar will be printed
But with classes.
Thank you.
You could also do the following if you don't want to or can't change change your JSON structure as already mentioned in the comments.
$field_name = 'counter_'.$id;
$field_value = $data->$field_name;
$row .= "<td>$field_value</td>";
// or $row .= '<td>'.$data->$field_name.'</td>';
About rewriting the JSON. Here's code that would convert your JSON to the slightly better structure.
$data = json_decode($data_json);
foreach($data->countersData as $counter_data) {
$counters = array();
foreach($counter_data as $key => $val) {
if(substr($key, 0, 8) == 'counter_') {
$counters[substr($key, 8)] = $val;
unset($counter_data->$key);
}
}
$counter_data->counters = $counters;
}
$data_json_new = json_encode($data);
Using an array instead of fields like 'counter_1', 'counter_2' means having structure like this this:
$countersData[0]->counters[90] = 1;
$countersData[0]->counters[89] = 1;
$countersData[0]->counters[88] = 1;
Instead of
$countersData[0]->counters_90 = 1;
$countersData[0]->counters_89 = 1;
$countersData[0]->counters_88 = 1;
This means having an associative array called counters instead of separate fields like 'counter_90' or something. It makes accessing the data programmatically alot easier.
Note that associative array is very similar to the stdClass. Basically a different datatype serving the same purpose. Using an array to represent your data just makes it easier to deal with integer keys. You can use json_decode($data_json, true) to get the data returned as an associative array.
Thanks in advance for looking.
I am trying to build some HTML using a foreach loop with a few layers of arrays.
Groups of data and groups of titles for that data are stored in sets of arrays.
In turn, those arrays of data are stored in an array ($titlegroups and datagroups).
The aim being to set up a nested loop, where each group of data and titles populate the relevant fields in some html.
Here is a full set of code (structure) of my attempt.
$a=1;
$b=2;
$c=3;
$d=4;
$titlesA=array('string1','string2');
$titlesB=array('string3','string4');
$dataA=array($a,$b);
$dataB=array($c,$d);
$titlegroups=array($titlesA,$titlesB);
$datagroups=array($dataA,$dataB);
$groups=array(array_combine($titlegroups, $datagroups));
$j=0;
foreach($groups as $titlesX => $dataX)
{
$j++;
echo'<div class="something">';
$i=0;
foreach(array_combine($titlesX, $dataX) as $title => $var)
{
$i++;
echo '
<li>'.$title.'</li><input name="'.$j.'x'.$i.'" value="'.$var.'" />
';
}
echo '</div>';
}
Checking it in ideone I get the error:
Warning: array_combine() expects parameter 1 to be array, integer
given in /home/0zw0mb/prog.php on line 26
Line 26 is:
foreach(array_combine($titlesX, $dataX) as $title => $var)
but $titlesX and $dataX should both be arrays?
If anyone can set me straight I'd appreciate it. Thanks.
You can't have arrays as keys, they are converted to strings. You logic required some changes and an additional sentinel variable ($idx), to tell when the code crosses one group to another.
array_merge was necessary due to the key requirements of arrays.
Check the below code:
$a=1;
$b=2;
$c=3;
$d=4;
$titlesA=array('string1','string2');
$titlesB=array('string3','string4');
$dataA=array($a,$b);
$dataB=array($c,$d);
$titlegroups=array_merge($titlesA,$titlesB);
$datagroups=array_merge($dataA,$dataB);
$items=array_combine($titlegroups, $datagroups);
$indexes = array(count($dataA), count($dataB));
$i = 0;
$j = 0;
$idx = $indexes[$j];
echo '<div class="something">';
foreach($items as $title => $var)
{
echo '
<li>'.$title.'</li><input name="'.$j.'x'.($i++).'" value="'.$var.'" />
';
$idx--;
if ($idx == 0) {
/* End of a group */
echo '</div>';
$idx = $indexes[++$j];
/* If there is another group, create new container */
if ($idx != null) {
echo '<div class="something">';
}
}
}
I am using PHP 5.3.6
I have the following code below. Everything works fine except for the last line which attempts to to return a value based on the position in the array as opposed to the associative name. Can anyone explain why this takes place and how I can build the array so that I can reference an item either by the associative name or position number?
Thanks.
<?php
class myObject {
var $Property;
function myObject($property) {
$this->Property = $property;
}
}
$ListOfObjects['form_a'] = new myObject(1);
$ListOfObjects['form_b'] = new myObject(2);
$ListOfObjects['form_c'] = new myObject(3);
$ListOfObjects['form_d'] = new myObject(4);
echo "<pre>";
print_r($ListOfObjects);
echo "</pre>";
echo "<hr />";
foreach ($ListOfObjects as $key => $val) {
echo "<li>" . $ListOfObjects[$key]->Property . "</li>";
}
echo "<hr />";
echo "<li>" . $ListOfObjects['form_a']->Property . "</li>"; // Works ok.
//Edit: ------------------------------------------------------------
//Edit: Everything above is for context only
//Edit: I'm only interested in the line below and why it does not work
//Edit: ------------------------------------------------------------
echo "<li>" . $ListOfObjects[0]->Property . "</li>"; //Does not work.
?>
function value_from_index($a,$k){
return array_slice($a,$k,1);
}
If you just want the first/last element of an array, try end($array) for the last item without destroying it and reset($array) to get the first.
Don't use reset and end if you're looping through an array as Flambino notes, this indeed results in some unexpected behaviour.
For anything inbetween you'll need to use array_slice()
Not the nicest way of doing it, but effektive and readable:
$i = 0;
$last = count($ListOfObjects);
foreach($ListOfObjects as $obj) {
if($i == 0) {
//do something with first object
$obj->property;
else if ($i == ($last-1)) {
//do something with last object
$obj->property;
}
}
PHP arrays aren't like arrays you know from most other programming languages, they are more like ordered hash tables / ordered dictionaries - they allow for access by named index and retain order when new items are added. If you want to allow access with numeric indices to such an array you have to define it that way or use one of roundabout ways given in other answers.
In your case you can use a single line of code to allow access by index:
$ListOfObjects += array_values($ListOfObjects);
This will extend your array with the same one but with numeric indices. As objects are always passed by reference, you can access the same object by writing $ListOfObjects['form_b'] and $ListOfObjects[1].
i am tring to put a loop to echo a number inside an echo ;
and i tried as bellow :
$array = array();
$result = mysql_query("SHOW TABLES FROM `st_db_1`");
while($row = mysql_fetch_row($result) ){
$result_tb = mysql_query("SELECT id FROM $row[0] LIMIT 1");
$row_tb=mysql_fetch_array($result_tb);
$array[] = $row[0];
$array2[] = $row_tb[0];
//checking for availbility of result_tb
/* if (!$result_tb) {
echo "DB Error, could not list tablesn";
echo 'MySQL Error: ' . mysql_error();
exit;
} */
}
natsort($array);
natsort($array2);
foreach ($array as $item[0] ) {
echo "<a href=show_cls_db.php?id= foreach ($array2 as $item2[0]){echo \"$item2[0]\"}>{$item[0]}<br/><a/>" ;
}
but php is not considering foreach loop inside that echo ;
please suggest me something
As mentioned by others, you cannot do loops inside a string. What you are trying to do can be achieved like this:
foreach ($array as $element) {
echo "<a href='show_cls_db.php?id=" . implode('', $array2) . "'>{$element}</a><br/>";
}
implode(...) concatenates all values of the array, with a separator, which can be an empty string too.
Notes:
I think you want <br /> outside of <a>...</a>
I don't see why you would want to used $item[0] as a temporary storage for traverser array elements (hence renamed to $element)
Just use implode instead of trying to loop the array,
foreach ($array as $item)
{
echo implode("",$array2);
}
other wise if you need to do other logic for each variable then you can do something like so:
foreach ($array as $item)
{
echo '<a href="show_details.php?';
foreach($something as $something_else)
{
echo $something_else;
}
echo '">Value</a>';
}
we would have to see the contents of the variables to understand what your trying to do.
As a wild guess I would think your array look's like:
array(
id => value
)
And as you was trying to access [0] within the value produced by the initial foreach, you might be trying to get the key and value separate, try something like this:
foreach($array as $id => $value)
{
echo $id; //This should be the index
echo $value; //This should be the value
}
foreach ($array as $item ) {
echo "<a href=\"show_cls_db.php?id=";
foreach ($array2 as $item2) { echo $item2[0]; }
echo "\">{$item[0]}<br/><a/>" ;
}
No offense but this code is... rough. Post it on codereview.stackexchange.com for some help re-factoring it. A quick tip for now would be to use PDO, and at the least, escape your inputs.
Anyway, as the answers have pointed out, you have simply echoed out a string with the "foreach" code inside it. Take it out of the string. I would probably use implode as RobertPitt suggested. Consider sorting and selecting your data from your database more efficiently by having mysql do the sorting. Don't use as $item[0] as that makes absolutely no sense at all. Name your variables clearly. Additionally, your href tag is malformed - you may not see the correct results even when you pull the foreach loop out of the echo, as your browser may render it all away. Make sure to put those quotes where they should be.