Jump to content

PHP 5 - References, the common misconception. How to make an object pointer.


Recommended Posts

The wonderful & symbol or reference symbol. In order to understand what a reference is one first needs to question how PHP handles variables and their values. PHP variables and variable content are separate entities. You can have more than 1 variable point to the same content location. This is done via reference. Like so:

 

$a = 0;

$b =& $a;

 

This means that both $a and $b point to the same content. This does NOT mean that $a points to $b or vice versa (php.net). This means that if I change $a, $b will also change and vice versa. Example:

 


$a = 0;

$b =& $a;

$b = $b+1; // same as $a = $a+1;

echo($a); // $a = 1;

 

the best way to think of it is by drawing this diagram:

 

reference_example.jpg

 

This reflects that there are 2 different variable names, that point (the term point in php means reference) the same value.

 

What is the real formal definition of a reference?

References in PHP are a means to access the same variable content by different names (php.net). This means by creating a reference in PHP you effectively create another "name" that points to the same value.

 

With this in mind lets take a look at PHP5's object model.

 

PHP references are very useful in PHP OOP, or at least from the OOP I have done with PHP. References allow you to iterate though Arrays / Objects easier, help with recursion, allow you to follow good naming conventions and coding practices, and most of all save memory. Although creating a reference does create a new variable in memory and does consume memory it does NOT make a copy of the value. This can be good and bad. There are some instances where you want a copy of the object to be made, and there are instances where you do not.

 

PHP5 automatically passes object by reference. This is good, as we don't (or usually don't) want a copy of the current object we are working with, we want the current instance.

 

OK, I understand references but what is a Singleton?

 

The term singleton is a design pattern. A design pattern in a example of a piece of code (or an object) that gives building block to solves or helps to solve a complex situations (help from wikipedia.org). The singleton design pattern states that the a singleton object can only ever be instantiated once, there can only ever be one running copy of this object.

 

Why would I need this?

 

In OOP there are times when you only need, or only want (more for security or memory purposes) to instantiate a class once. For instance, a database object should only ever be instantiated once. Even if you need to connect to different databases or read and write to a database you still only ever need one database connection. A well designed (and abstracted) database object(s) will allow you to connect to different types of databases no matter where you are in the system or what type of database you are connecting to, and it will allow you to make multiple connections, or queries when generating a page.

 

So, now what do I do?

 

The interesting thing about the singleton design pattern is there is only ever one instance of the object...... Doesn't that sound like a pointer? Not exactly but it can be used as one.

 

For instance:

 

Incorrect way!

class Singleton {
      public static function getInstance() {
             ..........
      }

      public function sayHi() {
            echo("Hello there!");
            return;
      }
..........
}

$newSingelton = Singelton::getInstance(); // BAD BAD BAD 
$newSingleton->sayHi();
.....

 

What you are actually doing here is creating an instance of the class Singleton and then creating a reference to the object you just created. WHAT!!???!!

 

Remember PHP5 passes (returns) objects by reference. When you save a singleton object into a variable you create a reference to that value ... that is what a reference is and that is how PHP5 passes objects around.

 

So what is the correct way?

 

Correct Way!!

class Singleton {
      public static function getInstance() {
             ..........
      }

      public function sayHi() {
             echo("Hello there!");
             return;
      }
..........
}

Singleton::getInstance()->sayHi(); // CORRECT WAY !!!
....

 

Now that is something interesting. Having singleton objects is a MUST in good application frameworks. It avoids a lot of confusion in debugging and saves a lot of memory (especially in large applications). Because the nature of the Singleton pattern there is no need to save the object into a variable as there is only ever one reference to the object itself, and when you call it's static getInstace() method it returns the object itself, this is where object chaining comes in handy.

 

Effectively the two code examples above do exactly the same thing, the only difference is there is more overhead saving the object to a variable, and if your working with many objects, passing them to other objects, polymorphism, and other design patterns it's a good programming practice to have standardized coding, naming conventions, and to save memory.

 

I hope you enjoyed this article!!

Link to comment
Share on other sites

Nice write up :)

 

Another good practice to follow when dealing with multiple singleton objects in a large application/framework is to have a object registry that is used to reference objects stored that are commonly used within the application, this reduces the amount of callbacks to that reference and duplicate copies of it being generated which can lead to properties being repeated over and over within different objects if they are not properly unset and cause massive memory issues.

 

