2

I'm working on a shopping cart (Cart model). One of its protected properties is "_items", which holds an array of Product objects. They (Products) all get stored in DB for populating the session (using ZF, Zend_Session_SaveHandler_DbTable() etc.).

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();
}

In the controller, I grab a Product obj from DB with the ProductMapper and provide it to "addItem()":

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

getProductByName() returns a new populated Model_Product object.


I usually get the

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

error message, a session dump obviously shows

['__PHP_Incomplete_Class_Name'] => 'Model_Product'


I know about the "declaring the class before serializing it". My problem is this: how can I declare the Product class in addItem(), if it's injected (first param) in the first place? Wouldn't a new declaration (like new Model_Product()) overwrite the param (original object) in addItem()? Must I declare it in the Cart model again?

Besides, I'll surely get a Cannot redeclare class Model_Product if I... redeclare it in Cart.

nevvermind
  • 3,302
  • 1
  • 36
  • 45
  • Are you using require function anywhere ? – Arihant Nahata May 05 '11 at 07:53
  • No. ZF's autoloader takes care of that. If I would, I'd get a `Cannot redeclare...`. The actual "declaration" is in the ProductMapper, when I retrieve/populate a new Product using `$prod = new Product(); return $prod->populate($values)`. – nevvermind May 05 '11 at 07:59
  • It's weird that I must declare it in order to properly get it serialized, but cannot, because it's already declared. I don't know where to re-declare it. – nevvermind May 05 '11 at 08:06
  • Hi, maybe you find the answer or an idea here: http://stackoverflow.com/questions/5755473/php-serialize-deserialize-oop – strauberry May 05 '11 at 08:07
  • I think I got it. In ZF's bootstrap, the session initialization was made **prior** to autoloading. I can't post an answer right now (SO's 8 hour delay), but I will as soon as I can. – nevvermind May 05 '11 at 08:22
  • @nush: Please accept your answer as "the answer". This will mark the question as answered (And I think it's the right answer anyway). – hakre Jul 17 '11 at 13:37

1 Answers1

4

In ZF's bootstrap, the session was started before autoloading.

    /**
     * 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();
    }

When I was getting the errors I was talking about, the method declaration was the other way around: _initSession() was first, then _initAutoloaders() - and this was the exact order ZF was processing them.

I'll test some more, but this seems to work (and logical). Thanks for all your suggestions.

nevvermind
  • 3,302
  • 1
  • 36
  • 45
  • Sir, you are a lifesaver. I've spent the best part of 2 hours now trying to understand just what is happening with Zend_Auth and it turned out to be the module autoloader in a module bootstrap! Thank you! – Ross Feb 14 '12 at 02:29
  • I'm not sure if in a ZF doc/example somewhere the session is done before the autoloaders, or it's not specified and most developers presume since you would want session_start() as early as possible it's the first function in the Bootstrap, but we've taken over at least a dozen projects that had the session before the autoloader. – conrad10781 Nov 27 '16 at 12:27