今天我有一个非常奇怪的类结构的PHP项目。像这样:
db_base
`-- db_base_ext extends db_base
+-- module_1 extends db_base_ext
+-- module_2 extends db_base_ext
. ...
+-- module_N extends db_base_ext
`-- db_user extends db_base_ext
class_1
`-- submodule_1_1 extends class_1
db_base
连接到__construct()
中的db,并有一些辅助方法。
执行的例子:
$db = new db_user();
$user = new user($db);
unset($db);
$db = new module_2();
我不喜欢在这段代码中我们连接到DB两次并且整个类结构不是很好。
我怎样才能让它变得更好?我的意思是只创建一个数据库实例,并在此工作之后使用任何类(对应于DB)?
单身人士模式会对此有好处吗?
答案 0 :(得分:4)
你的问题在于,你的结构,
module_2 extends db_base_ext
db_user extends db_base_ext
submodule_1_1 extends class_1
他们都破坏了Single Responsibility Principle和Liskov Substitution Principle。
我怎样才能让它变得更好。我的意思是只创建一个数据库实例 可以使用任何类(对应于DB)吗?
Dependency injection是要走的路。您将实例化一个数据库实例,并且您的所有类将共享相同的 $db
实例。
final class MySQLPDO extends PDO
{
public function __construct(array $params)
{
parent::__construct(sprintf('mysql: host=%s; dbname=%s', $params['host'], $params['database']), $params['username'], $params['password']);
$this->setAttribute(parent::MYSQL_ATTR_INIT_COMMAND, 'SET NAMES UTF8');
$this->setAttribute(parent::ATTR_ERRMODE, parent::ERRMODE_EXCEPTION);
$this->setAttribute(parent::ATTR_EMULATE_PREPARES, false);
$this->setAttribute(parent::ATTR_DEFAULT_FETCH_MODE, parent::FETCH_ASSOC);
}
}
$db = new MySQLPDO(array(
'host' => 'localhost',
'database' => 'foo',
'username' => 'root',
'password' => '',
));
$user = new User($db);
$module = new Module1($user);
$foo = new Foo($db);
那么,你会在这里获得什么?重用能力和测试能力。
注意,你应该避免使用Singleton,因为它们会引入另一种形式的全局状态,这对单元测试来说是不利的。
答案 1 :(得分:2)
首先,我注意到项目中的类被命名为函数。如果项目试图使用PEAR命名约定,它应该正确。
您应该从db_base_ext
类断开模块。如果模块需要访问数据库实例,则可以使用构造函数参数或setter提供。它不应该直接扩展类。
$module = new Module($database);
答案 2 :(得分:-2)
您应该考虑为数据库类使用单例模式。
Take a look here for a tutorial。 它使用PDO进行通信,但也应该对mysqli或其他类型有效。