3

I am trying to assign values of array by dynamic name I am trying following

$arr = array();

$path = 'arr'."['item']['abc']";

${$path} = array(
       'name'=>'somename',
       'other'=>'...'
);

isn't ${$path} => $arr['item']['abc'];

also I tried $$path which should evaluated as $arr['item']['abc']; but none of them working

http://codepad.viper-7.com/Dc8Jei

Updated -> http://codepad.viper-7.com/k4sIgJ


What I am trying to do is store files and folder in array I have directory structure like this

(this is amazon aws s3 object keys)

   aaa/aaab/ 
   aaa/a.png 
   aaa/abc/one.png 

   abb/a/
   abb/some/
   abb/some/ac.png

now what I am trying to do is store those items in array

I broke down those keys into this string like

 ['aaa']['abc']

now what I want to get is

[aaa]{
    [aaab]{}
    [abc]{
        [0]{one.png}
    }
    [aaab]{}
}

its just for illustration

13
  • 3
    That's not how variable variables work. Commented Oct 16, 2015 at 11:29
  • @Rizier123 could you tell me how it works codepad.viper-7.com/OkcLdz ? Commented Oct 16, 2015 at 11:30
  • @Uchiha I just want to assign array to $arr ['item']['abc'] but I can not have it static Commented Oct 16, 2015 at 11:31
  • Richerd, but how about using a reference like $myItem = &$arr ['item']['abc'] instead? Then you could go $item[] = array(...) Commented Oct 16, 2015 at 11:35
  • 1
    I could rewrite the codepad not to use variable variables very easily. there are multiple possible solutions. But without a bit more context than that, it's hard to know whether any solution I write would be suitable. ie in your real program, are those array index strings hard-coded as in your codepad or are they coming in from somewhere else? Also, are you always going to have ['item'] as the first array subscript as in the codepad, or could that change? etc etc. Commented Oct 16, 2015 at 11:53

3 Answers 3

3

Referring to your updated codpad, there are multiple possible ways to write this without using variable variables.

Here's one possible option:

<?php

$arr = array();

$loc_arr = array('item' => array('abc', 'www', 'ccc'));

foreach($loc_arr as $itemKey=>$items){
  foreach($items as $subitem) {
    $arr[$itemKey][$subitem] = array(
       'name'=>'somename',
       'other'=>'...'
    );
  }
}

As I mentioned in the comments, it's very difficult to know how suitable this specific solution would be to your particular use-case, but I think it should demonstrate clearly that there shouldn't really be any need for variable variables in this kind of context.

Variable variables should be thought of much like eval(): Avoid using them wherever possible. If you find yourself wanting to use them, then you're probably approaching things from the wrong angle. They exist because they can be useful in some occasional cases, but those cases are very rare. I've been writing PHP as a professional developer for over a decade, and I can't remember the last time I even came close to needing to use them.

Sign up to request clarification or add additional context in comments.

5 Comments

Re the updated question: How are you getting that folder strucutre in the first place?
this is what amazon aws s3 bucket listbucket returns, as you know amazon s3 treat every thing as object
So you've got an object structure already? Why don't you just use that?
because I am integrating with javascript file browser which need json of associative array like in question.. and amazon aws s3 object is file not php object :)
2

I think you should really consider using references instead of $$, like this:

$arr = array();

$path = &$arr['item']['abc'];

$path[] = array(
       'name'=>'somename',
       'other'=>'...'
);

print_r($path);

EDIT: Another option based on the new details coming from the author:

Lets consider the case when indexes are stored in a separate array, 'dynamically' as you call it. 'item' index is always the same - let's just omit it.

$arr = array();

//Throwing out the 'item' index, leave only the important keys here
$loc_arr = array("abc","www","ccc");

foreach($loc_arr as $item){
    $arr['item'][$item] = array(
       'name'=>'somename',
       'other'=>'...'
    );
}

print_r($arr);

And even if the 'item' element wouldn't have the same name all the time - you could use 2 dimensions to specify the right one. Add some recursive function and it will iterate over the thing and set values accordingly. Just another option for you.

$loc_arr = array('item' => array('abc','www','ccc'), 'foo' => array('bar', 'bar2'));

3 Comments

Yep. I'll upvote anyone who suggests something sensible instead of the insanity that is variable variables.
['item']['abc'] is not static its dynamic check codepad.viper-7.com/k4sIgJ
As usual: if eval is the answer, you are probably asking the wrong questions.
0

A less weired approach than variable variables would be to build a proper structure:

<?php

$arr = array();

$loc_arr = array(
   'item' => array(
           'abc',
           'www',
           'ccc'),
   'other item' => array(
           'other index'
   )
);

foreach($loc_arr as $item => $scndLevel){
    foreach ( $scndLevel as $level) {
        $arr[$item][$level] = array(
           'name'=>'somename',
           'other'=>'...'
        );
    }
}

print_r($arr);

this prints:

Array
(
    [item] => Array
        (
            [abc] => Array
                (
                    [name] => somename
                    [other] => ...
                )    
            [www] => Array
                (
                    [name] => somename
                    [other] => ...
                )   
            [ccc] => Array
                (
                    [name] => somename
                    [other] => ...
                )    
        )   
    [other item] => Array
        (
            [other index] => Array
                (
                    [name] => somename
                    [other] => ...
                )    
        )    
)

UPDATE:

You should consider a recursional function when traversing directories rather than a procedural approach:

Pseudo code:

dir = array();

function traverse(dir)
{
    foreach ( direntry as filename) {
        if ( filename is a sub directory ) {
            dir[filename] = array();
            traverse(dir[filename]);
        } else {
            dir[] = filename;
        }

}
dir['/'] = array();
traverse(dir['/']);

That's only to give you an idea and a starting point, this is not working code.

8 Comments

this is the actual problem I can not have fix number of keys :( please check the updated question
Your approach to traverse the directories of S3 may be worth consideation. This likely smells like a task for a recursion rather than strange algorithms.
i tried recursion but amazon aws s3 doesn't provide folder structure where all we get is array something like pastebin.com/mNHNNyUE so there is no way i can apply recursion as you can see
And how do you get ['aaa']['abc']
To be more precise: if you can build a string like ['aaa']['abc'] you can also build a multidimensional array out of that. And if so, you may also easily immediately add the items on arbitrary levels.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.