1

我在优化我的 PHP 脚本时遇到问题。例如:

一个 MySQL 表:

    选项名称 || 选项值
    ==================================================== ===
    基本网址 || http://mysite.com/myproject
    主题名 || 默认
    语言 || zh

MyScript.php 文件:

class options {
  private $options = null;
  public function get($optionName) {
    if(!isset($this->options))
        self::get_data();
    return $this->options[$optionName];
  }
  protected function get_Data() {
    // ...
    // DO A MYSQL QUERY AND SAVE IT TO $this->options
    // ...
  }
}

该类返回的数据是常量。因此,每次我需要访问例如base_url值时,都不需要运行 MySQL 查询。创建对象并在全局范围内使用它的最佳方法是什么?

$OPTIONS = new options;
function load_option($optName) {
  global $OPTIONS;
  return $OPTIONS->get($optName);
}

也许像这个功能?有人说这是最糟糕的方法

我需要帮助。谢谢!

4

2 回答 2

1

您的问题是您不了解 SOLID 和 DI 原则是什么。您应该实现为每个单一职责服务的类,然后按需注入它们的实例。

在你的情况下,它看起来像这样,

class Config
{
    protected $pdo;

    protected $cache;

    public function __construct($pdo)
    {
       $this->pdo = $pdo;
    }

    public function read($key)
    {
        // Read a value by its key from a table
        // Here should be a SELECT query

        // You can also prevent reading the same thing twice
        // by storing it in a cache
    }

    public function write(array $data)
    {
        foreach ($data as $key => $value) {

            // Here should be INSERT statement
        }
    }

    public function delete($key)
    {
         // Here comes a DELETE statement
    }
}

每次需要读取配置值时,只需将 的实例注入Config需要它的类即可。

class Foo
{
     protected $config;

     public function __construct(Config $config)
     {
         $this->config = $config;
     }

     public function doSomethingDependingOnConfig()
     {
         if ($this->config->read('lang') === 'en') {
            // do something
         }
     }
}

你会像这样使用它,

$pdo = new PDO(...);

$config = new Config($pdo);

// Test
echo $config->read('lang'); //en

// So,
$foo = new Foo($config);

$foo->doSomethingDependingOnConfig();
于 2013-08-04T18:52:55.917 回答
0

事实上,我不认为这是最糟糕的方式。

许多配置设置不需要存储在数据库中。有些甚至不能(例如数据库的地址和凭据)。

所以很明显,一些硬编码的配置很方便。如果您调查现有的 PHP 应用程序,您会发现它们中的大多数都有一些全局可配置的选项。

全局变量的缺点是它非常严格并且很难改变它的用法。很快您就会发现自己在整个应用程序中都在使用这个全局变量。

但是您已经通过将对它的访问包装在一个函数中来反驳这一点,因此您可以在以后轻松更改选项,而无需更改整个应用程序。通过制作这个包装函数,您已经隐藏了选项的存储方式。如果您愿意,您仍然可以从数据库中获取它们,或者开始将它们存储在文件中,因为您需要更改的只是这个函数。所以这实际上是一个很好的解决方案。

您可以做一件事来改进此代码:

也许您可以将它包装在 Config 单例类中。这样做的好处是,您实际上也可以将配置存储在该类中,摆脱全局变量,从而摆脱对该全局变量的意外访问。您将强迫自己始终使用函数/类访问选项。

于 2013-08-04T07:54:17.917 回答