1
\$\begingroup\$

I have an object which stores an app configuration in an associative array, as this:

[
  'Database' => 
    [
      'DB_SERVER' => 'localhost'
      'DB_NAME' => 'adbname'
      'DB_USER' => 'theuser'
      'DB_PASS' => 'thepass'
    ]
]

And a function, get(), which receives a variable number of arguments and returns the configuration value for this parameters. For example, Config::get('Database','DB_PASS') will return 'thepass'.

This is an excerpt of the code:

class Config
{
    protected static $values;

    ...

    public static function get()
    {
        $val = &self::$values;
        $argList = func_get_args();
        for ($i = 0; $i < count($argList); $i++) {
            $val = &$val[$argList[$i]];
            if(empty($val)) break;
        }
        return (is_null($val)?"":$val);
    }
}

Is there a more elegant / efficient way of accessing the value?

\$\endgroup\$
0

2 Answers 2

2
\$\begingroup\$

This seems alright, but you could use foreach, and checking and returning can be simpler:

class Config
{
    protected static $values;

    ...

    public static function get()
    {
        $val = &self::$values;
        foreach(func_get_args() as $argument)
        {  
          $val = &$val[$argument];
          if(empty($val)) return "";
        }
        return $val;
    }
}

I would call this more elegant, but it's not more efficient. (I did not test the code.)

\$\endgroup\$
2
  • \$\begingroup\$ I didn't have the courage to use foreach: iteration throught arrays seems to be tricky, and I wanted to be sure that the processing order was the same. \$\endgroup\$ Jun 8, 2016 at 13:24
  • \$\begingroup\$ It will most likely work, foreach simply starts with the first element, and then the next, just like your for loop. \$\endgroup\$ Jun 8, 2016 at 15:08
1
\$\begingroup\$

There is more accurate and efficient way to access config options:

class Config {

    protected static $values = [    // exemplary config array
        'Database' =>
                [
                    'DB_SERVER' => 'localhost',
                    'DB_NAME' => 'adbname',
                    'DB_USER' => 'theuser',
                    'DB_PASS' => 'thepass'
                ],
        'testUrl' => "http://myexample.com"     // 1st level option
    ];

    public static function get() {
        $args = func_get_args();
        $count = count($args);

        if ($count == 0 || empty($args[0])) {
            throw new \Exception("Unspecified config option!");
        }
        if ($count == 1 && isset(self::$values[$args[0]])) {
            return self::$values[$args[0]];
        } elseif ($count == 2 && isset(self::$values[$args[0]])
                && is_array(self::$values[$args[0]]) 
                && isset(self::$values[$args[0]][$args[1]])) {
            return self::$values[$args[0]][$args[1]];
        }

        return null;
    }
}

print_r(Config::get('Database','DB_PASS'));  // "thepass"
print_r(Config::get('testUrl'));             // "http://myexample.com"
print_r(Config::get(""));              // will throw an exception: Unspecified config option!
\$\endgroup\$
4
  • \$\begingroup\$ But what if we have more than two levels? I wouldn't work... \$\endgroup\$ Jun 8, 2016 at 13:19
  • \$\begingroup\$ @AlvaroMaceda so, you should know how deep can be your config path \$\endgroup\$ Jun 8, 2016 at 13:30
  • \$\begingroup\$ Let's say I have ten levels. \$\endgroup\$ Jun 8, 2016 at 19:24
  • \$\begingroup\$ @AlvaroMaceda, ten levels? That's bad practice to construct a tangled/confused structure for intensively used config within application \$\endgroup\$ Jun 8, 2016 at 20:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.