【问题标题】:php parse_ini_file oop & deepphp parse_ini_file oop & deep
【发布时间】:2011-08-09 02:49:19
【问题描述】:

我想使用 [parse_ini_file][1] 之类的东西。

假设我有一个 boot.ini 文件,我将加载该文件以进行进一步处理:

    ;database connection settings
[database]
type        =   mysql;
host        =   localhost;
username    =   root;
password    =   "";
dbName      =   wit;

但是,我想以不同的方式使用 php 数组:

$ini['database']['whatever']

所以首先我希望我的 boot.ini 具有这样的结构:

;database settings (comment same style)
db.host1.type = mysql;
db.host1.host = localhost;
db.host1.username = root;
db.host1.password = "";
db.host1.dbName = wit;

db.host2.type = mysql;
db.host2.host = otherHost;
db.host2.username = root;
db.host2.password = "";
db.host2.dbName = wit;

所以当我现在访问该文件时,我想以这种方式访问​​它:

$ini['db']['host1']['whatever']

除此之外,我想通过 OOP 来实现,所以可以说: $ini->db->host1->随便

or `$ini->db->host1` 

将返回一个包含所有属性的数组,例如类型、主机、用户名、密码和 dbName;

感谢任何形式的帮助。非常感谢您。

  [1]: http://uk2.php.net/manual/en/function.parse-ini-file.php

【问题讨论】:

    标签: php parsing config ini


    【解决方案1】:

    那么,您需要对parse_ini_file 结果数组进行后处理。

    $ini_array = parse_ini_file("bootstrap.ini");
    
    $ini = new stdclass;
    foreach ($ini_array as $key=>$value) {
        $c = $ini;
        foreach (explode(".", $key) as $key) {
            if (!isset($c->$key)) {
                $c->$key = new stdclass;
            }
            $prev = $c;
            $c = $c->$key;
        }
        $prev->$key = $value;
    }
    

    更新 Hackety-Hack。现在使用额外的$prev 再次取消设置最后一个对象级别。 (检测最后一个 $key 的 for 循环会更好)。

    如果要使用数组语法对象语法,请将new stdclass 替换为new ArrayObject(array(), 2);

    【讨论】:

    • 嗯,我认为你的更好,因为它有更少的行和更少的条件。我还想将$prev->$key = $value; 移出循环,但出于某种原因决定$last hack 会更好。好吧,不是,$prev 在这种情况下更方便;-)
    • 好吧,$prev hack 用一个额外的变量污染了本地范围,并创建了一个临时对象,然后覆盖它,所以它可能会使堆更加碎片化。因此,为什么 $last 检查也可能更快。 -- 无论如何,结果比预期有更多的边缘情况.. :]
    • 堆碎片是我在使用 php 编程时最不想想到的事情)))
    • 完美,非常感谢!实际上它看起来很简单,因为你只是在分解字符串并依赖于你继续 - 嗯为什么我没有考虑到:((
    【解决方案2】:
    $ini_array = parse_ini_file("sample.ini");
    
    $ini = new stdclass;
    foreach ($ini_array as $key => $value) {
        $last = substr(strrchr($key, '.'), 1);
        if (!$last) $last = $key;
    
        $node = $ini;
    
        foreach (explode('.', $key) as $key2) {
            if (!isset($node->$key2)) {
                $node->$key2 = new stdclass;
            }
    
            if ($key2 == $last) {
                $node->$key2 = $value;
            } else {
                $node = $node->$key2;
            }
        }
    
    }
    
    var_dump($ini->db->host1->type);
    

    【讨论】:

      【解决方案3】:

      我为您准备了一个优雅的解决方案。这个实现允许使用点的继承和向量,正如我们的同事“zerkms”之前向我们展示的那样。事实上,我采用了他的解决方案并对其进行了改进。因此,该解决方案就像 Zend Parser :) 我对其进行了测试并且工作正常。但是,众所周知,不可能测试所有的可能性。那么,希望有心人发现问题,提出改正意见。

      这里是代码(作为一个函数):

      function parse($filename) {
      
              $ini_array = parse_ini_file ( $filename, true );
      
              if (! $ini_array)
                  throw new Exception ( 'Error on parsing ini file!', - 1 );
      
              $ini = new stdClass ();
      
              //Parse section...
              foreach ( $ini_array as $namespace => $prop ) {
      
                  $section = $namespace;
                  $ext = explode ( ':', $namespace );
      
                  if (count ( $ext ) == 2) {
      
                      $section = trim ( $ext [0] );
                      $extend = trim ( $ext [1] );
      
                      if (! isset ( $ini->$extend ))
                          throw new Exception ( 'Parent section doesn\'t exists!', - 1 );
      
                      $ini->$section = clone $ini->$extend;
      
                  } else
                      $ini->$section = new stdClass ();
      
                  foreach ( $prop as $key => $value ) {
      
                      $arr = explode ( '.', $key );
                      $n = count ( $arr ) - 1;
      
                      if ($n) {
                          $aux = $ini->$section;
                          for($i = 0; $i < $n; ++ $i) {
      
                              if(!isset($aux->$arr [$i]))
                                  $aux->$arr [$i] = new stdClass ();
      
                              $aux = $aux->$arr [$i];
                          }
                          $aux->$arr [$n] = $value;
                      } else
                          $ini->$section->$key = $value;
      
                  }
      
              }
      
              return $ini;
      
      }
      

      这里有一个 .ini 文件的例子:

      [环境]
      env_name = 生产
      x.y = 3

      [oi : 环境]
      z = 5

      【讨论】:

        猜你喜欢
        • 2013-05-10
        • 2012-06-17
        • 2015-05-06
        • 1970-01-01
        • 2012-12-11
        • 2010-09-13
        • 1970-01-01
        • 1970-01-01
        • 2012-06-28
        相关资源
        最近更新 更多