function Authorize(){
if ($this->session->userdata('login_in') != 'TRUE') {
redirect('Login', 'refresh');
}
$user_group_id = $this->session->userdata('user_group');
if ($user_group_id != '') {
$pre = $this->db->get_where('afro_user_group', array(
'user_group_id' => $user_group_id
))->row();
$this->Authorize = $pre;
$array = (array) $pre;
$select = 'all';
foreach ($array as $key => $value) {
if ($value == 't'){
$select .= ',' ."'". $key."'";
}
}
$array = (array) $select;
$Authorized = array_map('strtoupper', $array);
//die(print_r($Authorized));
return $Authorized ;
}
}
}
dumping $Authorized gives the following result.
Array ( [0] => 'ALL','USER_GROUP_STATUS','USER_GROUP_HAS_PERMISSION_CREATE_DEPARTMENT' )
And I want to convert it like this... in order to use array_search, array filter functions.
Array ( [0] => Array ( [0] => ALL [1] => USER_GROUP_STATUS [2] => USER_GROUP_HAS_PERMISSION_CREATE_DEPARTMENT)
how can I do that.
change
return $Authorized ;
to
$Authorized_new_format = explode(",", $Authorized[0]);
return [$Authorized_new_format];
This will break the explode the string and convert to multidimensional array;
I have an array that looks like this:
$array = array (
[level_1] => array (
[level_2] => array (
[level_3] => something
)
),
[level_12] => array (
[level_2] => somethingelse
),
[level_13] => array (
[level_22] => array (
[level_3] => something
)
),
);
The keys or values aren't always unique but the branches are.
And I have a string that looks like this:
$string = 'level_1-level_2-level_3';
Those are the keys for a branch.
And I need to somehow get the value from the array based on that string?
Like this:
$string_array = explode('-', $string);
$array[$string_array[0]][$string_array[1]][$string_array[2]] // something
But since the depth can be different this is not a viable solution...
Try this simple example, no need for a recursive function:
function get_item( $path, $array )
{
$paths = explode( '-', $path );
$result = $array;
foreach ( $paths as $path) {
isset( $result[$path] ) ? $result = $result[$path] : $result = false;
}
return $result;
}
$path = 'level_1-level_2-level_3';
echo get_item( $path, $array );
Try this:
$array = array (
'level_1' => array (
'level_2' => array (
'level_3' => 'something'
)
),
'level_12' => array (
'level_2' => 'somethingelse'
),
'level_13' => array (
'level_22' => array (
'level_3' => 'something'
)
),
);
$string = 'level_1-level_2-level_3';
$keys = explode('-', $string);
echo getItemIterative($keys, $array);
echo "\n";
echo getItemRecursive($keys, $array);
function getItemIterative($keys, $array)
{
$value = null;
foreach ($keys as $key) {
if ($value == null) {
$value = $array[$key];
}
if (is_array($value) && array_key_exists($key, $value)) {
$value = $value[$key];
}
}
return $value;
}
function getItemRecursive($keys, $array)
{
$key = array_shift($keys);
$value = $array[$key];
if (empty($keys)) {
return $value;
} else {
return getItemRecursive($keys, $value);
}
}
Make a $result variable which initially points to the root of the array, and loop through the levels of your $string_array 'til $result points at the leaf you were looking for.
// stuff you already have:
$array = array(...); // your big array
$string = 'level_1-level_2-level_3';
$string_array = explode('-', $string);
// new stuff:
$result = $array;
foreach ($string_array as $level) {
$result = $result[$level];
}
echo $result; // 'something'
Working example: Ideone
I have got an array that contains different kinds of element.
The array can have different dimension in different fields.
I want to write a function to check if there are some variables in the array are empty.
The sample array is like the following.
$array = new array(
'a'=>'A',
'b' => new array('B',''),
'c'=> ''
);
Here is a function that will go through all the arrays:
$isEmpty = checkArray( $arr );
if ( $isEmpty ) {
echo "there are empties!";
} else {
echo "no empties!";
}
function checkArray( $array ) {
foreach ( $array as $key => $value ) {
if ( is_array( $value ) ) {
if ( checkArray( $value ) ) return true;
} else {
if ( empty( $value ) ) return true;
}
}
return false;
}
How about this:
foreach ($array as $key => $value) {
if (empty($value)) {
do_stuff();
}
}
I have a multidimensional array like this one in PHP:
Array
(
[folder1] => Array
(
[folder11] => Array
(
[0] => index.html
[1] => tester.html
)
[folder12] => Array
(
[folder21] => Array
(
[0] => astonmartindbs.jpg
)
)
)
)
and should be converted to a "file path" string like this one:
Array
(
[0] => 'folder1/folder11/index.html'
[1] => 'folder1/folder11/tester.html'
[2] => 'folder1/folder12/folder21/astonmartindbs.jpg'
)
Has anybody any ideas?
I have tried a lot any all deleted... This is the starting point of my last try:
public function processArray( $_array ) {
foreach( $_array AS $key => $value ) {
if( is_int( $key ) ) {
} else {
if( is_array( $value ) ) {
$this->processArray( $value );
} else {
}
}
}
echo $this->string;
}
But i do not come to an end.... Hope somebody can help?
A recursive function may be what you are searching for. The following function will work:
/**
* Flattens the array from the question
*
* #param array $a Array or sub array of directory tree
* #param string $prefix Path prefix of $a
*/
function flatten($a, $prefix = './') {
$paths = array();
foreach($a as $index => $item) {
// if item is a string then it is a file name (or a leaf in tree)
// prefix it and add it to paths
if(is_string($item)) {
$paths []= $prefix . $item;
} else {
// if item is a directory we call flatten on it again.
// also we append the new folder name to $prefix
foreach(flatten($item, $prefix . $index . '/') as $path) {
$paths []= $path;
}
}
}
return $paths;
}
var_dump(flatten($a));
Note that flatten() call itself inside the foreach loop with a sub array as argument. This is called a 'recursive algorithm'.
If you like the SPL you can use RecursiveArrayIterator and RecursiveIteratorIterator to iterate over a flat structure.
My result would look like this:
$arr = array(); // your array
$arr = new RecursiveArrayIterator($arr);
$iterator = new RecursiveIteratorIterator($arr, RecursiveIteratorIterator::SELF_FIRST);
$currentDepth = 0;
$currentPath = array();
$result = array();
foreach($iterator as $key => $value) {
// if depth is decreased
if ($iterator->getDepth() < $currentDepth) {
// pop out path values
do {
$currentDepth--;
array_pop($currentPath);
} while($iterator->getDepth() < $currentDepth);
}
if (is_array($value)) {
// add parent to the path
$currentPath[] = $key;
$currentDepth++;
} else {
// add children to result array
$result[] = implode('/', $currentPath).'/'.$value;
}
}
Dumping the data would then look like this:
print_r($result);
/*
Array
(
[0] => folder1/folder11/index.html
[1] => folder1/folder11/tester.html
[2] => folder1/folder12/folder21/astonmartindbs.jpg
)
*/
In your case, you need to implement, a recursive function, that you tried to do, here is a simple code, it may help you,
i am not sure if that is working or no:
$result = array();
$d = 0;
$tmp = "";
public function processArray( $_array ,$before) {
foreach( $_array AS $key => $value ) {
if( is_int( $key ) ) { // If the key is a number, then there is no a sub-array
$result[$d] = $before . '/' . $value;
$d++;
$before="";
} else {
if( is_array( $value ) ) { // if the value is an array, then we will add the key into string that we will return and search into subarray.
$before = $before . '/' . $key;
$this->processArray( $value,$before );
} else {
}
}
}
return $result;
}
Looking into Kohana documentation, i found this really usefull function that they use to get values from a multidimensional array using a dot notation, for example:
$foo = array('bar' => array('color' => 'green', 'size' => 'M'));
$value = path($foo, 'bar.color', NULL , '.');
// $value now is 'green'
Im wondering if there is a way to set the an array value in the same way:
set_value($foo, 'bar.color', 'black');
The only way i found to do that is re-building the array notation ($array['bar']['color']) and then set the value.. using eval.
Any idea to avoid eval?
function set_val(array &$arr, $path,$val)
{
$loc = &$arr;
foreach(explode('.', $path) as $step)
{
$loc = &$loc[$step];
}
return $loc = $val;
}
Sure it's possible.
The code
function set_value(&$root, $compositeKey, $value) {
$keys = explode('.', $compositeKey);
while(count($keys) > 1) {
$key = array_shift($keys);
if(!isset($root[$key])) {
$root[$key] = array();
}
$root = &$root[$key];
}
$key = reset($keys);
$root[$key] = $value;
}
How to use it
$foo = array();
set_value($foo, 'bar.color', 'black');
print_r($foo);
Outputs
Array
(
[bar] => Array
(
[color] => black
)
)
See it in action.
Look at https://gist.github.com/elfet/4713488
$dn = new DotNotation(['bar'=>['baz'=>['foo'=>true]]]);
$value = $dn->get('bar.baz.foo'); // $value == true
$dn->set('bar.baz.foo', false); // ['foo'=>false]
$dn->add('bar.baz', ['boo'=>true]); // ['foo'=>false,'boo'=>true]
That way you can set the following values more than once to the same variable.
You can make these two ways (by static variable and reference variable):
<?php
function static_dot_notation($string, $value)
{
static $return;
$token = strtok($string, '.');
$ref =& $return;
while($token !== false)
{
$ref =& $ref[$token];
$token = strtok('.');
}
$ref = $value;
return $return;
}
$test = static_dot_notation('A.1', 'A ONE');
$test = static_dot_notation('A.2', 'A TWO');
$test = static_dot_notation('B.C1', 'C ONE');
$test = static_dot_notation('B.C2', 'C TWO');
$test = static_dot_notation('B.C.D', 'D ONE');
var_export($test);
/**
array (
'A' =>
array (
1 => 'A ONE',
2 => 'A TWO',
),
'B' =>
array (
'C1' => 'C ONE',
'C2' => 'C TWO',
'C' =>
array (
'D' => 'D ONE',
),
),
*/
function reference_dot_notation($string, $value, &$array)
{
static $return;
$token = strtok($string, '.');
$ref =& $return;
while($token !== false)
{
$ref =& $ref[$token];
$token = strtok('.');
}
$ref = $value;
$array = $return;
}
reference_dot_notation('person.name', 'Wallace', $test2);
reference_dot_notation('person.lastname', 'Maxters', $test2);
var_export($test2);
/**
array (
'person' =>
array (
'name' => 'Wallace',
'lastname' => 'Maxters',
),
)
*/
I created a small class just for this!
http://github.com/projectmeta/Stingray
$stingray = new StingRay();
//To Get value
$stingray->get($array, 'this.that.someother'):
//To Set value
$stingray->get($array, 'this.that.someother', $newValue):
Updated #hair resins' answer to cater for:
When a sub-path already exists, or
When a sub-path is not an array
function set_val(array &$arr, $path,$val)
{
$loc = &$arr;
$path = explode('.', $path);
foreach($path as $step)
{
if ( ! isset($loc[$step]) OR ! is_array($loc[$step]))
$loc = &$loc[$step];
}
return $loc = $val;
}
None of the examples here worked for me, so I came up with a solution using eval() (read about the risks here, but if you don't use user data, it shouldn't be much of an issue). The if-clause in the set-method allows you to push your item onto a new or existing array at that location ($location[] = $item).
class ArrayDot {
public static function get(array &$array, string $path, string $delimiter = '.') {
return eval("return ".self::getLocationCode($array, $path, $delimiter).";");
}
public static function set(array &$array, string $path, $item, string $delimiter = '.') : void {
//if the last character is a delimiter, allow pushing onto a new or existing array
$add = substr($path, -1) == $delimiter ? '[]': '';
eval(self::getLocationCode($array, $path, $delimiter).$add." = \$item;");
}
public static function unset(array &$array, $path, string $delimiter = '.') : void {
if (is_array($path)) {
foreach($path as $part) {
self::unset($array, $part, $delimiter);
}
}
else {
eval('unset('.self::getLocationCode($array, $path, $delimiter).');');
}
}
public static function isSet(array &$array, $path, string $delimiter = '.') : bool {
if (is_array($path)) {
foreach($path as $part) {
if (!self::isSet($array, $part, $delimiter)) {
return false;
}
}
return true;
}
return eval("return isset(".self::getLocationCode($array, $path, $delimiter).");");
}
private static function getLocationCode(array &$array, string $path, string $delimiter) : string {
$path = rtrim($path, $delimiter); //Trim trailing delimiters
$escapedPathParts = array_map(function ($s) { return str_replace('\'', '\\\'', $s); }, explode($delimiter, $path));
return "\$array['".implode("']['", $escapedPathParts)."']";
}
}
Example usage:
echo '<pre>';
$array = [];
ArrayDot::set($array, 'one.two.three.', 'one.two.three.');
ArrayDot::set($array, 'one.two.three.four.', 'one.two.three.four.');
ArrayDot::set($array, 'one.two.three.four.', 'one.two.three.four. again');
ArrayDot::set($array, 'one.two.three.five.', 'one.two.three.five.');
ArrayDot::set($array, 'one.two.three.direct set', 'one.two.three.direct set');
print_r($array);
echo "\n";
echo "one.two.three.direct set: ".print_r(ArrayDot::get($array, 'one.two.three.direct set'), true)."\n";
echo "one.two.three.four: ".print_r(ArrayDot::get($array, 'one.two.three.four'), true)."\n";
Output:
Array
(
[one] => Array
(
[two] => Array
(
[three] => Array
(
[0] => one.two.three.
[four] => Array
(
[0] => one.two.three.four.
[1] => one.two.three.four. again
)
[five] => Array
(
[0] => one.two.three.five.
)
[direct set] => one.two.three.direct set
)
)
)
)
one.two.three.direct set: one.two.three.direct set
one.two.three.four: Array
(
[0] => one.two.three.four.
[1] => one.two.three.four. again
)