Can I access item in array without additional loop? - php

I have a data structure like this:
array (size=4)
'active' =>
array (size=1)
170 =>
object(stdClass)[2847]
public 'item' => string '170' (length=3)
'complete' =>
array (size=1)
8 =>
object(stdClass)[2849]
public 'item' => string '8' (length=1)
'dropped' =>
array (size=1)
10 =>
object(stdClass)[2850]
public 'item' => string '10' (length=2)
'total' =>
array (size=1)
188 =>
object(stdClass)[2851]
public 'item' => string '188' (length=3)
I am using this loop to iterate the datastruct and access the value in item.
foreach($ecounts as $key => $value){
if($key == 'total'){
foreach($value as $i){
$te = $i->item;
}
}elseif($key == 'active'){
foreach($value as $i){
$ae = $i->item;
}
}elseif($key == 'dropped'){
foreach($value as $i){
$de = $i->item;
}
}elseif($key == 'complete'){
foreach($value as $i){
$ce = $i->item;
}
}
}
I am sure there is a smarter way to access the item value. The additional foreach() loop inside each if statement seems overkill, but I could not find a better way to accomplish.
Thank you for insights.

Maybe you can decide the name of the variable before you start the additional loops.
Like
foreach($ecounts as $key => $value){
$var = ($key == 'total' ? 'te' : $key == 'active' : 'ae' ? $key == 'dropped' : 'de' ? $key == 'complete' : 'ce');
foreach($value as $i){
${$var} = $i->item;
}
}
Read http://php.net/manual/en/language.variables.variable.php for more documentation.

Related

Find value on array in PHP

I have an array on variable $menu:
array (size=3)
0 =>
array (size=2)
'principal' => string 'regulacao' (length=9)
'submenu' => string 'agenda' (length=6)
1 =>
array (size=2)
'principal' => string 'regulacao' (length=9)
'submenu' => string 'marcacao' (length=8)
2 =>
array (size=2)
'principal' => string 'gestao' (length=6)
'submenu' => string 'usuarios' (length=8)
I need to know if an word exists, ex:
if (array_value_exists('regulacao')) //return true
if (array_value_exists('marcacao')) //return true
if (array_value_exists('usuarios')) //return true
if (array_value_exists('gestao')) //return true
I trying using if (array_search('regulacao', $menu)) but it's not works
Any idea?
I believe this code solves your problem:
function recursive_array_search($needle, $haystack) {
foreach($haystack as $key=>$value) {
$current_key=$key;
if($needle === $value OR (is_array($value) && recursive_array_search($needle,$value) !== false)) {
return true;
}
}
return false;
}
Array_search not works with nested array.
To do this search you need to iterate your $menu array and call array_search on each sub array. Like this:
$word = "regulacao";
foreach($menu as $arr) {
$arrKey = array_search($word, $arr);
if($arrKey){
print "Found {$word} in key {$arrKey}";
// break; <-- uncomment this line for search only one occurrence
}
}

Iterating over multidimensional array in PHP

