设为首页 收藏本站
查看: 698|回复: 0

[经验分享] 在PHP中使用全局变量[2]

[复制链接]

尚未签到

发表于 2017-4-2 11:18:49 | 显示全部楼层 |阅读模式
PHP中使用全局变量【二】



第一部分

使用单件(Singletons

解决函数参数问题的一种方法就是采用单件(Singletons)来代替函数参数。单件是一类特殊的对象,它们只能实例化一次,而且含有一个静态方法来返回对象的接口。下面的例子演示了如何构建一个简单的单件:

<?php
//GetinstanceofDBConnection
$db=&DBConnection::getInstance();
//Setuserpropertyonobject
$db->user='sa';
//Setsecondvariable(whichpointstothesameinstance)
$second=&DBConnection::getInstance();
//Shouldprint'sa'
echo$second->user;
Class
DBConnection{
var
$user;
function&
getInstance(){
static
$me;
if(
is_object($me)==true){
return
$me;
}
$me=newDBConnection;
return
$me;
}
function
connect(){
//TODO
}
function
query(){
//TODO
}
}
?>

上面例子中最重要的部分是函数getInstance()。这个函数通过使用一个静态变量$me来返回这个类的实例,从而确保了只有一个DBConnection类的实例。
使用单件的好处就是我们不需要明确的传递一个对象,而是简单的使用getInstance()方法来获取到这个对象,就好像下面这样:


<?php
functiontest(){
$db=DBConnection::getInstance();
//Dosomethingwiththeobject
}
?>

然而使用单件也存在一系列的不足。首先,如果我们如何在一个类需要全局化多个对象呢?因为我们使用单件,所以这个不可能的(正如它的名字是单件一样)。另外一个问题,单件不能使用个体测试来测试的,而且这也是完全不可能的,除非你引入所有的堆栈,而这显然是你不想看到的。这也是为什么单件不是我们理想中的解决方法的主要原因。

注册模式

让一些对象能够被我们代码中所有的组件使用到(译者注:全局化对象或者数据)的最好的方法就是使用一个中央容器对象,用它来包含我们所有的对象。通常这种容器对象被人们称为一个注册器。它非常的灵活而且也非常的简单。一个简单的注册器对象就如下所示:

<?php
ClassRegistry{
var
$_objects=array();
function
set($name,&$object){
$this->_objects[$name]=&$object;
}
function&
get($name){
return
$this->_objects[$name];
}
}
?>

使用注册器对象的第一步就是使用方法set()来注册一个对象:

<?php
$db
=newDBConnection;
$settings=newSettings_XML;
$user=newUser;
//Registerobjects
$registry=&newRegistry;
$registry->set('db',$db);
$registry->set('settings',$settings);
$registry->set('user',$user);
?>

现在我们的寄存器对象容纳了我们所有的对象,我们指需要把这个注册器对象传递给一个函数(而不是分别传递三个对象)。看下面的例子:

<?php
functiontest(&$registry){
$db=&$registry->get('db');
$settings=&$registry->get('settings');
$user=&$registry->get('user');
//Dosomethingwiththeobjects
}
?>

注册器相比其他的方法来说,它的一个很大的改进就是当我们需要在我们的代码中新增加一个对象的时候,我们不再需要改变所有的东西(译者注:指程序中所有用到全局对象的代码),我们只需要在注册器里面新注册一个对象,然后它(译者注:新注册的对象)就立即可以在所有的组件中调用。
为了更加容易的使用注册器,我们把它的调用改成单件模式(译者注:不使用前面提到的函数传递)。因为在我们的程序中只需要使用一个注册器,所以单件模式使非常适合这种任务的。在注册器类里面增加一个新的方法,如下所示:

<?
function&getInstance(){
static
$me;
if(
is_object($me)==true){
return
$me;
}
$me=newRegistry;
return
$me;
}
?>

这样它就可以作为一个单件来使用,比如:

<?php
$db
=newDBConnection;
$settings=newSettings_XML;
$user=newUser;
//Registerobjects
$registry=&Registry::getInstance();
$registry->set('db',$db);
$registry->set('settings',$settings);
$registry->set('user',$user);
function
test(){
$registry=&Registry::getInstance();
$db=&$registry->get('db');
$settings=&$registry->get('settings');
$user=&$registry->get('user');
//Dosomethingwiththeobjects
}
?>

正如你看到的,我们不需要把私有的东西都传递到一个函数,也不需要使用“global”关键字。所以注册器模式是这个问题的理想解决方案,而且它非常的灵活。

请求封装器

虽然我们的注册器已经使“global”关键字完全多余了,在我们的代码中还是存在一种类型的全局变量:超级全局变量,比如变量$_POST,$_GET。虽然这些变量都非常标准,而且在你使用中也不会出什么问题,但是在某些情况下,你可能同样需要使用注册器来封装它们。
一个简单的解决方法就是写一个类来提供获取这些变量的接口。这通常被称为请求封装器,下面是一个简单的例子:

<?php
ClassRequest{
var
$_request=array();
function
Request(){
//Getrequestvariables
$this->_request=$_REQUEST;
}
function
get($name){
return
$this->_request[$name];
}
}
?>

上面的例子是一个简单的演示,当然在请求封装器(request wrapper)里面你还可以做很多其他的事情(比如:自动过滤数据,提供默认值等等)。
下面的代码演示了如何调用一个请求封装器:

<?php
$request
=newRequest;
//Registerobject
$registry=&Registry::getInstance();
$registry->set('request',&$request);
test();
function
test(){
$registry=&Registry::getInstance();
$request=&$registry->get('request');
//Printthe'name'querystring,normallyit'dbe$_GET['name']
echohtmlentities($request->get('name'));
}
?>
  
正如你看到的,现在我们不再依靠任何全局变量了,而且我们完全让这些函数远离了全局变量。

结论

在本文中,我们演示了如何从根本上移除代码中的全局变量,而相应的用合适的函数和变量来替代。注册模式是我最喜欢的设计模式之一,因为它是非常的灵活,而且它能够防止你的代码变得一塌糊涂。
另外,我推荐使用函数参数而不是单件模式来传递注册器对象。虽然使用单件更加轻松,但是它可能会在以后出现一些问题,而且使用函数参数来传递也更加容易被人理解。


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-359055-1-1.html 上篇帖子: PHP调用外部程序的方法 下篇帖子: 基于PCNTL的PHP并发编程
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表