解析PHP中使用全局变量的几种方法
即使你有了一个新的大型PHP程序,你将不可避免地要使用全局数据,因为有些数据需要使用您的代码的不同部分。一些常见的全球数据:程序设置类,数据库连接类,用户数据等等。有许多方法可以使这些数据的全局数据,最常用的是用全球的关键字来声明,稍后我们将详细解释这篇文章。
使用全局关键字来声明全局数据的唯一的缺点是,它实际上是一个很差的编程方式,往往导致在节目之后更大的问题,因为全球数据原本独立的代码在您的代码都放在一起,这样的后果是:如果你改变了其中的一部分代码,可能会导致其他部分,所以如果你在你的代码中有很多的全局变量,你的整个计划势必难以维持。
本文将展示如何通过不同的技术或设计模式来防止这个全局变量问题。当然,让我们先看看如何使用全局关键字来处理全局数据,以及它是如何工作的。
使用全局变量和全局关键字
PHP中定义了一些超级全局变量(superglobals)默认。这些变量是自动国际化,可以调用程序中的任何地方,如_get美元美元和_request.they通常来自数据或其他外部数据,并使用这些变量通常是没有问题的,因为它们本质上是不可写的。
但是您可以使用自己的全局变量。使用关键字全局,您可以将全局数据导入函数的局部范围。如果您不了解变量的范围,请参阅PHP手册中的相关说明。
下面是使用全局关键字的演示示例:
复制代码代码如下所示:
< PHP
my_var美元=你好世界;
test_global();
功能test_global(){
在本地作用域中/现在
my_var美元变量不存在 / /
Undefined variable: my_var error: / / Produces
echo $ my_var;
让我们重要的变量
全球my_var美元;
工程:
echo $ my_var;
}
>
正如您在上面的示例中所看到的,使用全局关键字导入全局变量。它似乎工作得很好,而且非常简单,为什么我们要担心使用全局关键字来定义全局数据呢
这里有三个充分的理由:
1。代码重用几乎是不可能的。
如果一个函数依赖于一个全局变量,那么在另一个环境中使用这个函数几乎是不可能的。另一个问题是,你不能提取这个函数,然后在其他代码中使用它。
2,调试和解决这个问题非常困难。
跟踪一个全局变量比跟踪一个非全局变量要困难得多,在一些不明显的包含文件中,可以重新定义全局变量。即使你有一个很好的程序编辑器(或IDE)来帮助你,你也需要几个小时才能发现这个问题。
三.要理解代码是非常困难的。
很难找到一个全局变量来自何处,以及它是用来做什么的。在开发过程中,您可能知道每个全局变量都是已知的,但是一年左右之后,您可能会忘记至少所有的一般变量。你会后悔在这个时候使用了这么多全局变量。
如果不使用全局变量,我们应该使用什么让我们来看看一些解决方案。
使用函数参数
停止使用全局变量的一种方法是将变量作为参数传递给函数,如下所示。
复制代码代码如下所示:
< PHP
$ var =你好世界;
测试(var);
函数测试($ var){
回波变量;
}
>
如果只需要传递一个全局变量,那么这是一个非常优秀甚至优秀的解决方案。但是,如果你想传递许多价值观,你会怎么做
例如,如果我们想使用一个数据库类、一个程序设置类和一个用户类,在我们的代码中,这三个类在所有组件中都被使用,所以它必须传递给每个组件:
复制代码代码如下所示:
< PHP
$ db =新类;
设置新的settings_xml美元=;
用户=新用户;
测试($ DB,$设置,$用户);
函数测试($ db,$设置,$用户){
做某事
}
>
显然,这是不值得的,一旦我们有了一个新的对象加入,我们必须为每个函数添加一个函数参数,所以我们需要用另一种方法来解决它。
用单块的方法之一(单身)解决函数参数的问题是使用单块(单身)代替函数参数。一块是一个特殊的类,只能实例化一次对象,就返回对象的接口的静态方法。下面的例子显示了如何建立一个简单的单块:
复制代码代码如下所示:
< PHP
类 / /实例的获取
$ db = DbConnection::getInstance();
对象集上的用户属性
为数据库->用户= 'sa;
第二个变量集(指向同一个实例)
第二类:美元=:getInstance();
print'sa ' / /应
第二个用户;
{类类
var用户;
函数getInstance(){
静态$我;
如果(is_object(为我)= = true){
还我;
}
$我=新类;
还我;
}
函数连接(){
}
函数查询(){
}
}
>
上述例子中最重要的部分是函数getInstance(),这个函数返回一个类的实例,通过使用一个静态变量,为我,为了确保只有一个类的实例的类。
利用单身的好处是,我们不需要显式传递的对象,而是使用getInstance()得到这个对象的方法。
复制代码代码如下所示:
< PHP
函数测试(){
$ db = DbConnection::getInstance();
用对象做某事
}
>
然而,也有在单块使用一系列缺点。首先,如果我们需要全球化的多个对象在一个班吗因为我们使用一个单件,所以这是不可能的(就像它的名字是单件)。另一个问题是单件测试不能通过个别测试来测试,除非你介绍所有显然不想看到的堆栈,否则完全不可能。这也是为什么单件不是我们理想的解决方案的主要原因。
登记模式
让我们的代码中的所有组件使用某些对象的最好方法是使用一个中央容器对象来使用它来包含我们所有的对象。通常这个容器对象称为注册器。它非常灵活而且非常简单:
复制代码代码如下所示:
< PHP
类{注册表
VaR _objects美元=阵();
函数集($名称,对象){
美元-> _objects {姓名} = $ $对象;
}
函数获取($ name){
返回这个-> _objects { $名称};
}
}
>
使用寄存器对象的第一步是使用方法集()注册对象:
复制代码代码如下所示:
< PHP
$ db =新类;
设置新的settings_xml美元=;
用户=新用户;
寄存器对象
注册表=新注册表;
$注册->设置('db,$分贝);
$注册->设置('settings美元,设置);
$注册->设置(用户,为用户);
>
现在我们的寄存器对象保存了所有的对象。我们的意思是,我们需要将这个寄存器对象转移到一个函数,而不是单独传递三个对象:
复制代码代码如下所示:
< PHP
函数测试(注册表){
分贝=美元美元注册表->得到('db);
设置注册表->美元=美元获得('settings);
用户注册->美元=美元获得(用户的);
用对象做某事
}
>
将注册与其他方法进行比较,这是一个很大的改进,当我们需要添加到一个对象中的代码时,我们不再需要更改所有内容(译者注:指在程序代码中使用所有全局对象),我们只需要注册一个新的注册。一个对象,然后它(译者注:新对象注册)立即可以调用所有组件。
为了使注册器更容易使用,我们将其调用改为单一模式。因为在我们的程序中只需要一个注册器,单模式就非常适合这个任务:
复制代码代码如下所示:
<
函数getInstance(){
静为我;
如果(is_object(为我)= = true){
还我;
}
$ =新注册表;
还我;
}
>
因此,它可以作为一个单件使用,例如:
复制代码代码如下所示:
< PHP
$ db =新类;
设置新的settings_xml美元=;
用户=新用户;
寄存器对象
注册表注册表:美元=:getInstance();
$注册->设置('db,$分贝);
$注册->设置('settings美元,设置);
$注册->设置(用户,为用户);
函数测试(){
注册表注册表:美元=:getInstance();
分贝=美元美元注册表->得到('db);
设置注册表->美元=美元获得('settings);
用户注册->美元=美元获得(用户的);
用对象做某事
}
>
正如您所看到的,我们不需要将所有私有的东西传递给函数,也不需要使用全局关键字,因此注册模式是解决这个问题的理想方法,而且它非常灵活。
请求包装
虽然我们的注册表使全球关键词冗余,我们的代码的一个全局变量:超级全局变量,如变量_post美元,美元_get.although这些变量是非常标准的,也会在你的使用是没有问题的,但在某些情况下,您可能还需要使用寄存器来封装它们。
一个简单的解决方案是编写一个类来提供一个接口来获取这些变量,这通常称为请求包装器,下面是一个简单的示例:
复制代码代码如下所示:
< PHP
{请求类
VaR _request美元=阵();
函数请求(){
请求变量
美元-> _request = $ _request;
}
函数获取($ name){
返回这个-> _request { $名称};
}
}
>
上面的例子是一个简单的演示。当然,在请求包装器(请求包装器)中还可以做许多其他的事情,比如自动过滤数据、提供默认值等。
下面的代码演示如何调用请求包装器:
复制代码代码如下所示:
< PHP
$请求=新请求;
寄存器对象
注册表注册表:美元=:getInstance();
$注册->设置(请求,要求美元);
测试();
函数测试(){
注册表注册表:美元=:getInstance();
要求美元=美元注册->得到(请求的);
the'name ' / /打印查询通常会为_get { 'name' }
回声htmlentities($请求->得到('name'));
}
>
正如你所看到的,现在我们不依赖于任何全局变量,并且我们完全保持这些函数远离全局变量。
结论
在本文中,我们演示了如何从代码中彻底删除全局变量,并用适当的函数和变量替换它们。注册模型是我最喜欢的设计模式之一,因为它非常灵活,并且可以防止代码陷入混乱。
此外,我建议使用函数参数而不是单模式来传递寄存器对象,虽然使用一块比较容易,但它将来可能会有一些问题,并且更容易理解函数参数的用法。