1

I wrote a custom framework. Which uses the .ini type of config file.

Say, if I have a constant assigned in the .ini file as

[production]
db.mongo.hostName = localhost

I am currently parsing this through parse_ini_file() function.

The result will be

$config[production][db.mongo.hostname] = "localhost";

Now I wanna turn this array to an object which should go like

$config->db->mongo->hostname

I tried exploding it with '.', but then I am stuck with forming this as an above iterative object.

Can someone please help me with this.

10

3 Answers 3

3

The following is a rudimentary class that has a single function to import the ini array as you have specified it:

/**
 * Config "Class"
 * @link http://stackoverflow.com/q/11188563/367456
 */
class Config
{
    public function __construct(array $array = array())
    {
        $this->importIniArray($array);
    }

    public function importIniArray(array $array)
    {
        foreach ($array as $key => $value) {
            $rv = &$this;
            foreach (explode('.', $key) as $pk) {
                isset($rv->$pk) || $rv->$pk = new stdClass;
                $rv = &$rv->$pk;
            }
            $rv = $value;
        }
    }
}

I only added the __construct function because you re-use the variable. Usage:

$config = parse_ini_file($path);

$config = new Config($config['production']);

print_r($config);

Exemplary output:

Config Object
(
    [db] => stdClass Object
        (
            [mongo] => stdClass Object
                (
                    [hostname] => localhost
                    [user] => root
                )

        )

)

Edit: You can also solve the problem to locate the array member at time of access. I compiled a little example that behaves similar and it explodes nothing. I called it DynConfig because as you'll see it's dynamic (or magic):

$config = new DynConfig($config['production']);
var_dump($config);
echo $config->db->mongo->hostname; # localhost

The var_dump shows that the array is just preserved internally:

object(DynConfig)#1 (1) {
  ["array":"DynConfig":private]=>
  array(2) {
    ["db.mongo.hostname"]=>
    string(9) "localhost"
    ["db.mongo.user"]=>
    string(4) "root"
  }
}

So how does this work? Each time you access a property, either a key exists or the prefix is extended and the same object is returned. That's in the __get function:

/**
 * Config "Class"
 * @link http://stackoverflow.com/q/11188563/367456
 */
class DynConfig
{
    private $array;

    public function __construct($array)
    {
        $this->array = $array;
    }

    public function __get($name)
    {
        static $prefix = '';
        $k = $prefix .= $name;
        if (isset($this->array[$k])) {
            $prefix = '';
            return $this->array[$k];
        }
        $prefix .= '.';
        return $this;
    }
}

However, this is of experimental nature. The first suggestion is much more direct and much easier to deal with. Keep in mind that your config object should be really simple, it just needs to store some values and that's it.

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

2 Comments

I am already using php magic functions and singleton pattern in my Config class... Thank you... This is so cool... DynConfigAccess nis so cool..
No, actually I made a mistake, this does not need a second class. I edit the answer. And don't use the singleton antipattern, also magic is not really helpful in the long run. you will introduce problems.
2

You can done it as below

function assignTo($obj,$keys,$value)
{
        if(count($keys) > 1)   
        {                      
                $h = array_shift($keys);        
                $obj->$h = $obj->$h ? $obj->$h : new stdClass();
                assignTo($obj->$h,$keys,$value);
        }                      
        else                   
        {                      
                $obj->$keys[0] = $value;        
        }
}
$config['production']['db.mongo.hostname'] = "localhost";
$config['production']['db.mongo.password'] = "1234567";
$config['production']['version'] = "1.0";

$object = new stdClass();      
foreach($config['production'] as $key=>$value)
{
        assignTo($object,explode('.',$key),$value);
}                              
print_r($object); 

Which would output:

stdClass Object
(
    [db] => stdClass Object
        (
            [mongo] => stdClass Object
                (
                    [hostname] => localhost
                    [password] => 1234567
                )

        )

    [version] => 1.0
)

3 Comments

@Lake: In case you want to learn some tricks, take a look at this duplicate question and it's answers: stackoverflow.com/q/8537148/367456
@hakre It is the duplicate... But to be honest for all the key words I searched I couldn't end up in that page.
@Karthik: Sure, it's hard to find stuff sometimes. The most important stuff is to have it cross-linked I'd say, it's not even and exact "exact" duplicate, because that one is about arrays and yours objects (however those two are close in PHP).
0
// assuming $var is a multidimensional array
$obj = json_decode (json_encode ($var), FALSE);

Comments

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.