PHP配置类和依赖类的编程最佳实践

时间:2017-09-28 23:52:39

标签: php class inheritance

我有机会重写一年前写的非常大的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;
    }
  }
?>

我的问题是:这是一个坏主意,如果是这样,为什么?我正在寻找技术上的原因,为什么不应该这样做,或者担心未来的可维护性会让这个想法变得糟糕。

3 个答案:

答案 0 :(得分:2)

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

这里你想要的是“依赖注入”。谷歌一下。同时,有一些不错的PHP类(如this one)可以为您提供即时注入,如下所示:

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

与魔术一样,DI库只需将其合并到您的签名中即可自动使用该配置对象。

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

答案 1 :(得分:0)

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

<强> 1。准备个人环境文件

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

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

e.g。你可能有这样的文件夹结构:

-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。有一个生成配置类的Common Config文件

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

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

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

答案 2 :(得分:0)

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

PostgreSQLDatabaseConfiguration::getDatabaseName()

可以通过其定义简单地引用它:

POSTGRESQL_DATABASE

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