所以我遇到了PHP类的“问题”。
我有一些需要彼此功能的类,所以目前我正在做以下事情:
$db = new blueConnect;
$core = new blueCore($db);
$users = new blueUsers($db, $core);
然后在文件中:
public function __construct(blueConnect $db, blueCore $core) {
$this->db = $db;
$this->core = $core;
}
但是,不是为每个需要附加功能的文件执行此操作,而是编写
更好global $db, $core
在每个需要它的函数中?
答案 0 :(得分:3)
您所谈论的模式的名称简称为“依赖注入”或 DI 。
根据您的项目使用全局可能会在短期内解决问题,但如果您计划创建一个大项目,您稍后将测试并与多人共享,您希望避免使用全局。 - 你无法测试或调试那些东西。
(坏)解决方案是让您的数据库和核心类使用 Singleton Pattern 来避免全局但具有相同的效果。 (不可测试,不可配置)
public function __construct() {
$this->db = blueConnect::getInstance();
$this->core = blueCore::getInstance();
}
解决方案通常是创建工厂功能,以创建需要数据库和核心的所有服务。
public function createService($name) {
$serviceClass = 'blue'.ucfirst($name).'Service';
return new $serviceClass($this->getDatabase(), $this->getCore());
}
此功能通常是注册表的一部分或更好的 DI容器,例如PIMPLE
每个服务只有一个实例的示例:
public function createService($name) {
$serviceClass = 'blue'.ucfirst($name).'Service';
static $services = array();
if(!isset($services[$name])) {
$services[$name] = new $serviceClass($this->getDatabase(), $this->getCore());
}
return $services[$name];
}
请注意,由于容器内部存在“全局”状态,因此不应使用Registry / DI容器进行测试。 (例如,两次获取相同的服务)
答案 1 :(得分:2)
我不会使用全局变量。
理由:
这不是OOP方式。
难以调试。
生成的代码不可测试。如果您希望单元测试涵盖您的应用程序,您应该像现在一样使用Dependcy Injection。我会试着简要解释一下原因。正如其名称所暗示的单元测试就是:测试应用程序的单个单元,即您的类(它们的public
方法)。
现在让我们假设您使用在应用中的某个位置设置的全局变量。您将无法将blueUsers
类作为独立单元进行测试,因为您需要实例化$db
和$core
对象。因此,您将无法仅包含blueUsers.php
文件并测试该类,因为您将需要应用程序的其他部分(定义全局变量$db
和$core
的那些部分)。
另一方面,如果您使用Dependcy Injection,则不会遇到这样的问题。为了测试blueUsers
类,您需要做的唯一事情就是包括类,创建依赖项$db
和$core
的模拟,并将它们传递给{ {1}}构造函数。
这是一个很好的source,有关如何编写可测试和可维护代码的更详细说明。
here您可以找到有关模拟的更多信息,以及使用它是否以及您可以从中受益。
答案 2 :(得分:1)
我使用单线来包含全局对象。它可以被其他对象轻松访问,并且可以安全地访问这些变量:
final class GlobalObjects
{
public static function Instance()
{
static $inst = null;
if ($inst === null) {
$inst = new GlobalObjects();
}
return $inst;
}
private function __construct() {
$db = new blueConnect;
$core = new blueCore($db);
}
public function getDb() { return $this->db; }
public function getCore() { return $this->core; }
}
// ...
public function __construct() {
$this->db = GlobalObjects::Instance()->getDb();
$this->core = GlobalObjects::Instance()->getCore();
}
我想到的另一种方法,一种更简单,更脏的方法是:由于这些变量是全局对象,因此可能值得将它们定义为常量以避免错误:
define( "db", new blueConnect );
define( "core", new blueCore($db) );
$users = new blueUsers($db, $core);
然后
public function __construct() {
global $db, $core;
$this->db = $db;
$this->core = $core;
}
答案 3 :(得分:0)
如果参数是动态和可变的,您应该在构造函数中传递它们,因此新的<div id="json"></div>
<script>
var obj = {"data": [
{
"name": "Rehan",
"location": "Pune",
"description": "hello hi",
"created_by": 13692,
"users_name": "xyz",
},
{
"name": "Sameer",
"location": "Bangalore",
"description": "how are you",
"created_by": 13543,
"users_name": "abc",
}
]}
var divId = document.getElementById("json")
for(var i=0;i<obj.data.length;i++)
for(var keys in obj.data[i]){
console.log(keys +"-->"+obj.data[i][keys]);
divId.innerHTML = divId.innerHTML + "<br/>"+ keys +"-->"+obj.data[i][keys];
}
</script>
更好。但是如果这些是静态参数,并且在初始化类时不需要传递它们,则应该定义为全局。