Magento is a good example of this while the application is very well structured there is no core registry for the singleton objects that are repeatedly referenced and the end result are massive objects that greatly influence loading times.

 

Also it also allows for easier maintaining in the future.

 

just my 2 cents )

Link to comment
Share on other sites

$newSingelton = Singelton::getInstance(); // BAD BAD BAD 

huh? Are you saying it's bad because Singelton is not defined as a class? Though, I don't know what's really bad about that. In short, it's easier to type $newSingleton->sayHi() and other methods in the class rather than having to call getInstance() every time.

Link to comment
Share on other sites

Ken2k7 I don't understand what you mean by a singleton is not defined as a class? A singleton is an object so it has to have a class. All I'm saying is you don't have to save a singleton into a variable. Yes you have to call getInstance() every time, but you don't keep creating references to that singleton every time. Also the object registry mentioned by ionik is also a good example. I only use a registry to put objects and variables into a global scope, and since you can call the singleton object from anywhere in the application framework there is no need to place it into a registry, but you can if needed. If you use the method of calling the singleton as I have stated ionik there is no need to worry about references or repeating properties you will always only get the original object.

Link to comment
Share on other sites

Nice, I didn't see that ... haha anyways you get the gist.

Yeah, I know. Saying saving a singleton into a variable is bad isn't completely right. You can say it's not necessary, but it's not bad.

 

Edit: I believe classes in general should have some singleton method. Not all classes, but most.

Link to comment
Share on other sites

as I have stated ionik there is no need to worry about references or repeating properties you will always only get the original object.

 

Yes you will always get the exact copy of the object as it was when it was first created if you do not use a registry, it can depending on how complex and involved a singleton class is result in more overhead for that class once it is initiated, more code to be written or less adaptability if that class was to ever change.

 

Example Non-Registry Setting a clone

-------------------

// Simple DB system
// Call the db object
$db = Foo_Db::getInstance();
// Do a query
$query = $db->query('SELECT * FROM foo');
while ($foo = $db->fetchAssoc($query)) {
   // Do stuff Here
}
// now we must unset the DB object to insure there is no ovearhead created from this object
// if not unset there will be multiple instances of this object everywhere we have called it
unset($db);

 

Example Non-Registry No Clone

// Simple DB system
// Call the db object
$db = Foo_Db::getInstance();
// Do a query
$query = Foo_Db::getInstance()->query('SELECT * FROM foo');
while ($foo = Foo_Db::getInstance()->fetchAssoc($query)) {
   // Do stuff Here
}

 

Example With Registry

-------------------------

// query
$query = Reg::get('db')->query('SELECT * FROM foo');
// print out results
while($fetch = Reg::get('db')->fetchAssoc($query)) {
    // echo our stuff here
}

 

As you can see from the 2 examples above they perform the same exact thing each with its pros and cons.

 

The non-registry clone example you must clone the singleton DB, and then have to make sure you unset it so you dont cause overhead from cloning the object over and over.

 

The non-registry no clone example you need to write out Foo_Db::getInstance() each time you will call the class and if the object has any properties that can change on the fly, you must write the object to a variable or property and have to unset it down the road.

 

The registry example you do need to write our Reg::get('db') every time you will call the object, but since the object is already an exact copy of what it would be if you called it using a getInstance method, you do not need to worry about having to change anything on the fly or unseating unneeded objects.

 

While it may not seem like much its only a line or 2 different between each, programmers are lazy and don't like worrying about to much, so anything that can be done in a faster less hassle free way is an advantage.

Link to comment
Share on other sites

time spent to modify passed....

 

I only use a registry to put objects and variables into a global scope

 

Which variables, if you are setting variables and then parsing them into a registry for later use to act as a global, this should be set either (1) to a constant or (2) you are not developing with strict OOP,

you should no longer need to globally set anything expect for configuration settings such as database names and program settings. If you need to globally depend on something that is getting away from the concept of OOP.....

 

A registry is meant to store program information to be used later, such as db objects, view objects, ACL systems, plug in system or any singleton class that will be used more than a few times in different areas of you program.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.