`

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吧。

相关推荐

    2025年深圳杯(东三省)B题完整论文+代码结果+思路(全套资源+多家资源整合)

    本方案针对2025年深圳杯(东三省)B题,提供高质量成品文章、完整解题代码及所有结果表。内容涵盖Python和MATLAB双版本代码、PDF论文文档(附PDF转Word功能),并包含详细思路解析,助力参赛队伍高效完成比赛,冲刺高奖项。 【核心内容】 成品文章 包含完整解题思路、模型构建、数据分析与结果讨论。 格式规范,符合竞赛论文要求,可直接提交或稍作修改使用。 完整代码 提供Python和MATLAB两种语言实现,覆盖数据处理、模型训练、结果可视化全流程。 代码模块化设计,注释清晰,便于理解与二次开发。 结果表格 所有实验数据与结果均已整理成表,直观展示模型性能与对比分析。 PDF转Word支持 提供一键转换工具,方便用户根据需求调整论文格式。 【产品优势】 高效实用:成品论文与代码已通过严格测试,确保结果准确且可复现。 全面覆盖:从思路解析到最终成果,一站式解决参赛需求。 灵活便捷:支持多平台使用,网盘直发,后续更新免费获取。 【适用人群】 冲刺“妈妈杯”高奖项的参赛团队。 希望快速掌握解题思路与实现方法的学习者。 需要高质量参考材料的科研爱好者。 【交付清单】 成品论文(PDF+Word) Python/MATLAB代码包 数据集与结果表 PDF转Word工具

    C++实现编译原理语法分析实验

    根据给定文法设计语法分析程序,要求如下:(1)使用递归子程序法,对文法定义的所有语法成分进行分析;(2)输入文件为testfile.txt,输出文件为output.txt。输出内容包括:1)按词法分析顺序,逐行输出单词信息(预读单词不输出);2)在分析特定语法成分结束前,另起一行输出该成分名称,如“<常量说明>”。该代码在CG实验平台满分通过,仅供参考。

    MATLAB环境下极化码SC与SCL译码仿真研究

    极化码(Polar Code)是由土耳其科学家Erdal Arıkan在2009年提出的一种新型纠错编码技术。它通过利用信道的极化现象,将虚拟信道分为误码率接近0和接近1/2的两类。在编码设计中,数据被放置在误码率极低的信道上,从而实现高效的数据传输。极化码的主要优势在于其理论编码容量能够达到香农限,并且构造方法较为简单。 MATLAB是一种功能强大的数学计算和编程工具,广泛应用于科学研究和工程领域。在极化码的研究中,MATLAB可用于构建编码和解码算法,模拟数据在不同信道条件下的传输效果,验证理论性能,并优化相关参数。 SC(Successive Cancellation,逐位取消)译码是极化码的基本解码方法。它从最可靠的比特开始,依次解码每个虚拟信道,且每个比特的解码结果会影响后续比特的解码,因为它们之间存在依赖关系。虽然SC译码的实现较为简单,但其计算复杂度较高,随着码长的增加,解码时间会线性增长。 SCL(Successive Cancellation List,逐位取消列表)译码是SC译码的改进版本。它通过引入列表机制,同时处理多个路径,从而增强了错误校正能力,并在一定程度上降低了错误率。与SC译码相比,SCL译码虽然需要消耗更多的计算资源,但能够提供更好的性能。 一个完整的MATLAB仿真资源通常包含以下内容: 编码模块:用于实现极化码的生成,包括码字构造和极化矩阵操作等。 信道模型:用于模拟各种通信信道,例如AWGN(加性高斯白噪声)信道或衰落信道。 SC/SCL译码模块:包含SC译码和SCL译码的算法实现。 误码率(BER)计算:通过比较发送和接收的码字,计算误码率,以评估编码性能。 性能曲线绘制:绘制误码率与信噪比(SNR)之间的关系曲线,展示不同译码策略的性能差异。 使用说明:指导用户如何运行仿真,理解代码结构,以及如何调整参数以进行自定义实验。 代码注

    ClazzController.java

    ClazzController.java

    qwq3 model 1use for ollama

    qwq3 model 1use for ollama

    cmd-bat-批处理-脚本-MinimizeWindow.zip

    cmd-bat-批处理-脚本-MinimizeWindow.zip

    基于指针标注的中文医学文本实体关系抽取研究.pdf

    基于指针标注的中文医学文本实体关系抽取研究.pdf

    二十四节气之大暑节气.pptx

    二十四节气之大暑节气.pptx

    cmd-bat-批处理-脚本-DEFRAG-W7.zip

    cmd-bat-批处理-脚本-DEFRAG-W7.zip

    cmd-bat-批处理-脚本-数据结构二叉树binaryTree.zip

    cmd-bat-批处理-脚本-数据结构二叉树binaryTree.zip

    cmd-bat-批处理-脚本-safepath.zip

    cmd-bat-批处理-脚本-safepath.zip

    实证数据-2004-2023年企业社会信任数据-社科经管.rar

    该数据集为2004-2023年中国企业社会信任面板数据,涵盖全国31个省份的上市公司信息。数据基于中国企业家调查系统(CESS)的问卷调查结果,采用张维迎在《经济研究》中的研究方法构建:通过对1500多家企业调查“最守信用地区”的排序结果(前五位分别赋5至1分),以各省得票百分比为权重加权求和后取自然对数,形成三个核心指标: 社会信任1(trust1):各得分下加权占比 社会信任2(trust2):最值得信任地区的占比 社会信任3(trust3):加权占比数值的对数处理 数据包含证券代码、所属省份、年份、行业名称等字段,提供Excel和dta两种格式,适用于区域经济、企业信用、金融投资等领域的实证研究。原始数据来源及方法论详见参考文献:张维迎, 柯荣住. 信任及其解释: 来自中国的跨省调查分析[J]. 经济研究, 2002(10): 59-70+96。

    cmd-bat-批处理-脚本-get-memory-size.zip

    cmd-bat-批处理-脚本-get-memory-size.zip

    高安全领域可编程逻辑器件软件工程技术研究与应用.pdf

    高安全领域可编程逻辑器件软件工程技术研究与应用.pdf

    cmd-bat-批处理-脚本-网络通信-keyreader.zip

    cmd-bat-批处理-脚本-网络通信-keyreader.zip

    小程序 新版影视源码 前后端非框架版+破解域名授权.zip

    前不久发布的外面泛滥版本很大错误和少文件,今天分享一套可运营的版本不是外面泛滥的版本采集播放都OK完美运营 最新影视小程序安装说明: 1.安装环境: 建议服务器装Linux CentOS 7 系统宝塔面板。 环境用 1:Nginx 1.18.0 2:php7.0 — 安装fileinfo插件、redis、sg11扩展(然后重启php服务) 3:MySQL 5.6.50 本次操作需要用电脑或用挂机宝操作 反正必须电脑:源码文件以包含全部教程 弄完测试转圈圈就是合法域名或证书没弄好 自己检查一下 安装教程来保你上线 本人亲测分类需要刷新才可以出来 问题不大

    YOLOv5目标检测网络架构Visio源文件

    提供一份YOLOv5网络结构图的Visio源文件,该文件支持直接进行编辑和修改。

    基于python的卷积神经网络实现,包含源码

    python卷积神经网络实现源码, 卷积神经网络(Convolutional Neural Networks, CNN)是一类包含卷积或相关计算且具有深度结构的前馈神经网络(Feedforward Neural Networks),是深度学习(deep learning)的代表算法之一 [1-2] 。由于卷积神经网络能够进行平移不变分类(shift-invariant classification),因此也被称为“平移不变人工神经网络

    西门子S7-200PLC与MCGS6.2在立体仓库堆垛机控制中的应用及优化

    内容概要:本文详细介绍了西门子S7-200PLC与MCGS6.2组态软件在立体仓库控制系统中的具体应用。文中首先阐述了硬件部分,特别是S7-200PLC的高速计数器(HSC)用于堆垛机精确定位的关键作用及其初始化代码。接着讨论了MCGS软件在物料调度界面上的作用,如通过动态脚本实现货架状态的实时显示,并解决了坐标补偿的问题。此外,还探讨了S7-200的移位指令在处理入库队列时的应用以及应对多请求情况的方法。最后提到了MCGS的历史报警查询功能和通讯干扰问题的解决方案。整个系统强调了稳定性和精确性的实现。 适合人群:从事工业自动化领域的工程师和技术人员,尤其是对PLC编程和组态软件有一定了解的人群。 使用场景及目标:适用于需要理解和实施立体仓库自动化的技术人员,帮助他们掌握S7-200PLC与MCGS6.2的具体应用技巧,确保系统的稳定运行并提高效率。 其他说明:尽管目前新的项目可能更多地采用更新的技术,但对于旧工厂改造项目而言,这套组合仍然非常实用。文中提到的各种优化措施对于提升系统的可靠性和性能至关重要。

    cmd-bat-批处理-脚本-SquishRunTestCase.zip

    cmd-bat-批处理-脚本-SquishRunTestCase.zip

Global site tag (gtag.js) - Google Analytics