【问题标题】:Making $_SESSION available in controllers使 $_SESSION 在控制器中可用
【发布时间】:2013-05-15 00:32:14
【问题描述】:

我正在尝试使 $_SESSION 全局在我从头开始编写的框架的控制器中可用。它不完全是 MVC,表示层由两个父类和多个子类组成。

不做详细介绍,我的观点呈现在class Template

class Template{

    protected $_controller;
    protected $_action;

    function __construct($controller,$action) {
        $this->_controller = $controller;
        $this->_action = $action;
    }

    function render(){
        if (file_exists(APP_ROOT . DS . 'app' . DS . 'view' . DS . $this->_controller . DS . $this->_action . '.php')) {
            include (APP_ROOT . DS . 'app' . DS . 'view' . DS . $this->_controller . DS . $this->_action . '.php');
        }
    }

}

然后我在构造函数中实例化class Template 后,在父控制器的析构函数中调用Template::render()。所有类都被自动加载。

class CoreController {

    protected $_controller;
    protected $_action;
    protected $_template;

    function __construct($controller, $action) {
        $this->_controller = ucfirst($controller);
        $this->_action = $action;

        $this->_template = new Template($controller,$action);
    }

    function __destruct() {
        $this->_template->render();
    }
} 

我的问题是如何使$_SESSIONCoreController 中可用,以及在关机序列期间它究竟何时可用?我试过直接在CoreControllerTemplate::render() 中调用它,并且总是得到未定义的变量警告,但是在我的视图中定义$_SESSION 是可行的。这背后的原因是我想根据是否设置会话 ID 来设置某些变量,并且我想将大多数表示逻辑保留在我的控制器中。提前致谢。

【问题讨论】:

  • 只需在进程的引导阶段调用 session_start,您应该能够在请求的整个生命周期内得到它
  • 您的建议很有效,再次感谢!前几天你的服务器小费是救命稻草。我想知道我是否应该按照 teresko 的建议在模型层中使用它,这可能涉及通过调度程序发送它,如果我很挑剔的话,这似乎是一种更好的方法。
  • 恕我直言,它属于控制器。如果你把它放在模态中,你就是在模态和需要会话的使用模式之间创建依赖关系,所以在 from 脚本中使用模态说是不可能的。
  • @Orangepill,所以,就因为不想抽象超全局,就决定销毁SoC?
  • $_SESSION 是一个超全局的,所以它无处不在。在关闭阶段,超全局变量在其中被杀死,会话在某个时间关闭。 Johannes Schlüter 有一篇精彩的演讲,请参阅 PHP Shutdown Sequence ca。 25:50

标签: php session model-view-controller session-variables


【解决方案1】:

会话是一种存储形式。这意味着,它只能在模型层的深处使用。

在表示层中操作$_SESSION 与在控制器和/或视图中扭曲 SQL 类似。您将消除SoC 的最后痕迹......尽管您已经通过实现像“ViewController”怪物这样的Rails 来做到这一点。

您应该使用与 sql 类似的映射器,而不是在表示层中泄漏您的存储逻辑。

来自model layer中的一些服务

public function identify( $parameters )
{

    $user = $this->domainObjectFacctory->create('user');
    $mapper = $this->mapperFactory->create('session');

    if ( $mapper->fetch($user, 'uid') === false )
    {
        $mapper = $this->mapperFactory->create('user');
        $user->setUsername($parameters['login']);
        $user->setPassword($parameters['pass']);

        $mapper->fetch($user);
    }

    $this->currentUser = $user->isValid()
                       ? $user
                       : null;
}

控制器只与服务交互

public function postLogin( $request )
{
    $auth = $this->serviceFactory->create('recognition');
    $auth->identify([
        'login' => $request->getParameter('username'),
        'pass'  => $request->getParameter('password'),
        ]);
}

服务工厂将被注入到控制器(以及随附的视图)的构造函数中。

注意:以上代码仅用于说明这一点,不应复制粘贴或以其他方式移植到生产代码上。

【讨论】:

  • 感谢您的建议,处理此问题的最佳方法是什么?我正在考虑在调度程序中定义 $_SESSION 而不是在父模型构造中调用它。
  • 会话对象的初始化($_SESSIONusperglobal 的抽象)应该在工厂中完成,为服务创建data mappers。同一个工厂还将确保会话对象只创建一次,而不需要单例或其他不良做法。
  • 好吧,从这个角度看,如果我理解的话,在内存中初始化 $_SESSION 然后通过表示层与之交互,请原谅速记。似乎是最合乎逻辑的方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-09
  • 2017-09-30
相关资源
最近更新 更多