I've the following callback function in my codeiginter form validation rule:
function validate_milestone($mileStones, $csrf) {
if(is_array($mileStones)) {
foreach ($mileStones as $value) {
}
}
}
This is the result of var_dump
array (size=3)
0 =>
array (size=3)
'Name' => string 'a' (length=1)
'Amount' => string '50.00' (length=5)
'Type' => string 'AMOUNT' (length=6)
1 =>
array (size=3)
'Name' => string 'b' (length=1)
'Amount' => string '20.00' (length=5)
'Type' => string 'AMOUNT' (length=6)
2 =>
array (size=3)
'Name' => string 'c' (length=1)
'Amount' => string '30.00' (length=5)
'Type' => string 'AMOUNT' (length=6)
If I remove if(is_array()) condition from the above code, then PHP returns a warning of "Invalid argument supplied for foreach". When I used var_dump($mileStones) it gave array type of variable. Then what is the role of this PHP condition in removing the warning?
When you put the is_array() condition, the code block is simply skipped when $mileStones is not an array (which happens in some cases caused by some other portion of your code that you haven't shared here) and as a result the foreach statement is never executed and gets skipped (thus no warning):
if(is_array($mileStones)) {
echo 'This entire block is skipped when $mileStones is not an array.';
foreach ($mileStones as $value) {
}
}
Now when you remove the is_array() check, the foreach loop is executed no matter what and as $mileStones is not an array or is an empty array in some cases, the built-in warning is thrown. Try this to confirm:
if (is_array($mileStones)) {
foreach ($mileStones as $value) {
}
} else {
echo 'Damn, $mileStones is indeed not an array in some weird cases that I need to check now.';
}
Note: In my opinion you should not use the is_array() check as it simply ignores the situation and all the built-in error handling gets skipped - making debugging difficult.
Related
While using something like:
$db = new PDO(connection_details)
$query = "SELECT * FROM vservers LIMIT 5";
$result = $db->query($query);
And then try to get records with while f.e.
while ($row = $result->fetchAll(PDO::FETCH_OBJ)) {
var_dump($row);
}
it returns an array with StdObjects like this:
array (size=5)
0 =>
object(stdClass)[3]
public 'vserverid' => string '898' (length=3)
public 'templatename' => string 'Debian' (length=14)
public 'template' => string 'debian-7.0-x86' (length=14)
1 =>
object(stdClass)[4]
public 'vserverid' => string '792' (length=3)
public 'templatename' => string 'Ubuntu' (length=33)
public 'template' => string 'ubuntu-15.04' (length=27)
And with foreach it returns StdObjects
foreach ($result->fetchAll(PDO::FETCH_OBJ) as $key) {
var_dump($key);
}
object(stdClass)[3]
public 'vserverid' => string '898' (length=3)
public 'templatename' => string 'Debian' (length=6)
public 'template' => string 'debian' (length=6)
object(stdClass)[4]
public 'vserverid' => string '792' (length=3)
public 'templatename' => string 'Ubuntu' (length=6)
public 'template' => string 'ubuntu' (length=6)
Can someone please explain this behaviour? Normally, I would like to return Objects like with foreach, but is it a good practice ?
fetchAll() returns all the results as an array, where each element is an object that represents a row from the table.
In your while code, the first iteration sets $row to the entire result set, and dumps it as a single array. There's only one iteration because the next call to fetchAll() returns an empty array, because there's nothing left to fetch.
In your foreach code, fetchAll() returns the array to foreach, which then iterates over it one element at a time, setting $key to each object. Then you dump that one object in your body.
Normally when you're using while you use fetch(), not fetchAll(). This code will be equivalent to the foreach:
while ($key = $result->fetch(PDO::FETCH_OBJ)) {
var_dump($key);
}
I have two arrays like:
array (size=4)
0 => string '5' (length=1)
1 => string '4' (length=1)
2 => string '2' (length=1)
3 => string '2' (length=1)
3 => string '8' (length=1)
and one array more that I load from an XML file:
object(SimpleXMLElement)[1]
public 'book' =>
array (size=101)
0 =>
object(SimpleXMLElement)[2]
public 'id' => string '1' (length=1)
public 'title' => string 'p' (length=1)
1 =>
object(SimpleXMLElement)[3]
public 'id' => string '2' (length=1)
public 'title' => string 'pp' (length=2)
2 =>
object(SimpleXMLElement)[4]
public 'id' => string '3' (length=1)
public 'title' => string 'pen' (length=3)
3 =>
object(SimpleXMLElement)[5]
public 'id' => string '4' (length=1)
public 'title' => string 'lapton' (length=6)
......
......
101 =>
object(SimpleXMLElement)[103]
public 'id' => string '101' (length=1)
public 'title' => string 'title' (length=5)
I want to compare each value of key id of second array with key of first array for each value. When it's the same, I want to update value of key title of second array.
Assuming your first array is $idArray and your second is $xmlArray, you could use something like this.
$result = array_map(function($xmlElement) use ($idArray) {
if (in_array($xmlElement->id, $idArray)) {
$xmlElement->title = 'updated value';
}
return $xmlElement;
}, $xmlArray);
Assumptions
the first array is called $array1
the second array is called $fromXML
the second array is not actually an array, it's a SimpleXMLElement with the following structure (psuedocode / JSONish syntax)
{
'book' => {
0 => SimpleXMLElement {
'id' => 1,
'title' => 'p'
}
}
}
I assume you can access the second array of elements with $fromXML['book']
I assume you can access an attribute of the first element with $fromXML['book'][0]['id']
I assume that you can set the text of the title of the first element with $fromXML['book'][0]['title'][0] = 'new title'
based on How can I set text value of SimpleXmlElement without using its parent? and PHP SimpleXML, how to set attributes? and PHP foreach change original array values
Solution
foreach($fromXML['book'] as $key => $element) {
if(array_key_exists($element['id'], $array1)) {
$fromXML['book'][$key]['title'][0] = $array1[$element->id];
}
}
Caveat and troubleshooting
I didn't test this, just going off of the documentation. If I've misinterpreted the structure of your SimpleXMLElement array, try experimenting with var_dump($fromXML['some']['key']) until you find the right way to access the array/element
Note: Apparently, array_key_exists() performs better than in_array() on large arrays
Try this for now
foreach($array1 as $arr1 => $val1){
foreach($array2 as $arr2 =>$val2){
if($arr1==$arr2){
$val2['title']='update value';
}
}
}
I am trying to parse out certain things within the JSON code, but the problem is that the two groups of arrays that have the information in it I need have random names, here is from the var_dump:
array (size=2)
'results' =>
array (size=1)
0 => string 'Phone.5d5b6fef-a2e0-4b08-cfe3-bc7128b776c3.Durable' (length=50)
'dictionary' =>
array (size=3)
'Person.51f28c76-2993-42d3-8d65-4ea0a66c5e16.Ephemeral' =>
array (size=8)
'id' =>
array (size=5)
...
'type' => null
'names' =>
array (size=1)
...
'age_range' => null
'locations' => null
'phones' =>
array (size=1)
...
'best_name' => string 'John Smith' (length=15)
'best_location' => null
'Location.28dc9041-a0ee-4613-a3b0-65839aa461da.Durable' =>
array (size=30)
'id' =>
array (size=5)
...
'type' => string 'ZipPlus4' (length=8)
'valid_for' => null
'legal_entities_at' => null
'city' => string 'City' (length=8)
'postal_code' => string '12345' (length=5)
'zip4' => string '4812' (length=4)
'state_code' => string 'MO' (length=2)
'country_code' => string 'US' (length=2)
'address' => string 'Main St, City, MO 12345-4812' (length=33)
'house' => null
No I am trying to get best_name from under the part that starts with Person and address under Location. But when I do:
$string = file_get_contents($url);
$json=json_decode($string,true);
var_dump($json);
echo $json['dictionary']['Person']['best_name'];
I get Undefined index: Person error, because the actual object name for Person is:
Person.51f28c76-2993-42d3-8d65-4ea0a66c5e16.Ephemeral which is different every time I do a search. Is there a way to do this without putting the random generated line in?
Hopefully this makes sense, thanks for the help in advance!
If the Person key always starts with the string "Person", than simply do a foreach and check the key which contains this string.
Like:
foreach ($json['dictionary'] as $key => $value) {
if (preg_match('/^Person/', $key)) {
echo $json['dictionary'][$key]['best_name'];
}
}
Of course this get complicated, if you have multiple keys which start with "Person".
You can do the same with "Location" or any other string you need.
How about something like this ... loop through $json['dictionary']'s index keys to find something that starts with "Person".
$foundIt = false;
foreach (array_keys($json['dictionary']) as $key) {
if (substr($key,0,6) == 'Person') {
$foundIt = $key;
break;
}
}
if ($foundIt) { echo $json['dictionary'][$foundIt]['best_name']; }
I am using PHP 5.3.5, and I am stuck with an error. I have an array
$input = array(
0=>array(
'a'=>'one0',
'b'=>'two0',
'c'=>'three0',
'd'=>'four0',
'e'=>'five0'
),
1=>array(
'a'=>'one1',
'b'=>'two1',
'c'=>'three1',
'd'=>'four1',
'e'=>'five1'
)
);
I use array_splice to remove the initial two values from each array
by using &(value by reference) in foreach
foreach ($input as $bk => &$bv) {
$op[]=array_splice($bv,0,2);
}
Now when I see the $input then it adds a & just before the second array.
var_dump($input); shows this
array
0 =>
array
'c' => string 'three0' (length=6)
'd' => string 'four0' (length=5)
'e' => string 'five0' (length=5)
1 => & <====================================From where this `&` comes?
array
'c' => string 'three1' (length=6)
'd' => string 'four1' (length=5)
'e' => string 'five1' (length=5)
Where does & come from and how does it produce such array? Is it valid?
If I remove & in the foreach, it does not gives me desired array. Am I doing something wrong?
It's pretty counter-intuitive but it isn't actually a bug. When you use references in a loop, you're advised to unset the reference right after the loop:
foreach ($input as $bk => &$bv) {
$op[]=array_splice($bv,0,2);
}
unset($bv);
I would like a hint or much better a solution for this:
I do a regular expresion match to an url for example '/product/100/'
preg_match('/^\/(?<name>\w+)\/(?<digit>\d+)\/$/', '/product/100/', $matches);
As result of this I get the following array on $matches:
array
0 => string '/product/100/' (length=13)
'name' => string 'product' (length=7)
1 => string 'product' (length=7)
'digit' => string '100' (length=3)
2 => string '100' (length=3)
How can I use reduce this array to get this?
array
'name' => string 'product' (length=7)
'digit' => string '100' (length=3)
After I get the matching expresions, I call a function and give the 'named' keys as arguments to the function.
call_user_func_array($view, $just_named_args_no_integer_keys);
I hope anyone can give me any hint.
Best Regards
Just run the keys you get from array_keys() through array_filter():
/* This is for PHP 5.3, I'm sure you'll figure out how to the same thing pre 5.3 :) */
$allKeys = array_keys($view);
$namedKeys = array_filter($allKeys, function($value) { return !is_numeric($value); });
Update
Did not read the question properly. In this case, actually just foreach over the data:
$namedValues = array();
foreach ($view as $key => $value)
if (!is_numeric($key))
$namedValues[$key] = $value;