Over the past few days, I've been thinking about how to deal with iterating over keys in a multidimensional array, and I just cannot figure it out. The problem is, I don't know how deep the array might be - I want my code to be able to handle arrays of any depth.
The array itself comes from Advanced Custom Fields, but that's not too important. I need to iterate over the array, run a function on every array key which starts with field_ (to convert it from field_* to its proper name like post_title or something), and reconstruct the array with the same structure and values (although the order is not important). The array looks like this:
array (size=12)
'field_5b23d04fef8a6' => string '' (length=0)
'field_5b23d04fefa99' => string '' (length=0)
'field_5b23d04fefe85' => string '' (length=0)
'field_5b23d04ff0077' => string '' (length=0)
'field_5b23d04ff026c' => string '' (length=0)
'field_5b23d0bdb3c1a' => string 'Version 1' (length=9)
'field_5b23d0f48538b' => string '' (length=0)
'field_5b23d0f485772' => string '' (length=0)
'field_5b23d0d52be2d' => string '' (length=0)
'field_5b5ed10a6a7bc' => string '' (length=0)
'field_5b5ed10a6bcf5' =>
array (size=1)
0 =>
array (size=1)
'field_5b5ed10acd264' =>
array (size=1)
0 =>
array (size=6)
'field_5b5ed10b0c9ca' => string '0' (length=1)
'field_5b5ed10b0cce2' => string 'TEST1234' (length=8)
'field_5b5ed10b0d0fd' => string 'Download title' (length=14)
'field_5b5ed10b0d4e2' => string 'EN' (length=2)
'field_5b5ed10b0d72e' => string 'A00' (length=3)
'field_5b5ed10b0df27' => string '887' (length=3)
'field_5b23d088500a4' => string '' (length=0)
What would be the best way to handle this? I've looked at recursive functions and ResursiveArrayIterator already, but none of the examples I found were close enough to let me figure out what I need.
You can recursively call the same function if it finds a nested array like this:
$input = array(
'field_5b23d04fef8a6' => '',
'field_5b23d04fefa99' => '',
'field_5b23d04fefe85' => '',
'field_5b23d04ff0077' => '',
'field_5b23d04ff026c' => '',
'field_5b23d0bdb3c1a' => 'Version 1',
'field_5b23d0f48538b' => '',
'field_5b23d0f485772' => '',
'field_5b23d0d52be2d' => '',
'field_5b5ed10a6a7bc' => '',
'field_5b5ed10a6bcf5' => array(
array(
'field_5b5ed10acd264' => array(
array(
'field_5b5ed10b0c9ca' => '0',
'field_5b5ed10b0cce2' => 'TEST1234',
'field_5b5ed10b0d0fd' => 'Download title',
'field_5b5ed10b0d4e2' => 'EN',
'field_5b5ed10b0d72e' => 'A00',
'field_5b5ed10b0df27' => '887',
),
),
),
),
'field_5b23d088500a4' => '',
);
// recursively re-key array
function dostuff($input){
// always refer to self, even if you rename the function
$thisfunction = __function__;
$output = array();
foreach($input as $key => $value){
// change key
$newkey = (is_string($key) ? preg_replace('/^field_/', 'post_title_', $key) : $key);
// iterate on arrays
if(is_array($value)){
$value = $thisfunction($value);
}
$output[$newkey] = $value;
}
return $output;
}
var_dump(dostuff($input));
So I was looking at this and to my knowledge there is no wrapper function for recursion with callbacks, so here it is:
// general function for recursively doing something
// $input -> array() / the array you wan to process
// $valuefunction -> callable | null / function to run on all values *
// $keyfunction -> callable | null / function to run on all keys *
// * at least one has to defined or there is nothing to do
// callable has two inputs
// $input -> current branch
// $depth -> (int) how deep in the structure are we
// i.e: recursion($some_array, function($branch, $depth){something..}, 'trim');
function recursion($input, $valuefunction = false, $keyfunction = false){
if(!is_array($input)){
trigger_error('Input is '.gettype($input).'. Array expected', E_USER_ERROR);
return null;
}
if(!is_callable($valuefunction)){$valuefunction = false;}
if(!is_callable($keyfunction)){$keyfunction = false;}
if(!$valuefunction && !$keyfunction){
trigger_error('Input is unchanged!', E_USER_WARNING);
return $input;
}
// use recursion internally, so I can pass stuff by reference
// and do the above checks only once.
$recurse = function(&$branch, $depth = 0) use (&$recurse, &$valuefunction, &$keyfunction){
$output = array();
foreach($branch as $key => $value){
$key = $keyfunction ? $keyfunction($key, $depth) : $key;
$output[$key] = (is_array($value) ?
$recurse($value, $depth + 1) :
($valuefunction ?
$valuefunction($value, $depth) :
$value
)
);
}
return $output;
};
return $recurse($input);
}
$valuefunction = function($value, $depth){
return is_string($value) ? $depth.'_'.$value : $value;
};
function keyfunction($key){
return is_string($key) ? preg_replace('/^field_/', 'post_title_', $key) : $key;
}
var_dump(recursion($input, $valuefunction, 'keyfunction'));
Or for your example:
var_dump(recursion($input, 0, function($key){
return is_string($key) ? preg_replace('/^field_/', 'post_title_', $key) : $key;
}));
You could do something like this:
$arr = [
'a',
'b',
'c',
[
'd',
'e',
'f',
[
'g',
'h',
'i',
],
],
];
class MyIterator
{
public function iterate( $array )
{
foreach ( $array as $a ) {
if ( is_array( $a ) ) {
$this->iterate($a);
} else {
echo $a;
}
}
}
}
$iterator = new MyIterator();
$iterator->iterate($arr);
It prints this:
abcdefghi
You can iterate over array recursively like this
function recursiveWalk($array, callable $x)
{
$result = [];
foreach ($array as $key => $value) {
if (is_array($value)) {
$result[$key] = recursiveWalk($value, $x);
} else {
$result[$key] = $x($value);
}
}
return $result;
}
Here example:
$array = [
"aaa" => 1,
"sub1" => [
"xxx" => 2,
"sub2" => [
"yyy" => 3,
"ttt" => 4
]
]
];
print_r(recursiveWalk($array, function ($x) {
return $x + 1;
}));
Array
(
[aaa] => 2
[sub1] => Array
(
[xxx] => 3
[sub2] => Array
(
[yyy] => 4
[ttt] => 5
)
)
)

