2011-04-22 108 views
1

我想在我的模型中检索Zend_Session_Namespace的实例,但我不希望它们对Zend的实现有一个具体的依赖关系(所以我可以对它进行测试)。通过DI容器获取Zend_Session_Namespace的实例

会话实例需要在通话时传递给它的一些配置。我的其他依赖关系不可以在bootstap进程中配置。

我有一个非常基本的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内部服务器错误:(

回答

1

我通过调整Lib_Model::getSession()稍微解决了500内部服务器错误:

public function getSession($ns = null) { 
    $ns = ($ns == null) ? $this->_sessionName : $ns; 
    if (!isset($this->_sessionInstance[$ns])) { 
    $sessionFactory = $this->_session; 
    $this->_sessionInstance[$ns] = $sessionFactory($ns); 
    } 
    return $this->_sessionInstance[$ns]; 
} 

我放在一起简单的脚本慢慢建立它的复杂性,直到它曙光我在Lib_Model我调用了一个未定义的方法,虽然没有错误信息显示在Apache下运行的PHP。

$f = function() { 
    return function($name) { 
    echo "Hello " . $name . PHP_EOL; 
    }; 
}; 

$hello = $f(); 
$hello("World"); 
unset($hello); 

// second test 

class 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]; 
    } 
} 

$c = new Container; 
$c->h = function() { 
    return function($name) { 
    echo "Hello " . $name . PHP_EOL; 
    }; 
}; 

$hello = $c->h; 
$hello("Bert"); 

// third test 

class MyTest { 
    public $attr; 
} 

$test = new MyTest; 
$test->attr = $c->h; 
$test->attr("Ernie"); 

测试输出:

$ php -f test.php 
Hello World 
Hello Bert 
PHP Fatal error: Call to undefined method MyTest::attr() in /home/greg/test.php on line 53