联系电话:0755-27515592
最新动态:

Magento教程

Magento的全局变量设计模式

点击数:9942015-07-29 15:51:59 来源: 外贸网站建设,深圳外贸网站建设,深圳网站建设,外贸商城网站制作-亿恩科技

新闻摘要:PHP中,变量有全局的概念,比如$_GET $_POST等数组中保存的值都是全局的,如果直接使用一个变量,那么它也是全局可用的,如果在函数中使用global关键字声明一个变量,那这个函数就可以使用

PHP中,变量有全局的概念,比如$_GET $_POST等数组中保存的值都是全局的,如果直接使用一个变量,那么它也是全局可用的,如果在函数中使用global关键字声明一个变量,那这个函数就可以使用来自外部的这个变量值,函数中的这个变量值还可以从函数带出到外部,所有直接声明的变量或用global关键字声明的变量,实际上全部注册到$GLOBALS数组中。比如声明了$var,当要引用这个变量时可以直接用$var或$GLOBALS['var']。这种搞法其实已经非常怪异了,不过还有更加怪异的,比如$_GET['name'],你可能可以使用$name直接引用或用$GLOBALS['name']来引用这个变量(具体决定于PHP的配置,不过一般都是关闭的了)。 这些诡异的用法是PHP的历史原因导致的。不过作为一个PHP程序员,仍然需要知道这个。
这里的全局变量的使用有很大风险,比如我声明了一个$var,然后在其它地方再次声明一个同名的$var,那么后面的将悄悄覆盖前面的。更加糟糕的是,如果这个变量引用一个对象,但是由于一些第三方代码的引入,也声明了一个同名的变量,那么这个变量在其它地方调用方法时将出现错误,这个问题很令人烦恼。所以我们得到的教训是:慎用全局变量。
以上说得情况在面向过程的代码中中,尤为明显。由于这个问题,全局变量设计模式就产生了。以下主要探讨Magento中的全局设计模式和单态设计模式。
Magento中使用如下方法实现了全局设计模式:
Mage::register
Mage::unregister  
Mage::registry
分别对应注册 和 注销 和 获取全局变量。首先看看注册一个全局变量时发生了什么事情:
public static function register($key, $value, $graceful = false)
{
    if (isset(self::$_registry[$key])) {
        if ($graceful) {
            return;
        }
        self::throwException('Mage registry key "'.$key.'" already exists');
    }
    self::$_registry[$key] = $value;
}
首先检查$key是否存在$_registry数组中,如果存在就根据$graceful的设置,返回空或者抛出异常。如果不存在就直接赋值。可见,一个变量注册了,就不能再注册一个同名的变量了,这个很好解决了变量被覆盖的威胁。但是还是有不足,因为程序员可以先调用unregister来注销变量,然后设置自己的变量:
public static function unregister($key)
{
    if (isset(self::$_registry[$key])) {
        if (is_object(self::$_registry[$key]) && (method_exists(self::$_registry[$key], '__destruct'))) {
            self::$_registry[$key]->__destruct();
        }
        unset(self::$_registry[$key]);
    }
}
注销全局变量时如果全局变量是对象并且设置了__destruct析构函数,那么直接调用它的析构函数释放资源。否则就是简单unset,这个就依赖PHP的垃圾回收器来回收了。
当想要获取这个全局变量时,直接调用registry,可以把它看做是注册表:
public static function registry($key)
{
    if (isset(self::$_registry[$key])) {
        return self::$_registry[$key];
    }
    return null;
}
Magento内核高度使用这个模式,我们知道Magento中的控制器并不会直接和视图交互,真正和视图交互的是Block,控制器中只要使用renderLayout就可以获取输出:
1
2
3
$this->loadLayout();
$this->getLayout()->getBlock('content')->setSomeVar($var);
$this->renderLayout();
我们可以在控制器中添加:
Mage::register('product', $product);
一个Block中可能包含如下方法:
public function getProduct()
{
    return Mage::registry('product');
}
这样就可以在视图中使用:
echo $this->getProduct()->getName();
Magento中的单态设计模式(Singleton Pattern)
获取一个对象的一份单态实例:
Mage::getSingleton('group/class');
过多解释在面对代码时非常苍白,所以我们这里直接看看这个方法的实现:
#File: app/Mage.php
public static function getSingleton($modelClass='', array $arguments=array())
{
    $registryKey = '_singleton/'.$modelClass;
    if (!self::registry($registryKey)) {
        self::register($registryKey, self::getModel($modelClass, $arguments));
    }
    return self::registry($registryKey);
}
它使用’_singleton/’.$modelClass组建名字,然后调用register把getModel()返回的实例记录到注册表中,你可以看到,如果这个名称对应的值存在了,直接就放回这个实例,就是这样保证了全局唯一(看起来不是严格的单态模式,因为可以unregister)。这个封装另一个模式来实现的别的设计模式,也算是一个亮点吧。不过一般单态设计模式是控制类的构造函数来保证的,常见的使用方法是:
1
$bar = Object_Type::getInstance();
可是Magento中并没有采用这种方式。尽管可以unregister,但是它的灵活性也体现出来了。
【责任编辑:(Top) 返回页面顶端
贴心
全国7×24小时客服热线
安全
病毒杀除率高于99%
稳定
网站可用性高于99.9%
实力
服务68家上市企业及集团公司
亿恩科技手机站
关注亿恩科技微信

亿恩科技—企业信息化一站式服务专家


Copyright © 2008- 深圳市亿恩科技有限公司版权所有 粤ICP备15056041号

联系我们 | 常见问题 | 在线留言 | 支付方式 | 软件开发 | 我的观点 | 资质荣誉 | 服务流程