[php]提供可全局访问的数据

来源:互联网 发布:淘宝买家内衣秀大尺度 编辑:程序博客网 时间:2024/06/05 09:12

        PHP变量作用域:作用域通常用来描述代码结构中对象或者值的可见程度。PHP的变量作用域有三个级别,1)标准级别是指一个HTTP请求从开始到结束的周期。2)PHP内置了对会话变量Session的支持。在一次请求结束后,会话变量会被序列化并存储到文件系统或者数据库中,然后在下一个请求开始时取回。存放在cookie中的会话ID和通过查询字符串传递的会话ID被用于跟踪该会话的拥有者。3)在Java中有一个“应用程序作用域”的概念,内存中的变量可以被系统中的所有对象实例访问到。这就和PHP不同了,为了能够在应用的任何层上能都访问到系统的配置数据,那就需要模拟构建应用程序作用域。

        实现模拟应用程序作用域的方法:1)可以在系统中把这些数据(Content)从一个对象传递到另一个对象(从一个负责处理请求的控制器对象传递到业务逻辑层的对象,然后再传递到持久化层中的对象),这样能在任意层中获取需要的对象。2)修改各层的接口,判断上下文是否需要该数据,但这会影响到松散耦合。3)注册表模式。


        注册表(Registry):注册表的作用是提供系统级别的对象的访问功能。Registry对象可以使数据全局有效,这就意味着它能在任意层中都能访问到数据了。

                             

       三种作用域的代码实现(另外最后有一个是共享内存shm的实现)

namespace demo\base;/** * Registry */abstract class Registry {protected abstract function get($key);protected abstract function set($key, $val);}/** * Request */class RequestRegistry extends Registry {private $value = array();private static $instance;private function __construct() {}public static function getInstance() {if (isset(self::$instance) == false) {self::$instance = new self();}return self::$instance;}protected function get($key) {if (isset($this->value[$key]) == true) {return $this->value[$key];}return null;}protected function set($key, $val) {$this->value[$key] = $val;}public function getRequest() {return self::$instance->get('request');}public function setRequest(\demo\controller\Request $request) {return self::$instance->set('request', $request);}}/** * Session */class SessionRegistry extends Registry {private static $instance;private function __construct() {// 开启会话session_start();}public static function getInstance() {if (isset(self::$instance) == false) {self::$instance = new self();}return self::$instance;}protected function get($key) {if (isset($_SESSION[__CLASS__][$key]) == true) {return $_SESSION[__CLASS__][$key];}return null;}protected function set($key, $val) {$_SESSION[__CLASS__][$key] = $val;}public function getSession() {return self::$instance->get('session');}    public function setSession(\demo\controller\Complex $complex) {        self::instance()->set('session', $complex);    }}/** * Application */class ApplicationRegistry extends Registry {    private static $instance;    private $freezedir = "./data"; // 此处硬编码,具体根据实际情况配置    private $values = array();    private $mtimes = array();    private function __construct() {        }public static function getInstance() {if (isset(self::$instance) == false) {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])  == false) {             $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]) == true) {            return $this->values[$key];        }                return null;    }    protected function set($key, $val) {        $this->values[$key] = $val;        $path = $this->freezedir . DIRECTORY_SEPARATOR . $key;        if (file_exists($path) == false) {        touch($path);        }        file_put_contents($path, serialize($val));        $this->mtimes[$key]=time();    }    public function getDSN() {        return self::getInstance()->get('dsn');    }    public function setDSN( $dsn ) {        return self::getInstance()->set('dsn', $dsn);    }    public function setControllerMap(\demo\controller\ControllerMap $map) {        self::getInstance()->set('cmap', $map);    }    public function getControllerMap() {        return self::getInstance()->get('cmap');    }        // 其它一些列getter和setter    // ...}/** * 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!");        }    }    public static function instance() {        if (isset(self::$instance) == false) {         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);    }    public function getDSN() {        return self::instance()->get(self::DSN);    }    public function setDSN( $dsn ) {        return self::instance()->set(self::DSN, $dsn);    }}
        SessionRegistry和ApplicationRegistry都将数据序列化到文件,所以从不同请求取回的对象是同一个对象的不同副本,而不是对同一个对象的引用。那么就需要注意数据的同步了,加锁避免冲突。魔术方法__sleep()和__wakeup()可以解决这个问题。

原创粉丝点击