技术开发 频道

如何用不同文件构建可配置PHP应用程序

    文本文件

    前面的两个例子对于只读配置条目都是合适的,但对于既读又写的配置参数来说又如何呢?首先,看看清单 6 中的文本配置文件。

    清单 6. config.txt

    # My application's configuration file
    Title=My App
    TemplateDirectory=tempdir

    这是同 INI 文件相同的文件格式,但我自己编写了辅助工具。为此,我创建了自己的 Configuration 类,如下所示。

    清单 7. text1.php

    <?php
    class Configuration
    {
      private $configFile = 'config.txt';

      private $items = array();

      function __construct() { $this->parse(); }

      function __get($id) { return $this->items[ $id ]; }

      function parse()
      {
    $fh = fopen( $this->configFile, 'r' );
    while( $l = fgets( $fh ) )
    {
      if ( preg_match( '/^#/', $l ) == false )
      {
    preg_match( '/^(.*?)=(.*?)$/', $l, $found );
    $this->items[ $found[1] ] = $found[2];
      }
    }
    fclose( $fh );
      }
    }

    $c = new Configuration();

    echo( $c->TemplateDirectory."\n" );
    ?>

    该代码首先创建了一个 Configuration 对象。该构造函数接下来读取 config.txt 并用解析过的文件内容来设置局部变量 $items。

    该脚本随后寻找 TemplateDirectory,这并没有在对象中直接定义。因此,使用设置成 'TemplateDirectory' 的 $id 来调用神奇的 __get 方法,__get 方法针对该键返回 $items 数组中的值。

    这个 __get 方法特定于 PHP V5 环境,所以此脚本必须在 PHP V5 下运行。实际上,本文中所有的脚本都需要在 PHP V5 下运行。

    当在命令行运行此脚本时,能看到下列结果:

    % php text1.php
    tempdir
    %

    一切都在预料之中,该对象读取 config.txt 文件,然后为 TemplateDirectory 配置项获得正确的值。

    但对于设置一个配置值,应该怎么做呢?在此类中建立一个新方法及一些新的测试代码,就能够得到这个功能,如下所示。

    清单 8. text2.php

    <?php
    class Configuration
    {
      ...

      function __get($id) { return $this->items[ $id ]; }

     function __set($id,$v) { $this->items[ $id ] = $v; }
      function parse() { ... }
    }
    $c = new Configuration();
    echo( $c->TemplateDirectory."\n" );
    $c->TemplateDirectory = 'foobar';
    echo( $c->TemplateDirectory."\n" );
    ?>

    现在,有了一个 __set 函数,它是 __get 函数的 “堂兄弟”。该函数并不为一个成员变量获取值,当要设置一个成员变量时,才调用这个函数。底部的测试代码设置值并打印出新值。

    下面是在命令行中运行此代码时出现的结果:

    % php text2.php
    tempdir
    foobar
    %

    太好了!但如何能将它存储到文件中,从而将使这个改动固定下来呢?为此,需要写文件并读取它。用于写文件的新函数,如下所示。

    清单 9. text3.php

    <?php
    class Configuration
    {
      ...

      function save()
      {
    $nf = '';
    $fh = fopen( $this->configFile, 'r' );
    while( $l = fgets( $fh ) )
    {
      if ( preg_match( '/^#/', $l ) == false )
      {
    preg_match( '/^(.*?)=(.*?)$/', $l, $found );
    $nf .= $found[1]."=".$this->items[$found[1]]."\n";
      }
      else
      {
    $nf .= $l;
      }
    }
    fclose( $fh );
    copy( $this->configFile, $this->configFile.'.bak' );
    $fh = fopen( $this->configFile, 'w' );
    fwrite( $fh, $nf );
    fclose( $fh );
      }
    }

    $c = new Configuration();
    echo( $c->TemplateDirectory."\n" );
    $c->TemplateDirectory = 'foobar';
    echo( $c->TemplateDirectory."\n" );
    $c->save();
    ?>

    新的 save 函数巧妙地操作 config.txt。我并没有仅用更新过的配置项重写文件(这样会移除掉注释),而是读取了这个文件并灵活地重写了 $items 数组中的内容。这样的话,就保留了文件中的注释。

    在命令行运行该脚本并输出文本配置文件中的内容,能够看到下列输出。

    清单 10. 保存函数输出

    %  php text3.php
    tempdir
    foobar
    % cat config.txt
    # My application's configuration file
    Title=My App
    TemplateDirectory=foobar
    %

    原始的 config.txt 文件现在被新值更新了。

0
相关文章