通过 DI 容器获取 Zend_Session_Namespace 的实例
我想在我的模型中检索 Zend_Session_Namespace 的实例,但我不希望他们对 Zend 的实现有具体的依赖(所以我可以模拟它进行测试)。
会话实例需要在调用时传递给它一些配置。我的其他依赖项没有,并且可以在引导过程中进行配置。
我有一个非常基本的 DI 容器,借自 Fabien Potencier:
class Lib_Container {
protected $services = array();
function __set($id, $service) {
$this->services[$id] = $service;
}
function __get($id) {
if (!isset($this->services[$id])) {
throw new ServiceNotRegisteredException(
"Service '$id' has not been registered"
);
}
if (is_callable($this->services[$id])) {
return $this->services[$id]($this);
}
return $this->services[$id];
}
}
我使用它来连接我的依赖项:
$container = new Lib_Container;
$container->session = function($c) {
return new Zend_Session_Namespace($c->sessionName);
};
...
我在我的基本模型中使用这些依赖项(我不希望我的模型了解太多有关我的容器配置的信息):
class Lib_Model {
protected $_container;
protected $_sessionName = 'default';
protected $_sessionInstance;
public function __construct($container) {
$this->_container = $container;
}
public function getDB() {
return $this->_container->database;
}
public function getRequest() {
return $this->_container->request;
}
public function getSession($ns = null) {
$ns = ($ns == null) ? $this->_sessionName : $ns;
if (!isset($this->_sessionInstance[$ns])) {
$this->_container->sessionName = $ns;
$this->_sessionInstance[$ns] = $this->_container->session;
}
return $this->_sessionInstance[$ns];
}
}
这使我的子类能够相当方便地检索会话实例:
class Model_User extends Lib_Model {
protected $_sessionName = 'user';
public function loggedIn() {
$session = $this->getSession();
return ($session && $session->loggedIn) ? true : false;
}
}
或者通过将会话命名空间作为参数传递:
$session = $this->getSession('admin');
但是,我的 Lib_Model::getSession() 方法比我想要的更复杂,并且对我的 DI 容器了解太多。理想情况下,希望通过调用来获取 Zend_Session_Namespace
的实例:
class Lib_Model {
protected $_sessionName = 'default';
protected $_sessionFactory;
...
public function __construct($container) {
$this->_sessionFactory = $container->session;
}
...
public function getSession($ns = null) {
$ns = ($ns == null) ? $this->_sessionName : $ns;
if (!isset($this->_sessionInstance[$ns])) {
$this->_sessionInstance[$ns] = $this->_sessionFactory($ns);
}
return $this->_sessionInstance[$ns];
}
}
我很欣赏我的 DI 容器正在检查它的服务是否可调用(例如匿名函数)并执行它们。如果我删除此行为,自动装配元素会崩溃吗?
有什么想法可以实现 $container->session('my_namespace')
返回与 new Zend_Session_Namespace('my_namespace')
等效的内容吗?
更新:我认为通过更改容器的配置我可以做一些事情:
$container->session = function($c) {
$s = function($namespace) {
return new Zend_Session_Namespace($namespace);
};
return $s;
};
这样 $container->session
将返回一个函数。更新我的 Lib_Model 类:
Lib_Model {
private $_sessionFactory;
...
public function __construct($container) {
...
$this->_sessionFactory = $container->session;
}
...
public function getSession($ns = null) {
$ns = ($ns == null) ? $this->_sessionName : $ns;
if (!isset($this->_sessionInstance[$ns]))
$this->_sessionInstance[$ns] = $this->_sessionFactory($ns);
return $this->_sessionInstance[$ns];
}
}
不幸的是,这给了我一个 500 内部服务器错误:(
I want to retrieve an instance of Zend_Session_Namespace within my models but I don't want them to have a concrete dependency on Zend's implementation (so I can mock it for it testing).
The session instance needs some configuration passed to it at call time. My other dependencies do not and can be configured during the bootstap process.
I have a very basic DI container, borrowed from Fabien Potencier:
class Lib_Container {
protected $services = array();
function __set($id, $service) {
$this->services[$id] = $service;
}
function __get($id) {
if (!isset($this->services[$id])) {
throw new ServiceNotRegisteredException(
"Service '$id' has not been registered"
);
}
if (is_callable($this->services[$id])) {
return $this->services[$id]($this);
}
return $this->services[$id];
}
}
I'm using this to wire up my dependencies:
$container = new Lib_Container;
$container->session = function($c) {
return new Zend_Session_Namespace($c->sessionName);
};
...
I'm using these dependencies within my base model (I don't want my model to know so much about my container configuration):
class Lib_Model {
protected $_container;
protected $_sessionName = 'default';
protected $_sessionInstance;
public function __construct($container) {
$this->_container = $container;
}
public function getDB() {
return $this->_container->database;
}
public function getRequest() {
return $this->_container->request;
}
public function getSession($ns = null) {
$ns = ($ns == null) ? $this->_sessionName : $ns;
if (!isset($this->_sessionInstance[$ns])) {
$this->_container->sessionName = $ns;
$this->_sessionInstance[$ns] = $this->_container->session;
}
return $this->_sessionInstance[$ns];
}
}
This enables my subclasses to retrieve a session instance reasonably conveniently:
class Model_User extends Lib_Model {
protected $_sessionName = 'user';
public function loggedIn() {
$session = $this->getSession();
return ($session && $session->loggedIn) ? true : false;
}
}
Or by passing the session namespace as an argument:
$session = $this->getSession('admin');
However, my Lib_Model::getSession()
method is more complex than I would like, and knows too much about my DI container. Ideally want to obtain an instance of Zend_Session_Namespace
by calling:
class Lib_Model {
protected $_sessionName = 'default';
protected $_sessionFactory;
...
public function __construct($container) {
$this->_sessionFactory = $container->session;
}
...
public function getSession($ns = null) {
$ns = ($ns == null) ? $this->_sessionName : $ns;
if (!isset($this->_sessionInstance[$ns])) {
$this->_sessionInstance[$ns] = $this->_sessionFactory($ns);
}
return $this->_sessionInstance[$ns];
}
}
I appreciate my DI container is checking if it's services are callable (e.g. anonymous functions) and executing them. If I remove this behaviour the auto-wiring element will crumble?
Any ideas how I can achieve $container->session('my_namespace')
to return the equivalent of new Zend_Session_Namespace('my_namespace')
?
Update: I thought I was on to something by changing the configuration of my container:
$container->session = function($c) {
$s = function($namespace) {
return new Zend_Session_Namespace($namespace);
};
return $s;
};
So that $container->session
would return a function. Updating my Lib_Model
class:
Lib_Model {
private $_sessionFactory;
...
public function __construct($container) {
...
$this->_sessionFactory = $container->session;
}
...
public function getSession($ns = null) {
$ns = ($ns == null) ? $this->_sessionName : $ns;
if (!isset($this->_sessionInstance[$ns]))
$this->_sessionInstance[$ns] = $this->_sessionFactory($ns);
return $this->_sessionInstance[$ns];
}
}
Unfortunately this gives me a 500 internal server error :(
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我通过稍微调整 Lib_Model::getSession() 解决了 500 内部服务器错误:
我将一个简单的脚本放在一起,慢慢地增加它的复杂性,直到我意识到我在
上调用了一个未定义的方法Lib_Model
,尽管在 apache 下运行 PHP 没有显示错误消息。测试输出:
I resolved the 500 internal server error by adjusting
Lib_Model::getSession()
slightly:I put together a simple script slowly building up it's complexity until it dawned on me I was calling an undefined method on
Lib_Model
, though no error message was displayed by PHP running under apache.Test output: