【问题标题】:Incomplete PHP class when serializing object in sessions在会话中序列化对象时不完整的 PHP 类
【发布时间】:2011-08-19 03:41:37
【问题描述】:

我正在制作购物车(购物车模型)。其中一个受保护的属性是“_items”,它包含一个 Product 对象数组。它们(产品)都存储在数据库中以填充会话(使用 ZF、Zend_Session_SaveHandler_DbTable() 等)。

public function addItem(Model_Product $product, $qty)
{
    $qty = (int) $qty;
    $pId = $product->getId();

    if ($qty > 0) {
        $this->_items[$pId] = array('product' => $product, 'qty' => $qty);
    } else {
        // if the quantity is zero (or less), remove item from stack
        unset($this->_items[$pId]);
    }

    // add new info to session
    $this->persist();
}

在控制器中,我使用 ProductMapper 从 DB 中获取一个 Product obj 并将其提供给“addItem()”:

    $product1 = $prodMapper->getProductByName('cap');
    $this->_cart->addItem($product1, 2);

getProductByName() 返回一个新填充的 Model_Product 对象。


我通常会得到

Please ensure that the class definition "Model_Product" of the object you are trying to operate on was loaded _before_ ...

错误信息,会话转储明显显示

['__PHP_Incomplete_Class_Name'] => 'Model_Product'


我知道“在序列化之前声明类”。我的问题是:我如何在addItem() 中声明 Product 类,如果它首先被注入(第一个参数)?新声明(如new Model_Product())不会覆盖addItem() 中的参数(原始对象)吗?我必须在 Cart 模型中再次声明它吗?

此外,如果我...在购物车中重新声明它,我肯定会得到 Cannot redeclare class Model_Product

【问题讨论】:

  • 你在任何地方都使用 require 函数吗?
  • 没有。 ZF 的自动装弹机可以解决这个问题。如果我愿意,我会得到一个Cannot redeclare...。实际的“声明”在 ProductMapper 中,当我使用 $prod = new Product(); return $prod->populate($values) 检索/填充新产品时。
  • 奇怪的是,我必须声明它才能正确序列化它,但不能,因为它已经声明了。我不知道在哪里重新声明它。
  • 嗨,也许你在这里找到了答案或想法:stackoverflow.com/questions/5755473/…
  • 我想我明白了。在 ZF 的引导程序中,会话初始化先于自动加载。我现在无法发布答案(SO 延迟 8 小时),但我会尽快发布。

标签: php session serialization object-serialization


【解决方案1】:

在 ZF 的引导程序中,会话在自动加载之前启动。

    /**
     * Make XXX_* classes available
     */
    protected function _initAutoloaders()
    {
        $loader = new Zend_Application_Module_Autoloader(array(
                    'namespace' => 'XXX',
                    'basePath' => APPLICATION_PATH
                ));
    }

    public function _initSession()
    {
        $config = $this->_config->custom->session;

        /**
         * For other settings, see the link below:
         * http://framework.zend.com/manual/en/zend.session.global_session_management.html
         */
        $sessionOptions = array(
            'name'             => $config->name,
            'gc_maxlifetime'   => $config->ttl,
            'use_only_cookies' => $config->onlyCookies,
//            'strict'           => true,
//            'path'             => '/',
        );

        // store session info in DB
        $sessDbConfig = array(
            'name'           => 'xxx_session',
            'primary'        => 'id',
            'modifiedColumn' => 'modified',
            'dataColumn'     => 'data',
            'lifetimeColumn' => 'lifetime'
        );

        Zend_Session::setOptions($sessionOptions);
        Zend_Session::setSaveHandler(new Zend_Session_SaveHandler_DbTable($sessDbConfig));
        Zend_Session::start();
    }

当我遇到我所说的错误时,方法声明是相反的:_initSession() 首先是 _initAutoloaders() - 这就是 ZF 处理它们的确切顺序。

我会再测试一些,但这似乎可行(并且合乎逻辑)。感谢您的所有建议。

【讨论】:

  • 先生,您是救生员。我现在花了 2 个小时的大部分时间试图了解 Zend_Auth 发生了什么,结果证明它是模块引导程序中的模块自动加载器!谢谢!
  • 我不确定是否在 ZF 文档/示例中某个地方的会话是在自动加载器之前完成的,或者它没有指定并且大多数开发人员认为,因为您希望 session_start() 尽早它是Bootstrap 中的第一个函数,但我们已经接管了至少十几个在自动加载器之前有会话的项目。
猜你喜欢
  • 2015-11-24
  • 1970-01-01
  • 2010-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-07
  • 1970-01-01
相关资源
最近更新 更多