Parsing a config-file - working/not working depending on how I do it

Discussion in 'PHP' started by PoPSiCLe, Jan 28, 2014.

  1. #1
    Okay. First off, I have a (somewhat extensive) config.php-file, with a list of predefined variables. This is working okay.
    Example:
    
    $version = "Beta 0.65";
    // database settings
    $dbhost = '127.0.0.1';
    $dbport = '';
    $dbusername = 'root';
    $dbpassword = '';
    // more stuff beneath
    
    PHP:
    Then, I also have a Config php-class, in coreclass.php, which looks like the following:
    
    class Config
    {
      static $confArray;
      public static function read($name)
      {
      return self::$confArray[$name];
      }
      public static function write($name, $value)
      {
      self::$confArray[$name] = $value;
      }
    }
    
    PHP:
    The coreclass.php-file is loaded from the config.php file, via require_once('coreclass.php');
    If I, in the coreclass-file, use the Config-class as this:
    
    Config::write('db.host', $dbhost);
    Config::write('db.port', $dbport);
    
    PHP:
    it works just fine. However, if I try to do the same, only read all the content of the config.php via file() and do a parsing that way, it does NOT work - and I can't for the life of me understand why. Granted, I'm tired, so I might be missing something obvious here...
    What I'm doing, currently, is this:
    
    $getconfigvars = file('config.php', FILE_IGNORE_NEW_LINES); //reads the file
    $lines_in_configfile = count(file('config.php')); // counts the lines for the loop
    
    for ($i=0; $i < $lines_in_configfile; $i++) {
      if (strstr($getconfigvars[$i], '=')) { // limits the parsing to the lines with actual variables
      $first = strstr($getconfigvars[$i], '=', true); // gives the variable names
      $name = str_replace('$','',rtrim($first));
      Config::write(''.$name.'',${$first}); // this should do what the single lines do above?
      }
    }
    
    PHP:
    But for some reason that doesn't work - what I'm trying to do here is just get the variable names from the config-file - the variables themselves are already present, as the coreclass (where I'm doing this), is loaded from the config.php-file - and therefore the variables I assign with Config::write should be present, yes? But I keep getting "undefined variable" for every line. And I can't figure out why they're "unassigned" when they're created and exist in config.php.

    Could someone more awake than me shed some light?
     
    Solved! View solution.
    PoPSiCLe, Jan 28, 2014 IP
  2. stephan2307

    stephan2307 Well-Known Member

    Messages:
    1,277
    Likes Received:
    33
    Best Answers:
    7
    Trophy Points:
    150
    #2
    The answer is really simple. All your code is correct and it works as you intended. Problem is in this line

    Config::write(''.$name.'',${$first});
    PHP:
    when you do ${$first} you expect a variable to be present called ie $version ( from the config.php ). However that variable does not exist as you read in the config.php as text.

    So either include the config.php file before you read it in or use code like this.


    $getconfigvars = file('config.php', FILE_IGNORE_NEW_LINES); //reads the file
    $lines_in_configfile = count(file('config.php')); // counts the lines for the loop
    for ($i=0; $i < $lines_in_configfile; $i++) {
      if (strstr($getconfigvars[$i], '=')) { // limits the parsing to t$parts = explode(' = ',$getconfigvars[$i]);
            $first = trim ( str_replace('$','',$parts[0]));
            $value = trim (str_replace(array(';','"','\''),'',$parts[1]));
           Config::write($first,$value);
      }
    }
    PHP:
     
    stephan2307, Jan 29, 2014 IP
  3. PoPSiCLe

    PoPSiCLe Illustrious Member

    Messages:
    4,623
    Likes Received:
    725
    Best Answers:
    152
    Trophy Points:
    470
    #3
    I know I read in the config.php as text, but as I'm including the coreclass.php in the config.php, shouldn't the variables in the config.php be available for the coreclass.php?
     
    PoPSiCLe, Jan 29, 2014 IP
  4. stephan2307

    stephan2307 Well-Known Member

    Messages:
    1,277
    Likes Received:
    33
    Best Answers:
    7
    Trophy Points:
    150
    #4
    looks like a scoping issue.

    lets assume you have the following

    <?php
    
       $var = 'foo';
    
    
    class whatever {
    
         function something() {
           // $var is not in scope by default.
          // you could do the following to bring it into scope.
          global $var;
         }
    
    }
    PHP:
     
    stephan2307, Jan 29, 2014 IP
  5. HuggyStudios

    HuggyStudios Well-Known Member

    Messages:
    724
    Likes Received:
    20
    Best Answers:
    26
    Trophy Points:
    165
    #5
    You could just use CONSTANTS
     
    HuggyStudios, Jan 29, 2014 IP
  6. PoPSiCLe

    PoPSiCLe Illustrious Member

    Messages:
    4,623
    Likes Received:
    725
    Best Answers:
    152
    Trophy Points:
    470
    #6
    Yes, I could understand the scoping-issue, but again - if I run the
    Config::write('name',$var);
    separately, without running it within the settings above, after reading the file, it works just fine. I'll have to take a closer look, maybe I'm just looking at something and seeing something else.
    Scope shouldn't be a problem, since the Config::write-function isn't inside a class at all.
     
    PoPSiCLe, Jan 29, 2014 IP
  7. stephan2307

    stephan2307 Well-Known Member

    Messages:
    1,277
    Likes Received:
    33
    Best Answers:
    7
    Trophy Points:
    150
    #7
    just wondering if there is any whitespace that is messing things up. try these lines

    $first = trim(strstr($getconfigvars[$i], '=', true)); // gives the variable names
      $name = trim(str_replace('$','',$first));
    PHP:
     
    stephan2307, Jan 29, 2014 IP
  8. #8
    on second thought I wonder if this one is wrong

    Config::write(''.$name.'',${$first})
    PHP:
    If you take the first setting in your config
    $version = "Beta 0.65";
    PHP:
    then $name would be 'version' and $first would be '$version '

    $name is correct but first has 2 problems I think.
    1. there shouldn't be any whitespace
    2. there shouldn't be a $ sign as ${$first} would be $$version which is wrong.

    So I wonder if this is the correct line
    Config::write(''.$name.'',${$name})
    PHP:
     
    stephan2307, Jan 29, 2014 IP
  9. PoPSiCLe

    PoPSiCLe Illustrious Member

    Messages:
    4,623
    Likes Received:
    725
    Best Answers:
    152
    Trophy Points:
    470
    #9
    Damn, I feel stupid now. Of course.
    The final code looks like this:
    
    $getconfigvars = file('config.php', FILE_IGNORE_NEW_LINES);
    $lines_in_configfile = count(file('config.php'));
    for ($i=0; $i < $lines_in_configfile; $i++) {
      if (strstr($getconfigvars[$i], '=')) {
         $first = strstr($getconfigvars[$i], '=', true);
         $name = str_replace('$','',rtrim($first));
         Config::write(''.$name.'',${$name});
      }
    }
    
    PHP:
    Under 10 lines total... now I just need to redo some of the names, so everything fits (not everything was named exactly as the variable, and everything should be hunky-dory :D Thanks for your help!
     
    PoPSiCLe, Jan 29, 2014 IP
  10. nico_swd

    nico_swd Prominent Member

    Messages:
    4,153
    Likes Received:
    344
    Best Answers:
    18
    Trophy Points:
    375
    #10
    Why don't you store the settings in an array? That would pretty much eliminate a lot of problems.

    Config file:
    
    $settings['version'] = "Beta 0.65";
    // database settings
    $settings['dbhost'] = '127.0.0.1';
    $settings['dbport'] = '';
    $settings['dbusername'] = 'root';
    $settings['dbpassword'] = '';
    
    PHP:
    Config class:
    
    public static function loadConfig()
    {
        require __DIR__ . '/config.php';
    
        if (empty($settings) || !is_array($settings))
        {
             throw new Whatever();
        }
    
        static::$confArray = $settings;
    }
    
    
    public static function exportModifiedSettings()
    {
        $settings = '<' . '? $settings = ' . var_export(static::$settings, true) . '; ?' . '>';
    
        if (!@file_put_contents($settings, __DIR__ . '/config.php', LOCK_EX))
        {
            throw new Something();
        }
    
        return true;
    }
    
    PHP:
     
    nico_swd, Jan 29, 2014 IP
  11. PoPSiCLe

    PoPSiCLe Illustrious Member

    Messages:
    4,623
    Likes Received:
    725
    Best Answers:
    152
    Trophy Points:
    470
    #11
    Mostly because the config.php-file is an older settings-file which I haven't begun to fiddle with as of yet, and it's being written via reading the sample file, iterating through empty variables, outputting empty variables to a form, for then to write the config.php when the form is filled. Of course this could be done with an array as well, but that would involve rewriting that logic instead of finding a way to automatically write the config-parameters - this just seemed quicker and easier :)
     
    PoPSiCLe, Jan 29, 2014 IP