我正在使用php / mysql开发一个网站。
我有3个文件config.php
,utils.php
和member.php
。文件的代码如下,
config.php - $objPath->docrootlibs
很好,我相信这没问题。
/* Other library files & their object */
require($objPath->docrootlibs.'/utils.php');
$objUtils = new utils();
require($objPath->docrootlibs.'/member.php');
$objMember = new member();
utils.php中
class utils{
function getCurrentDateTimeForMySQL(){
return date("Y-m-d H:i:s");
}
}
members.php
class member{
var $userid;
var $username;
function __construct(){
$this->lastactivity = $objUtils->getCurrentDateTimeForMySQL();
}
}
现在当我在页面config.php
中包含home.php
简单的php include语句并运行该页面时,它会给我以下错误。
Notice: Undefined variable: objUtils in D:\wamp\www\site\libs\member.php on line 17
Fatal error: Call to a member function getCurrentDateTimeForMySQL() on a non-object in D:\wamp\www\site\libs\member.php on line 17
上面错误的行号不同,我只是从这里的代码中复制了特定的部分。
我不明白为什么会给出错误,因为在包含成员类之前,在配置页面上定义了utils类的对象。它应该检测到该对象。
请检查并帮助我理解并纠正此错误。
谢谢!
答案 0 :(得分:2)
正如另一条评论所述,使用依赖注入。将utilities实用程序对象插入构造函数中。不要在全局范围内引入变量,尤其是在不同文件之间。这变得非常混乱,并创建了一些文件包含的强制命令。
class member {
...
public function __construct(utils $objUtils) {
$this->objUtils = $objUtils;
...
}
}
在调用代码时:
$member = new member(new utils);
顺便说一句,我觉得很幽默,你的宏名称比其执行的操作更长。
另外,您需要一个实用工具类吗?实用程序可以只是功能吗?
答案 1 :(得分:2)
与JavaScript不同,PHP不会通过范围冒泡,这意味着
public function __construct(){
$this->lastactivity = $objUtils->getCurrentDateTimeForMySQL();
}
不知道$objUtils
是什么,因为在本地范围内没有定义这样的对象。这意味着,您必须在该范围内使对象可用。最干净,最易维护的方法是将utils实例注入成员实例,例如
public function __construct($utils){
$this->lastactivity = $utils->getCurrentDateTimeForMySQL();
}
但是,由于您似乎只在构造中使用该值,因此您的成员实例无需知道如何使用utils对象。那么为什么不直接从一开始就插入实际值,例如
public function __construct($lastActivity){
$this->lastactivity = $lastActivity;
}
// then do
$utils = new utils();
$member = new member($utils->getCurrentDateTimeForMySQL());
您肯定不想要使用global
关键字或static
方法。两人都回到了全球范围。这意味着您不能再使用没有全局范围的成员类。这使得维护,重用,重构和测试更加困难。 OOP是关于封装的,通过从类到全局范围,你打破了封装。请使用依赖注入,如上所示。
除此之外,使用全局变量也会使您的代码更难阅读。查看成员ctor签名的开发人员可能会认为除了调用new member
之外别无他法。这是谎言,因为她还必须设置utils实例。换句话说,您正在隐藏依赖项。开发人员必须查看实际代码以了解正在发生的事情。因此,明确依赖关系。
更多资源:
如果确实需要该utils对象,请注入实例并将其分配给ctor中成员实例内的属性。然后,您可以从成员实例内的任何其他位置使用$this->utils->foo()
访问它。
但是,实用程序类几乎总是设计糟糕的标志。它们更有可能被拆开并分成其他物体。试着找出可靠性。也许会员不应该使用Utils,但Utils应该是使用会员的其他东西。
出于好奇,为什么你还需要MySql的实用方法?如果在MySql中为lastActivity使用Timestamp列,则只要更新行,它就会自动更新。我假设您正在设置lastActivity,然后存储成员数据?
关于表现:你不应该担心表现。首先编写可读和可维护的代码。如果您认为自己的表现不够好,请使用XDebug对应用程序进行分析,看看究竟有什么影响。
答案 2 :(得分:0)
听起来config.php在全球范围内。使用$ objUtils时需要使用global关键字
function __construct(){
global $objUtils;
$this->lastactivity = $objUtils->getCurrentDateTimeForMySQL();
}
答案 3 :(得分:0)
由于你的getCurrentDateForMySQL不依赖于utils对象中的任何其他东西,为什么不把它变成静态函数呢?这样您就可以将member()方法转换为:
function __construct(){
$this->lastactivity = utils::getCurrentDateTimeForMySQL();
}