Singleton in PHP not really a Singleton?

Let's say that I have the following singleton class:

==========
<?php
class Singleton
{

      private static $instance;

      private function __construct(){}
      
      public static function getInstance()
      {
            if(!isset(self::$instance))
            {
                  $object= __CLASS__;
                  self::$instance=new $object;
            }
            return self::$instance;
      }
      
      public function displayMessage()
      {
            echo 'I am a Singleton';
      }
}
?>
==========

Now I have two scripts, test.php, and test2.php

They each look like the following:

test.php
==========
<?php

require_once "singleton.php";

$singleton=Singleton::getInstance();
$singleton->displayMessage();// display message

$singleton2=Singleton::getInstance();
$singleton2->displayMessage();// display message

print "$singleton<br />";
print "$singleton2<br />";


      
?>
==========

test2.php
==========

require_once "singleton.php";

$e = new Exception();

$singleton=Singleton::getInstance();
$singleton->displayMessage();// display message

$singleton2=Singleton::getInstance();
$singleton2->displayMessage();// display message

print "$singleton<br />";
print "$singleton2<br />";
==========

Note that test2.php has created an exception object at the top.  So the output of test and test2 is the following:

I am a Singleton
I am a Singleton
Object id #1
Object id #1

I am a Singleton
I am a Singleton
Object id #2
Object id #2

So the Singleton only acts as a 'Singleton' within the current script.  On requests to other pages, it does NOT return the same object id.  On test, the object id is #1, but on test2, the object id is 2.  So this is not really a singleton like in Java?  I don't see how it could be since there is no container.  I thought maybe PHP did something behind the scenes.  And if you put some intialization code in the private constructor, it will run on every getInstance on separate scripts.  So if you have code that connects to the database, it is no different then connecting at the top of every script.  Am I missing something??


abstractionzAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Brian BushSolutions ArchitectCommented:
Unless there is some new thing in PHP5 that I haven't seen, PHP is still completely
stateless and objects don't really persist the way they do in languages like JAVA.

So, the only way that I know of that you can create a truly persistent object is to
serve it from a daemon PHP application that you attach to at runtime.

Otherwise, the PHP script only stays alive and in memory while the page loads.

So, to answer your question about something like a database connection object...
No, I don't see any real benefit over making the connection in each script.

PHP Architect publishes a NanoBook on Design Patterns in PHP (including the
Singleton) that may be of more help:
http://www.phparch.com/shop_product.php?itemid=96

Good Luck,
--brian
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
RoonaanCommented:
PHP is still a scripting language, and as such, each script request runs in its own environment and memory space.

When you need to have persistent connections to databases or other resources you would have to resolve to the modules that provide the connections themselves. For mysql you have the mysql_pconnect(). Personally I don't exactly know what is themysqli equivalent to this function.

-r-

0
cully_larsonCommented:
Another solution would be to store your instance in a Session variable:

http://www.php.net/manual/en/ref.session.php

If the instance doesn't exist, check for it in the session.


Cully
0
Introducing Cloud Class® training courses

Tech changes fast. You can learn faster. That’s why we’re bringing professional training courses to Experts Exchange. With a subscription, you can access all the Cloud Class® courses to expand your education, prep for certifications, and get top-notch instructions.

abstractionzAuthor Commented:
How do you put the instance into the Session?

I tried placing a database connection object into the session in one script, then in another tried to retrieve it and got the following fatal error:

Fatal error: main() [function.main]: The script tried to execute a method or access a property of an incomplete object. Please ensure that the class definition "DB_Mysql" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide a __autoload() function to load the class definition in C:\phpapps\\test2.php on line 10
0
Brian BushSolutions ArchitectCommented:
To hold an object in the session you have to instance the object before
getting or setting it to the session.

// To set the object...
require_once("MyObject.php");
session_start();

$_obj = new MyObject("param1", "param2", "param3");
$_SESSION['obj'] = $_obj;

// To get the object...
require_once("MyObject.php");
session_start();

$_obj = new MyObject();
$_obj = $_SESSION['obj'];

This way, PHP knows what the object is before it loads it.
Make sense? I know it probably seems weird, but that's the
way it works in PHP.

Anyway, give it a shot.
--brian
0
abstractionzAuthor Commented:
But it would not work if using a Singleton DB Connection object.
0
Brian BushSolutions ArchitectCommented:
Right, being that the whole point of the Singleton pattern is a single instantiation.
Typically, though, the Singleton class can handle the second instantiation attempt
and basically just ignore it.

Anyway, this is a pretty complex problem. I suggest you look at the PHP Design
Patterns book to see how they treat the Singleton. I haven't had a chance yet
myself, and for this example, it is very difficult to test. You would need to look at
the instance info like you have above and monitor the database connection to
see that it does persist and is not duplicated.

In the meantime, I can tell you that holding the object in the session is a good
attempt to overcome state, but it also writes to disk and may give you no better
performance than creating a new connection with each page.

Also, part of what Cully was suggesting might be to not implement a true
Singleton pattern, but to check for the object instance in the script or session
before instantiating any new ones. Of course that is the sort of thing that
typically takes place in a Singleton class constructor.

The last thing is about the error message you were getting... The one about
an incomplete object is basically saying you have to instantiate an empty object
locally (current script) before you can assign another object, say from the session,
to it.

I know this must feel like coding in circles. Sorry I can't be of more help.
--brian
0
cully_larsonCommented:
If you're just trying to get a persistent sql connection, use a function like mysql_pconnect().

Cully
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
PHP

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.