`

PHP架构之注册表

阅读更多

啥是注册表模式?其实很简单!

注册表的作用是提供系统级别的对象访问功能。我们在编码时通常把“全局变量是不好的”当做信条。不过,凡事都有两面性,全局性的数据访问非常具有吸引力。

 

问题来了:

大多系统都分为几个层,每个层都只通过事先定义好的通道和相邻的层交流。对层的分享使程序变得灵活,替换或修改每个层可以最小化对系统其他部分的影响。但当你需要在一个层中获取不相邻另一个层所需要的信息时,该如何?

 

方案一:通过系统的层之间的联系将上下文信息从一个对象传递给另一个需要的对象:在系统中把这些信息从一个对象传递到另一个对象,从一个负责处理请求的控制器对象传递到业务逻辑层的对象,再传递到负责和数据库对话的对象。当然还可以传递ApplicationHelper对象,或者是一个特定的Context对象。

 

方案二:必须修改所有对象的接口,判断上下文对象是否是它们需要的。很显然,有时候这种方案会破坏松散耦合。

 

方案三:通过注册表模式。注册表类提供静态方法(或单例对象的实例化方法)来让其他对象访问其中的数据(通常是对象)。整个系统中的每个对象都可以访问这些数据对象。

 

在实现之前先考虑一下PHP的作用域:

作用域通常用于描述代码中对象或值的可见程序,变量的生命周期可以用时间来衡量,变量作用域有3个级别。

一、HTTP请求作用域

指一个HTTP请求从开始到结束的周期。

二、会话作用域

PHP内置了对会话变量的支持。在一次请求结束后,会话变量会被序列化并存储到文件系统或者数据库中,然后在下一个请求开始时取回。存放在cookie中的会话ID和通过查询字符串传递的会话ID被用于跟踪该会话的拥有者。因此,你可以认为某些变量拥有会话级别的作用域。利用这一点,可以在几次请求之间存放对象,保存用户访问的踪迹到数据库中。当然,要小心避免持有同一个对象的不同版本,因此当你把一个会话对象存到数据库时,需要考虑使用一定的锁定策略。

三、应用程序作用域

在其他语言中,特别是JAVA,拥有缓存池,即“应用程序作用域”的概念。内存中的变量可以被程序中的所有对象实例访问。PHP没有这样的功能,但是在大规模的应用中,为了访问配置变量,访问应用程序级别的数据是很有用的。

 

下面就用注册表实现这三个作用域,类图如下:



<?php
namespace woo\base;

require_once( "woo/controller/AppController.php");

abstract class Registry {

    abstract protected function get( $key );
    abstract protected function set( $key, $val );
}

class RequestRegistry extends Registry {
    private $values = array();
    private static $instance;

    private function __construct() {}
    static function instance() {
        if ( ! isset(self::$instance) ) { self::$instance = new self(); }
        return self::$instance;
    }

    protected function get( $key ) {
        if ( isset( $this->values[$key] ) ) {
            return $this->values[$key];
        }
        return null;
    }

    protected function set( $key, $val ) {
        $this->values[$key] = $val;
    }

    static function getRequest() {
        return self::instance()->get('request');
    }

    static function setRequest( \woo\controller\Request $request ) {
        return self::instance()->set('request', $request );
    }

}

class SessionRegistry extends Registry {
    private static $instance;
    private function __construct() {
        session_start();
    }

    static function instance() {
        if ( ! isset(self::$instance) ) { self::$instance = new self(); }
        return self::$instance;
    }

    protected function get( $key ) {
        if ( isset( $_SESSION[__CLASS__][$key] ) ) {
            return $_SESSION[__CLASS__][$key];
        }
        return null;
    }

    protected function set( $key, $val ) {
        $_SESSION[__CLASS__][$key] = $val;
    }

    function setComplex( Complex $complex ) {
        self::instance()->set('complex', $complex);
    }

    function getComplex( ) {
        return self::instance()->get('complex');
    }
}

class ApplicationRegistry extends Registry {
    private static $instance;
    private $freezedir = "/tmp/data";
    private $values = array();
    private $mtimes = array();

    private function __construct() { }

    static function instance() {
        if ( ! isset(self::$instance) ) { self::$instance = new self(); }
        return self::$instance;
    }

    protected function get( $key ) {
        $path = $this->freezedir . DIRECTORY_SEPARATOR . $key;
        if ( file_exists( $path ) ) {
            clearstatcache();
            $mtime=filemtime( $path );
            if ( ! isset($this->mtimes[$key] ) ) { $this->mtimes[$key]=0; }
            if ( $mtime > $this->mtimes[$key] ) {
                $data = file_get_contents( $path );
                $this->mtimes[$key]=$mtime;
                return ($this->values[$key]=unserialize( $data ));
            }
        }
        if ( isset( $this->values[$key] ) ) {
            return $this->values[$key];
        }
        return null;
    }

    protected function set( $key, $val ) {
        $this->values[$key] = $val;
        $path = $this->freezedir . DIRECTORY_SEPARATOR . $key;
        file_put_contents( $path, serialize( $val ) );
        $this->mtimes[$key]=time();
    }

    static function getDSN() {
        return self::instance()->get('dsn');
    }

    static function setDSN( $dsn ) {
        return self::instance()->set('dsn', $dsn);
    }

    static function setControllerMap( \woo\controller\ControllerMap $map  ) {
        self::instance()->set( 'cmap', $map );
    }

    static function getControllerMap() {
        return self::instance()->get( 'cmap' );
    }

    static function appController() {
        $obj = self::instance();
        if ( ! isset( $obj->appController ) ) {
            $cmap = $obj->getControllerMap();
            $obj->appController = new \woo\controller\AppController( $cmap );
        }
        return $obj->appController;
    }
}

//如果你安装了PHP的shm扩展,就可以使用该扩展中函数来实现应用程序注册表
class MemApplicationRegistry extends Registry {
    private static $instance;
    private $values=array();
    private $id;
    const DSN=1;

    private function __construct() {
        $this->id = @shm_attach(55, 10000, 0600);
        if ( ! $this->id ) {
            throw new Exception("could not access shared memory");
        }
    }

    static function instance() {
        if ( ! isset(self::$instance) ) { self::$instance = new self(); }
        return self::$instance;
    }

    protected function get( $key ) {
        return shm_get_var( $this->id, $key );
    }

    protected function set( $key, $val ) {
        return shm_put_var( $this->id, $key, $val );
    }

    static function getDSN() {
        return self::instance()->get(self::DSN);
    }

    static function setDSN( $dsn ) {
        return self::instance()->set(self::DSN, $dsn);
    }

}
?>

 

 

 

  • 大小: 10.9 KB
2
0
分享到:
评论
3 楼 fnet 2014-06-20  
Yanghisun 写道
感觉完全木有意义。放到注册表,成千上万个用户怎么办?把注册表拖死?
还是用memcache吧。


他的好处是对公共对象、数据的集中管理,减少多次对象创建、读写。

注册表模式广泛的运用于各种PHP框架中,这是非常常见且优良的设计。
2 楼 home198979 2014-06-10  
Yanghisun 写道
感觉完全木有意义。放到注册表,成千上万个用户怎么办?把注册表拖死?
还是用memcache吧。

注册表本身不应该放过多的数据,注册表模式是放代码配置相关的数据,而不是业务的数据,因此也不会过多。然后你说用memcache,是可以的,只是另一种实现方式,都是起的缓冲池的作用,我代码是用文件来存储和shm扩展,具体应该用哪种方案当依情况而定。
1 楼 Yanghisun 2014-06-10  
感觉完全木有意义。放到注册表,成千上万个用户怎么办?把注册表拖死?
还是用memcache吧。

相关推荐

    UPUPW PHP v5.2.17 经典怀旧版套装 c1.zip

    2、可运行于任意版本任何架构的Windows系统之上(Windows Server 2003/2008/2012 ; XP/Vista/Win7/Win8 ; 32/64位) ;  3、无目录限制,任意磁盘任何非中文不含空格目录想放哪就放哪。 4、完全兼容IIS,独具代理...

    avro-serde-php:具有Symfony Serializer集成PHP 7.3+和8.0的Avro SerialisationDeserialisation(SerDe)库

    适用于PHP 7.3+和8.0的Avro SerDe动机在使用序列化格式对消息进行序列化和反序列化时,尤其是在与集成时,您需要... composer require ' flix-tech/avro-serde-php:^1.6 '快速开始注意您应该始终使用缓存的架构注册表客

    schema-registry-php-client:基于Guzzle 6的Confluent Schema Registry REST APIPHP 7.3+ API客户端-http

    融合架构注册表PHP API 一个PHP 7.3+库,用于使用Confluent Schema Registry REST API。 它提供了低级功能来创建可以使用的PSR-7兼容请求,还提供了高级抽象以简化开发人员的体验。 内容 快取 低级API 测验 单元...

    Windows10中的IIS10安装php manager的方法

    自IIS7以来,微软的IIS更改并不大,架构一致,几乎所有IIS7能用的组件都能够在IIS7.7/8/8.5/10上安装。 安装方法: 打开 注册表(regedit) 找到: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W3SVC\...

    ICE分布式程序设计中文版

    20.5 IcePack 注册表 541 20.6 IcePack 节点 545 20.7 IcePack 管理工具 548 20.8 部署 551 20.9 描述符参考资料 557 20.10 排除故障 565 20.11 总结 568 第 21 章 Freeze 569 21.1 本章综 569 21.2 引言 570 21.3 ...

    java开源包1

    jFastCGI 是一个可以让Tomcat 之类的Servlet容器支持运行PHP和其它fastcgi应用程序,将Servlet容器充当成一个FastCGI 的网关。 Java 绘图框架 JGraphEd JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java ...

    java开源包11

    jFastCGI 是一个可以让Tomcat 之类的Servlet容器支持运行PHP和其它fastcgi应用程序,将Servlet容器充当成一个FastCGI 的网关。 Java 绘图框架 JGraphEd JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java ...

    java开源包2

    jFastCGI 是一个可以让Tomcat 之类的Servlet容器支持运行PHP和其它fastcgi应用程序,将Servlet容器充当成一个FastCGI 的网关。 Java 绘图框架 JGraphEd JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java ...

    java开源包3

    jFastCGI 是一个可以让Tomcat 之类的Servlet容器支持运行PHP和其它fastcgi应用程序,将Servlet容器充当成一个FastCGI 的网关。 Java 绘图框架 JGraphEd JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java ...

    java开源包6

    jFastCGI 是一个可以让Tomcat 之类的Servlet容器支持运行PHP和其它fastcgi应用程序,将Servlet容器充当成一个FastCGI 的网关。 Java 绘图框架 JGraphEd JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java ...

    java开源包5

    jFastCGI 是一个可以让Tomcat 之类的Servlet容器支持运行PHP和其它fastcgi应用程序,将Servlet容器充当成一个FastCGI 的网关。 Java 绘图框架 JGraphEd JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java ...

    java开源包10

    jFastCGI 是一个可以让Tomcat 之类的Servlet容器支持运行PHP和其它fastcgi应用程序,将Servlet容器充当成一个FastCGI 的网关。 Java 绘图框架 JGraphEd JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java ...

    java开源包4

    jFastCGI 是一个可以让Tomcat 之类的Servlet容器支持运行PHP和其它fastcgi应用程序,将Servlet容器充当成一个FastCGI 的网关。 Java 绘图框架 JGraphEd JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java ...

    java开源包8

    jFastCGI 是一个可以让Tomcat 之类的Servlet容器支持运行PHP和其它fastcgi应用程序,将Servlet容器充当成一个FastCGI 的网关。 Java 绘图框架 JGraphEd JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java ...

    java开源包7

    jFastCGI 是一个可以让Tomcat 之类的Servlet容器支持运行PHP和其它fastcgi应用程序,将Servlet容器充当成一个FastCGI 的网关。 Java 绘图框架 JGraphEd JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java ...

    java开源包9

    jFastCGI 是一个可以让Tomcat 之类的Servlet容器支持运行PHP和其它fastcgi应用程序,将Servlet容器充当成一个FastCGI 的网关。 Java 绘图框架 JGraphEd JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java ...

    java开源包101

    jFastCGI 是一个可以让Tomcat 之类的Servlet容器支持运行PHP和其它fastcgi应用程序,将Servlet容器充当成一个FastCGI 的网关。 Java 绘图框架 JGraphEd JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java ...

    Java资源包01

    jFastCGI 是一个可以让Tomcat 之类的Servlet容器支持运行PHP和其它fastcgi应用程序,将Servlet容器充当成一个FastCGI 的网关。 Java 绘图框架 JGraphEd JGraphEd 是一个 Java 的图形编辑应用和绘图框架。 Java ...

    JAVA上百实例源码以及开源项目

    百度云盘分享 简介 笔者当初为了学习JAVA,收集了很多经典源码,源码难易程度分为初级、中级、高级等,详情看源码列表,需要的可以直接下载! 这些源码反映了那时那景笔者对未来的盲目,对代码的热情、执着,对...

    JAVA上百实例源码以及开源项目源代码

    Java 源码包 Applet钢琴模拟程序java源码 2个目标文件,提供基本的音乐编辑功能。编辑音乐软件的朋友,这款实例会对你有所帮助。 Calendar万年历 1个目标文件 EJB 模拟银行ATM流程及操作源代码 ...

Global site tag (gtag.js) - Google Analytics