real_escape_string on multidimensional array

I'm trying to escape values from a multidimensional array for my database class. The code I have currently:
// Function to escape array values
private function esc_sql_arr(array $to_esc) {
$clean_arr = array();
foreach($to_esc as $k => $v) {
if(is_array($to_esc[$k])) {
foreach($to_esc[$k] as $key => $val) {
$k = $this->_mysqli->real_escape_string($k);
$key = $this->_mysqli->real_escape_string($key);
$val = $this->_mysqli->real_escape_string($val);
$clean_arr[$k][$key] = $val;
}
} else {
$k = $this->_mysqli->real_escape_string($k);
$v = $this->_mysqli->real_escape_string($v);
$clean_arr[$k] = $v;
}
}
return $clean_arr;
}
I'm assuming the following input example (it should be 'where', I purposely changed it to test the above method):
$args = array(
"table" => "t'1",
"data" => array(
"c'sf4;(" => 'xdfbxdrf',
'c2' => "'t'est'",
'cs' => 'hey'
),
"whe're" => array(
'test' => 'test1'
)
);
var_dump:
array (size=3)
'table' => string 't\'1' (length=4)
'data' =>
array (size=3)
'c\'sf4;(' => string 'xdfbxdrf' (length=8)
'c2' => string '\'t\'est\'' (length=10)
'cs' => string 'hey' (length=3)
'whe\'re' =>
array (size=1)
'test' => string 'test1' (length=5)
The code works without any issue. However, is this the right way to escape a multidimensional array?
I believe I might not have to use this method since I use prepared statements. Any feedback on using this is welcome.

PHP weird situation while assigning vars into an array

