ZF-10448: Cache Zend_Navigation not working

Description

Dears,

This issue is more or less the same as ZF-6746.

Since Zend_Navigation use spl_object_hash to generate an id for the page, if you cache a Zend_Navigation object, once the cache is loaded, the navigation is broken because spl_object_hash generation unique id for the instance of php. See also http://stackoverflow.com/questions/1370130/…

Possible fix (to test): don't use spl_object_id but md5(serialize(array(...))) representing the object. The active property must be saved as false and the parents property must be saved as null because the parents may changed once you add a page.

I will join the patch but should be improved and well tested.

Thank you for your hard work on the Zend Framework.

Best regards,

Raphaël Dehousse

Comments

Really strange, I cannot add a file (don't see any link to do that)

I paste the patch here then


Index: Page.php
===================================================================
--- Page.php    (revision 22938)
+++ Page.php    (working copy)
@@ -1065,7 +1065,29 @@
      */
     public final function hashCode()
     {
-        return spl_object_hash($this);
+        return md5(
+            serialize(
+                array_merge(
+                    $this->getCustomProperties(),
+                    array(
+                        'label'     => $this->getlabel(),
+                        'id'        => $this->getId(),
+                        'class'     => $this->getClass(),
+                        'title'     => $this->getTitle(),
+                        'target'    => $this->getTarget(),
+                        'rel'       => $this->getRel(),
+                        'rev'       => $this->getRev(),
+                        'order'     => $this->getOrder(),
+                        'resource'  => $this->getResource(),
+                        'privilege' => $this->getPrivilege(),
+                        'active'    => false,
+                        'visible'   => $this->isVisible(),
+                        'type'      => get_class($this),
+                        'pages'     => null,
+                    )
+                )
+            )
+        );
     }
 
     /**

Best regards,

Raphaël Dehousse

Bad idea!


$hash = $page->hashCode();

if (array_key_exists($hash, $this->_index)) {
    // page is already in container
    return $this;
}

// adds page to container and sets dirty flag
$this->_pages[$hash] = $page;

public function testContainerWithTwoSamePages()
{
    $container = new Zend_Navigation(array(
        array(
            'label' => 'foo',
            'uri'   => 'foo',
            'bar'   => 'baz',
        ),
        array(
            'label' => 'foo',
            'uri'   => 'foo',
            'bar'   => 'baz',
        ),
    ));

    $found = array();
    foreach ($container as $page) {
        $found[] = $page->toArray();
    }

    $this->assertSame(2, count($found));
}

Fail!

Maybe the www.php.net/manual/en/class.splobjectstorage.php" rel="nofollow">SplObjectStorage class is a possible variant. I will look into this (including the performance).

Hello,

The user would have to define a different id for the page then. Sth has to be different between the pages, otherwise, what could be the interest?

Thank you for looking for a solution ;)

Regards,

Raphaël Dehousse

{quote} Sth has to be different between the pages, otherwise, what could be the interest? {quote} It breaks the test from "Zend_Navigation_ContainerTest":


public function testAddPageShouldWorkWithPageInstance()
{
    $pageOptions = array(
        'label' => 'From array 1',
        'uri' => '#array'
    );

    $nav = new Zend_Navigation(array($pageOptions));

    $page = Zend_Navigation_Page::factory($pageOptions);
    $nav->addPage($page);

    $this->assertEquals(2, count($nav));
}

;)