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\$
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\$
  • \$\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\$ – Alvaro Maceda Jun 8 '16 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\$ – KIKO Software Jun 8 '16 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\$
  • \$\begingroup\$ But what if we have more than two levels? I wouldn't work... \$\endgroup\$ – Alvaro Maceda Jun 8 '16 at 13:19
  • \$\begingroup\$ @AlvaroMaceda so, you should know how deep can be your config path \$\endgroup\$ – RomanPerekhrest Jun 8 '16 at 13:30
  • \$\begingroup\$ Let's say I have ten levels. \$\endgroup\$ – Alvaro Maceda Jun 8 '16 at 19:24
  • \$\begingroup\$ @AlvaroMaceda, ten levels? That's bad practice to construct a tangled/confused structure for intensively used config within application \$\endgroup\$ – RomanPerekhrest Jun 8 '16 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.