I'm building a SQL query. Weird thing is that some vars are being assigned correctly or wrongly depending on their position inside the array. Here's the code:
$v = [...] // $v is an array containing a serialized form
$id = 20;
foreach ($v as $key => $value) {
$key = explode('c_', $key);
$key = $key[1]; // this is the id of the fieldset that is being processed
// array containing the data to be inserted with the query
$data = array(
'a' => (empty($v['a_'.$key]) ? NULL : $v['a_'.$key]),
'b' => (empty($v['b_'.$key]) ? NULL : $v['b_'.$key]),
'c' => $value,
'd' => (empty($v['d_'.$key]) ? NULL : $v['d_'.$key]),
'e' => (empty($v['e_'.$key]) ? NULL : $v['e_'.$key]),
'id' => $id
);
// array containing the format of the data of the array $data
$format = array(
(empty($v['a'.$key]) ? NULL : '%s'),
(empty($v['b_'.$key]) ? NULL : '%s'),
'%s',
(empty($v['d_'.$key]) ? NULL : '%s'),
(empty($v['e_'.$key]) ? NULL : '%s'),
'%d'
);
[...] // then i send the query to the db
}
What happens here is:
if all the data that is going to be assigned returns false from the empty() check (and so they are NOT NULL), everything works fine;
if I omit the data before the 'c' => $value, everything works fine. Example:
$data = array(
'c' => $value,
'd' => (empty($v['d_'.$key]) ? NULL : $v['d_'.$key]),
'e' => (empty($v['e_'.$key]) ? NULL : $v['e_'.$key]),
'id' => $id
);
if I assign 'c' => $value and 'id' => $id BEFORE all the other variables, everything works fine. Example:
$data = array(
'c' => $value,
'id' => $id,
'a' => (empty($v['a_'.$key]) ? NULL : $v['a_'.$key]),
'b' => (empty($v['b_'.$key]) ? NULL : $v['b_'.$key]),
'd' => (empty($v['d_'.$key]) ? NULL : $v['d_'.$key]),
'e' => (empty($v['e_'.$key]) ? NULL : $v['e_'.$key])
);
in all the other case, using the code as displayed at the beginning of this question, c and id will be set as ''.
Of course I tried to echo both $value and $id: both of them are correctly assigned. This is something really weird!
UPDATE
Here's an example of the var_dump($v), as per Kim's request:
array (size=[...])
[...]
'a_0' => string 'test' (length=4)
'b_0' => string 'test' (length=4)
'c_0' => string 'test' (length=4)
'd_0' => string 'test' (length=4)
'e_0' => string 'test' (length=4)
'a_1' => string 'test' (length=4)
'b_1' => string 'test' (length=4)
'c_1' => string 'test' (length=4)
'd_1' => string 'test' (length=4)
'e_1' => string 'test' (length=4)
[...]
Moreover, I also tried to assigning the value directly like this 'c' => 'This is a test' and it is always returning '' into the final array. I think this is a proof that the problem is inside the code posted, as per Jason's doubt.
first of all, that is bad practice to reassign var inside the loop and during the loop
so your code:
foreach ($v as $key => $value) {
$key = explode('c_', $key);
$key = $key[1]; // this is the id of the fieldset that is being processed
must replaced with:
foreach ($v as $index => $value) {
$keyArr = explode('_', $index);
$key = $keyArr[1]; // this is the id of the fieldset that is being processed
That would make your code more readable with no confusion.
By the way, are you sure that you need really foreach ($v[]?
For me it seems better to be changed to:
$executedKey=null;
foreach ($v as $index => $value) {
$keyArr = explode('_', $index);
$key = $keyArr[1];
if ($key == $executedKey) {
continue;
} else {
$executedKey = $key;
};
So with your $v sample it will loop just 2 times, not 10.

Cannot add data to PHP array in CodeIgniter

I have a PHP array, actually a MySQL row constructed with CodeIgniter's Active Record.
So I have an array which var_dumps like this :
array (size=10)
0 =>
array (size=4)
'user_id' => string '2' (length=1)
'puzzle_id' => string '17' (length=2)
'birth' => string '2014-01-26 16:08:25' (length=19)
1 =>
array (size=4)
'user_id' => string '2' (length=1)
'puzzle_id' => string '16' (length=2)
'birth' => string '2014-01-26 02:07:05' (length=19)
2 => .....
this is constructed like this :
$this->db->order_by("birth" , "desc");
$rows = $this->db->get("my_table" , $limit)->result_array();
foreach($rows as $row)
{
$row['testindex'] = "testvalue";
}
return $rows;
so why does my array NOT have the "testindex" indices ?
Thanks for any help !
Because that's not how PHP and foreach() in particular works.
$row in your code is a copy of the corresponding element in $rows, not the actual element. Modifying a copy doesn't modify the original.
You'd want to do this:
for ($i = 0, $c = count($rows); $i < $c; $i++)
{
$rows[$i]['testindex'] = 'testvalue';
}
Try this (PHP 5+):
foreach($rows as &$row)
{
$row['testindex'] = "testvalue";
}
I think I can do this with foreach too.
Like this :
foreach($rows as $key => $value)
{
$rows[$key]['testindex'] = "testvalue";
}

Categories