【问题标题】:Programming best practice for PHP configuration class and dependent classesPHP 配置类和依赖类的编程最佳实践
【发布时间】:2018-03-10 19:54:23
【问题描述】:

我有机会重写我一年前编写的一个非常大的 PHP 应用程序,我正在寻找有关实现应用程序配置的想法的反馈。

目前我有一个配置类,它可以读取我的大量(并且非常易于阅读)config.php 文件,它让我可以轻松轻松地访问 PHP 代码中的配置参数。这个配置对象在我的_init.php 脚本中被实例化为一个变量。下面是一个简化的示例:

<?php
  class Configuration {
    public $someConfigProperty = true;
    public const someOtherConstant = false;
  }

  // _init.php
  $CONFIGURATION = new Configuration;
?>

这很好用,除了在每个其他类的每个方法中我必须将$CONFIGURATION 变量声明为全局变量。我想做的是让所有其他需要访问配置对象的类只扩展Configuration 类。像这样的:

<?php
  class Configuration {
    public $someConfigProperty = 'some string';
    public const someOtherConstant = false;
  }

  class Foo extends Configuration {
    public static function getConfigProperty() {
      return $this->someConfigProperty;
    }
  }
?>

我的问题是:这是一个坏主意,如果是,为什么?我正在寻找为什么不应该这样做的技术原因,或者担心将来的可维护性会使其成为一个坏主意。

【问题讨论】:

    标签: php class inheritance


    【解决方案1】:

    是的,这可能是个坏主意。一般来说,扩展其他类的类意味着一种专业化关系。经典示例包括Cat extends MammalSquare extends Rectangle。在这两种情况下,前者都是后者的专业化。所以除非Foo是一种特殊的配置,否则它不应该扩展Configuration

    你想要的是“依赖注入”。去谷歌上查询。同时,有一些不错的 PHP 类(如 this one)可以让您即时注入,如下所示:

    class Foo {
        public function __construct(Configuration $config) {
            echo $config->getConfigProperty();
        }
    }
    

    就像魔术一样,DI 库只需将配置对象合并到您的签名中,即可自动为您提供该配置对象。

    现在,这是进行 DI 的一种方式。还有其他的。谷歌“php依赖注入”,你会很好地了解不同的方法。

    【讨论】:

      【解决方案2】:

      我通常使用这样的模式,并且有各种配置文件,每个服务一个。此示例适用于 PostgreSQL:

      1.准备单独的环境文件

      为应用程序运行的每个环境创建一个文件,但将其命名为通用名称,例如 config.local.php。要么将该文件永久放置在服务器上,要么在部署期间从不可访问的环境文件夹复制到相关位置到常规配置文件夹(使用钩子/部署后脚本等)。文件格式可能如下所示:

      define("POSTGRESQL_DATABASE", "mydatabasename");
      define("POSTGRESQL_USERNAME", "myusername");
      define("POSTGRESQL_PASSWORD", "itsasecret");
      define("POSTGRESQL_SERVER_IP", "localhost");
      

      例如你可能有这样的文件夹结构:

      -config
      -environments
        -test
          -config
        -prod
          -config
      -public_html
      

      ...并在部署后挂钩中将/environments/prod/config/ 的内容复制到/config/

      理想情况下,您应该将配置文件排除在主源代码控制之外,而是在每台服务器上单独创建它们(也许从单独的安全存储库中复制它们?)

      此文件将在您的初始化过程中从/config/ 包含进来。

      2。创建一个使用这些常量的配置类

      创建包含配置变量的配置类,setter 是私有的(并在构造函数中调用),getter 是公共的。

      class PostgreSQLDatabaseConfiguration
      {
          private $databaseName = null;
          private $password = null;
          private $serverIP = null;
          private $username = null;
          #endregion
      
          #region Public methods
          final public function __construct($serverIP, $databaseName, $username, $password) {
              $this
                  ->setServerIP($serverIP)
                  ->setDatabaseName($databaseName)
                  ->setUsername($username)
                  ->setPassword($password);
          }
      
          /**
           * @return string
           */
          public function getDatabaseName() {
              return $this->databaseName;
          }
      
          public function getPassword() {
              return $this->password;
          }
      
          public function getServerIP() {
              return $this->serverIP;
          }
      
          public function getUsername() {
              return $this->username;
          }
          #endregion
      
          #region Private methods
          private function setDatabaseName($databaseName) {
              $this->databaseName = $databaseName;
              return $this;
          }
      
          private function setPassword($password) {
              $this->password = $password;
              return $this;
          }
      
          private function setServerIP($serverIP) {
              $this->serverIP = $serverIP;
              return $this;
          }
      
          private function setUsername($username) {
              $this->username = $username;
              return $this;
          }
          #endregion
      }
      

      3.拥有一个生成配置类的通用配置文件

      此文件对所有环境都是通用的(即构成标准部署的一部分),并将使用上一步中定义的常量实例化配置对象:

      include('/config/config.local.php');    
      $postgresqlDatabaseConfiguration = new PostgreSQLDatabaseConfiguration(
          POSTGRESQL_SERVER_IP,
          POSTGRESQL_DATABASE,
          POSTGRESQL_USERNAME,
          POSTGRESQL_PASSWORD
      );
      

      您的配置对象现在已准备好注入您的 DatabaseAccessor 类,并且您的主要代码库与环境无关。

      【讨论】:

        【解决方案3】:

        没有解释为什么需要类来传播常量。
        直接在应用程序中使用定义对我来说看起来更简单。
        例如:

        PostgreSQLDatabaseConfiguration::getDatabaseName()
        

        可以简单地被它的定义引用:

        POSTGRESQL_DATABASE
        

        使用后一种方法,您只需将带有定义的文件复制到目标环境。
        编程是让事情尽可能简单的艺术。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-08-13
          • 1970-01-01
          • 2011-06-11
          • 2010-12-11
          • 2012-10-09
          • 2011-10-15
          • 1970-01-01
          相关资源
          最近更新 更多