PHP Dynamic array key [duplicate] - php

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Dynamic array keys
I have an array $Values
which is set up like this
$Values
1
2
3
a
b
c
4
which is nested.
and I have a key like this: $key = "a"]["b"]["c";
Can I now do: Values[$key], ti get the value in c ?
#Edit
Simply said: I want to get the value from array $Values["a"]["b"]["c"] By doing $Values[$key]. What should my key be then?

No, but you can extract the result:
$Values = array( '1' => 'ONE',
'2' => 'TWO',
'3' => 'THREE',
'a' => array( 'b' => array( 'c' => 'alphabet') ),
'4' => 'FOUR'
);
$key = '"a"]["b"]["c"';
$nestedKey = explode('][',$key);
$searchArray = $Values;
foreach($nestedKey as $nestedKeyValue) {
$searchArray = $searchArray[trim($nestedKeyValue,'"')];
}
var_dump($searchArray);
Will only work if $key is valid.
Now how do you get in a situation with a key like this anyway? Perhaps if you explained the real problem, we could give you a real answer rather than a hack.

No, you only can get individual keys from variables. Depending on what you really want to do you could use references to your array elements.

Nah you can't. This is invalid syntax.
Hover you can do:
$key = 'a,b,c';
// or:
$key = serialize( array( 'a','b', 'c'));
// or many other things
And than implement your array-like class which will implement ArrayAccess or ArrayObject (let's way you'll stick with $key = 'a,b,c';):
class MyArray extends ArrayAccess {
protected $data = array();
protected &_qetViaKey( $key, &$exists, $createOnNonExisting = false){
// Parse keys
$keys = array();
if( strpos( $key, ',') === false){
$keys[] = $key;
} else {
$keys = explode( ',', $key);
}
// Prepare variables
static $null = null;
$null = null;
$exists = true;
// Browse them
$progress = &$this->data;
foreach( $keys as $key){
if( is_array( $progress)){
if( isset( $progress[ $key])){
$progress = $progress[ $key];
} else {
if( $createOnNonExisting){
$progress[ $key] = array();
$progress = $progress[ $key];
} else {
$exists = false;
break;
}
}
} else {
throw new Exception( '$item[a,b] was already set to scalar');
}
}
if( $exists){
return $progress;
}
return $null;
}
public offsetExists( $key){
$exists = false;
$this->_getViaKey( $key, $exists, false);
return $exists;
}
// See that we aren't using reference anymore in return
public offsetGet( $key){
$exists = false;
$value = $this->_getViaKey( $key, $exists, false);
if( !$exists){
trigger_error( ... NOTICE ...);
}
return $value;
}
public offsetSet ( $key, $val){
$exists = false;
$value = $this->_getViaKey( $key, $exists, true);
$value = $val;
}
}
// And use it as:
$array = MyArray();
$array['a']['b']['c'] = 3;
$array['a,b,c'] = 3;
Or implement function:
public function &getArrayAtKey( $array, $key){
// Similar to _qetViaKey
// Implement your own non existing key handling
}

Related

Check is a string element of CodeIgniter query

Hello I wanna check if is string element of codeIgniter query, so I wanna compere to arrays.
I use this soulution but i get false in both case.
$data = array(
'Firstname' => $ime ,
'Lastname' => $prezime,
'Nick' => $username,
'EmailAddress' => $email,
'Uid' => $uid,
);
$rs = $this->db->query("Select Nick FROM cms_cart_customers");
$array = $rs->result_array();
if(!in_array($data['Nick'],$array))
{
$this->db->insert('cms_cart_customers', $data);
}
The result_array() function returns you a multi-dimensional array, even with a single column. You need to flatten the array in order to search the array linearly, try something like this:
$array = $rs->result_array();
$flattened = array();
foreach($array as $a) {
$flattened[] = $a['Nick'];
}
if(!in_array($data['Nick'],$flattened)) {
$this->db->insert('cms_cart_customers', $data);
}
Codeigniter query will return result in associative array and in_array() function will not going to do the trick.
Here is one way you can do this custom is_in_array function source
//Helper function
function is_in_array($array, $key, $key_value){
$within_array = false;
foreach( $array as $k=>$v ){
if( is_array($v) ){
$within_array = is_in_array($v, $key, $key_value);
if( $within_array == true ){
break;
}
} else {
if( $v == $key_value && $k == $key ){
$within_array = true;
break;
}
}
}
return $within_array;
}
$array = $rs->result_array();
if(!is_in_array($array, 'Nick', $data['Nick']))
{
$this->db->insert('cms_cart_customers', $data);
}
Other Method
If you are trying to avoid duplicate entry, you should use a Select query first to check that the 'Nick' = $username is already present in table, if not then Issue an insert
Example
$rs = $this->db->get_where('cms_cart_customers', array('Nick' => $username));
//After that just check the row count it should return 0
if($rs->num_rows() == 0) {
$this->db->insert('cms_cart_customers', $data);
}

php multi array create dynamically

I have q question: what is the easiest way to create multi-dimensional array in php dynamically?
Here a static version:
$tab['k1']['k2']['k3'] = 'value';
I would like to avoid eval()
I'm not successful with variable variable ($$)
so I'm trying to develop a function fun with such interface:
$tab = fun( $tab, array( 'k1', 'k2', 'k3' ), 'value' );
Do you have a solution? What is the simplest way?
regards,
Annie
There are a number of ways to achieve this, but here is one which uses PHP's ability to have N arguments passed to a function. This gives you the flexibility of creating an array with a depth of 3, or 2, or 7 or whatever.
// pass $value as first param -- params 2 - N define the multi array
function MakeMultiArray()
{
$args = func_get_args();
$output = array();
if (count($args) == 1)
$output[] = $args[0]; // just the value
else if (count($args) > 1)
{
$output = $args[0];
// loop the args from the end to the front to make the array
for ($i = count($args)-1; $i >= 1; $i--)
{
$output = array($args[$i] => $output);
}
}
return $output;
}
Here's how it would work:
$array = MakeMultiArray('value', 'k1', 'k2', 'k3');
And will produce this:
Array
(
[k1] => Array
(
[k2] => Array
(
[k3] => value
)
)
)
Following function will work for any number of keys.
function fun($keys, $value) {
// If not keys array found then return false
if (empty($keys)) return false;
// If only one key then
if (count($keys) == 1) {
$result[$keys[0]] = $value;
return $result;
}
// prepare initial array with first key
$result[array_shift($keys)] = '';
// now $keys = ['key2', 'key3']
// get last key of array
$last_key = end($keys);
foreach($keys as $key) {
$val = $key == $last_key ? $value : '';
array_walk_recursive($result, function(&$item, $k) use ($key, $val) {
$item[$key] = $val;
});
}
return $result;
}
This should work if $tab always has 3 indices:
function func(&$name, $indices, $value)
{
$name[$indices[0]][$indices[1]][$indices[2]] = $value;
};
func($tab, array( 'k1', 'k2', 'k3' ), 'value' );

How to dynamically create nested array in php

I want create a nested array from a config file dynamically.
My config file structure is like this:
parameter1 value1;
parameter2 value2;
parameter3 value3;
block1{
parameter1-1 value1-1;
parameter1-2 value1-2;
block1-1{
parameter1-1-1 value1-1-1;
parameter1-1-2 value1-1-2;
block1-1-1{
parameter1-1-1-1 value1-1-1-1;
parameter1-1-1-2 value1-1-1-2;
}
block1-1-2{
parameter1-1-2-1 value1-1-2-1;
parameter1-1-2-2 value1-1-2-2;
}
}
block1-2{
parameter1-2-1 value1-2-1;
parameter1-2-2 value1-2-2;
block1-2-1{
parameter1-2-1-1 value1-2-1-1;
parameter1-2-1-2 value1-2-1-2;
}
block1-2-2{
parameter1-2-2-1 value1-2-2-1;
parameter1-2-2-2 value1-2-2-2;
}
}
}
block2{
parameter2-1 value2-1;
parameter2-2 value2-2;
block2-1{
parameter2-1-1 value2-1-1;
parameter2-1-2 value2-1-2;
block2-1-1{
parameter2-1-1-1 value2-1-1-1;
parameter2-1-1-2 value2-1-1-2;
}
block2-1-2{
parameter2-1-2-1 value2-1-2-1;
parameter2-1-2-2 value2-1-2-2;
}
}
block2-2{
parameter2-2-1 value2-2-1;
parameter2-2-2 value2-2-2;
block2-2-1{
parameter2-2-1-1 value2-2-1-1;
parameter2-2-1-2 value2-2-1-2;
}
block2-2-2{
parameter2-2-2-1 value2-2-2-1;
parameter2-2-2-2 value2-2-2-2;
}
}
}
and i want this array dynamically in php:
$blocks = array(
$parameter => $value,
$parameter => $value,
$block => array(
$parameter => $value,
$parameter => $value,
$block => array(
$parameter => $value,
$parameter => $value,
$block => array(
$parameter => $value,
$parameter => $value
...
)
)
)
);
How to create dynamically nested array in PHP
Thanks.
UPDATE:
I read file line by line to an array and i want create above structure for edit it and write it again to config file.
I means from "dynamic" is creating array inside "for" or other similar things.
Try this... (change "conf.txt" to "your conf file name")
<?php
$file = fopen("conf.txt","r");
$array = array();
$a = createArray($file, $array);
fclose($file);
print("<pre>".print_r($a,true)."</pre>");
function createArray($file, $array){
while(! feof($file)){
$line = fgets($file);
$line = trim($line);
if ($line == ""){
continue;
}
if (strpos($line,'{') !== false){
$line = trim(str_replace('{','',$line));
$array[$line] = array();
$array[$line] = createArray($file, $array[$line]);
} else if (strpos($line,'}') !== false) {
return $array;
} else {
$line = str_replace(';','',$line);
$key = strtok($line, ' ');
$value = strtok(' ');
$array[$key] = $value;
}
}
return $array;
}
?>
Creating array dynamically:
in all PHP versions:
$foo = array();
in PHP 5.4+ (aka "short syntax"):
$foo = [];
Creating nested array dynamically:
$foo = [];
$foo['bar'] = [];
$foo['bar']['zoo'] = [];
or
$foo = [];
$bar = ['zoo' => []];
$foo['bar'] = $bar;
And finally call
print_r($foo);
to see what you got created. Both cases are equal so you will see:
Array
(
[bar] => Array
(
[zoo] => Array
(
)
)
}
Please see docs on array: http://php.net/manua/en/language.types.array.php

How to make first array value to uppercase

I am trying to make first array value to uppercase.
Code:
$data = $this->positions_model->array_from_post(array('position', 'label'));
$this->positions_model->save($data, $id);
So before save($data, $id) to database I want to convert position value to uppercase. I have tried by this
$data['position'] = strtoupper($data['position']);
but than it is not storing the value in db with uppercase but as it is what user inputs.
Current output of $data:
Array ( [position] => it [label] => Information Technology )
And I want it in uppercase as IT
Added Model Method
public function get_positions_array($id = NULL, $single = FALSE)
{
$this->db->get($this->_table_name);
$positions = parent::get($id, $single);
$array = array();
foreach($positions as $pos){
$array[] = get_object_vars($pos);
}
return $array;
}
Main MY_Model method
public function array_from_post($fields)
{
$data = array();
foreach ($fields as $field) {
$data[$field] = $this->input->post($field);
}
return $data;
}
This should work:
$data = $this->positions_model->array_from_post(array('position', 'label'));
$data['position'] = strtoupper($data['position']);
$this->positions_model->save($data, $id);
If Its not, then $data array have only read attribute.
The array_from_post() method returns an array with the format below:
$data = array(
'position' => 'it',
'label' => 'Information Technology'
);
So, you could make first value of the array to uppercase, by using array_map or array_walk functions as follows:
$data = array_map(function($a) {
static $i = 0;
if ($i === 0) { $i++; return strtoupper($a); }
else return $a;
}, $array);
Note: This only works on PHP 5.3+, for previous versions, use the function name instead.
Here is the array_walk example, which modifies the $data:
array_walk($data, function(&$value, $key) {
static $i = 0;
if ($i == 0) { $i++; $value = strtoupper($value); }
});
Again, if you're using PHP 5.2.x or lower, you could pass the function name instead.

Split an array into sub arrays

I would like to split an array:
$o = json_decode('[{"id":"1","color":"green"},{"id":"2","color":"green"},{"id":"3","color":"yellow"},{"id":"4","color":"green"}]');
based on the color attribute of each item, and fill corresponding sub arrays
$a = array("green", "yellow", "blue");
function isGreen($var){
return($var->color == "green");
}
$greens = array_filter($o, "isGreen");
$yellows = array_filter($o, "isYellow");
// and all possible categories in $a..
my $a has a length > 20, and could increase more, so I need a general way instead of writing functions by hand
There doesn't seem to exist a function array_split to generate all filtered arrays
or else I need a sort of lambda function maybe
You could do something like:
$o = json_decode('[{"id":"1","color":"green"},{"id":"2","color":"green"},{"id":"3","color":"yellow"},{"id":"4","color":"green"}]');
$greens = array_filter($o, function($item) {
if ($item->color == 'green') {
return true;
}
return false;
});
Or if you want to create something really generic you could do something like the following:
function filterArray($array, $type, $value)
{
$result = array();
foreach($array as $item) {
if ($item->{$type} == $value) {
$result[] = $item;
}
}
return $result;
}
$o = json_decode('[{"id":"1","color":"green"},{"id":"2","color":"green"},{"id":"3","color":"yellow"},{"id":"4","color":"green"}]');
$greens = filterArray($o, 'color', 'green');
$yellows = filterArray($o, 'color', 'yellow');
In my second example you could just pass the array and tell the function what to filter (e.g. color or some other future property) on based on what value.
Note that I have not done any error checking whether properties really exist
I would not go down the road of creating a ton of functions, manually or dynamically.
Here's my idea, and the design could be modified so filters are chainable:
<?php
class ItemsFilter
{
protected $items = array();
public function __construct($items) {
$this->items = $items;
}
public function byColor($color)
{
$items = array();
foreach ($this->items as $item) {
// I don't like this: I would prefer each item was an object and had getColor()
if (empty($item->color) || $item->color != $color)
continue;
$items[] = $item;
}
return $items;
}
}
$items = json_decode('[{"id":"1","color":"green"},{"id":"2","color":"green"},{"id":"3","color":"yellow"},{"id":"4","color":"green"}]');
$filter = new ItemsFilter($items);
$greens = $filter->byColor('green');
echo '<pre>';
print_r($greens);
echo '</pre>';
If you need more arguments you could use this function:
function splitArray($array, $params) {
$result = array();
foreach ($array as $item) {
$status = true;
foreach ($params as $key => $value) {
if ($item[$key] != $value) {
$status = false;
continue;
}
}
if ($status == true) {
$result[] = $item;
}
}
return $result;
}
$greensAndID1 = splitArray($o, array('color' => 'green', 'id' => 1));

Categories