user269867
user269867

Reputation: 3972

Singleton pattern using PHP

I am trying to create a dynamic navigation class.

class myApp_Helper_Breadcrum{
    protected $navigationArray=array();
    private static $_instance = null;
    public static function getInstance()
    {
         if (!isset(self::$_instance)) {
            self::$_instance = new self();
        }
        return self::$_instance;
    }
    private function __construct() {
         $this->navigationArray = array();
    }

    public  function popin($popInElement){
        array_push($this->navigationArray,$popInElement);
    }

    public  function displayLinks()
    {
          //print array
    }
}

In boostrap I did following

$nlinks=myApp_Helper_Breadcrum::getInstance();
Zend_Registry::set('nlinks',$nlinks);

Now in my controller I am calling as follow

$nlinks= Zend_Registry::get('nlinks');
$nlinks->popin('Home');
$nlinks->displayLinks();

The problem is, even if this class is singleton the constructor is called again and again which makes my array to initialize. what I am trying to achieve is to keep pushing the items in the navigation array as I navigate the site.

Any idea why it is like this in ZF?

Upvotes: 0

Views: 2431

Answers (4)

Janis Peisenieks
Janis Peisenieks

Reputation: 4998

Even though this is old, I would like to add my 2 cent.

Zend DOES NOT create a singleton, that persists across multiple requests. Regardless of the interpretation of the ZF documentation, on each request, the whole stack is re-initialized.

This is where your problem comes from. Since bootstrapping is done on each request, each request also re-initializes your helper method. As far as I know, helpers in ZF 1.x CAN'T be singletons.

The only way I see this being implementes ar you want it to be, is using sessions.

Upvotes: 0

user1713042
user1713042

Reputation: 43

I ran into the exact same problem. The problem is that the persistence of your classes are on the request scope. And with zend, you can even have multiple requests for a page load.

PHP is a shared nothing architecture; each request starts in a new process, and at the end of the request, it's all thrown away. Persisting across requests simply cannot happen -- unless you do your own caching. You can serialize objects and restore them -- but pragmatically, in most cases you'll get very little benefit from this (and often run into all sorts of issues, particularly when it comes to resource handles).

You may want to use Zend_cache, for persistence

Upvotes: 0

davidethell
davidethell

Reputation: 12018

PHP isn't running like Java would where you have a JVM to maintain the state of your classes. In Java you can have a singleton behave exactly as you describe, but in PHP all the classes are refreshed with each subsequent call to the web server. So your singleton will stay in place for the duration of that call to the server, but once the response is sent then you start over again on the next call.

If you want to maintain state through successive calls you need to use the $_SESSION to keep track of your state.

EDIT: My answer above deals with PHP in general and not the Zend Framework specifically. See my comment below.

Upvotes: 2

Florent
Florent

Reputation: 12420

Try to define your component as below:

class MyApp_Helper_Breadcrum
{
    private static $_instance = null; // use private here

    public static function getInstance()
    {
        if (self::$_instance === null) { // use strictly equal to null
            self::$_instance = new self();
        }

        return self::$_instance;
    }

    private function __construct() // use private here
    {
         // ...
    }

    // ...
}

Upvotes: 0

Related Questions