2011-04-20 3 views
2

[parse_ini_file] [1]과 같은 somehting을 사용하고 싶습니다. 나는 PHP 배열이 될 것 같은 다른 방법으로 그것을하고 싶은,php parse_ini_file oop & deep

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

을하지만 :

내가 더 절차를로드하는 Boot.ini 파일을 예를 들어 말할 수 있습니다

$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의 지금 파일을 액세스 할 때 (210) 그래서 이런 식으로 접근하고 싶습니다 ->

or `$ini->db->host1` 

는 유형, 호스트, 사용자 이름, 암호와 DBNAME 같은 모든 속성을 가진 배열을 반환합니다 어떤

;

나는 도움을 주셔서 감사합니다. 대단히 감사드립니다.

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

답변

4

글쎄, 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 해킹. 이제 여분의 $prev을 사용하여 마지막 객체 레벨을 다시 설정 해제하십시오. (마지막 $ 키를 탐지하는 루프가 더 잘 작동했을 것입니다.)

개체 구문을 사용하려면 new stdclassnew ArrayObject(array(), 2);으로 바꿉니다.

+0

라인이 적고 조건이 적기 때문에 당신이 더 멋지다고 생각합니다. 나는 또한'$ prev -> $ key = $ value; '를 루프 밖으로 옮기기를 원했지만 어떤 이유로'$ last' 해킹이 더 좋을 것이라고 결정했다.음, $ prev는이 경우 더 편리합니다 .-) – zerkms

+0

$ prev hack은 추가 변수로 로컬 범위를 오염시키고 임시 객체를 만든 다음 덮어 씁니다. 따라서 힙을 조각화 할 수 있습니다. 조금 더. 그러므로 $ 마지막 확인도 더 빠를 가능성이 높습니다. - 어쨌든, 예상보다 많은 엣지 케이스가있는 것으로 밝혀졌습니다. :] – mario

+0

힙 조각화는 PHP를 사용하는 프로그램을 생각할 때 마지막으로 생각한 것입니다.)) – zerkms

3
$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); 
+0

+1 for nicer fix :) – mario

0

나는 당신을위한 우아한 솔루션을 가지고 있습니다. 이 구현은 상속을 허용하고 우리의 collegue "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 = 생산
XY = 3

[oi : environment]
z = 5