Implementing dynamic, read-only object properties in PHP

I was recently working on a PHP project where i needed (or would of liked) an object to have publicly available properties which were read-only. Unfortunately PHP doesn’t support this and the usual way of implementing something similar was to have private properties and standard getter methods. The trouble with getter methods is that sometimes they seem a little like overkill, especially if you’re only accessing a name or an age, etc. Do you really need a method call to return a simple string or number that is always the same? Plus, in my opinion, they are harder to read than properties, although it could be argued only slightly.

But, take a look at these two lines of code:

To me the first one is much more meaningful and better reflects what it represents, not only that but if this is concatenated within another string the readability of its simplicity increases.

Magic methods

So in order to simulate properties that are read-only i need to use some PHP kung fu called magic methods.

So what are magic methods? Basically, they are special methods of a class that when defined are called when certain actions are performed on that class’ instantiated object. One simple example would be, the  __construct()  magic method which is called whenever a class is instantiated. There are 14 magic methods in total as of PHP v5.3 but the two i’ll be mainly using here are  __get()  and  __set() .

The __get() method is called when you attempt to access a property of an object that is not accessible. It receives one parameter, the name of the property trying to be accessed and it returns one value, which will be treated as the value of that property.

The __set() method is called when you attempt to change the value of an object property that is not accessible. It receives two parameters, the name of the property trying to be accessed and the new value of that property.

Okay, so lets see some code. First i’ll show you a simple class that provides a little framework for working with read-only properties.

Here i’m using an array called  $Data  to hold the read-only properties instead of defining them in the class body. When code tries to access these properties and because they can’t be found (in the class body) the  __get()  and  __set()  magic methods will trigger.

If you notice inside the  __get()  method i’m using  array_key_exists()  to test if the property trying to be accessed is actually within the  $Data  array. If it is, return its value, if it’s not, display an error.

Conversely, if code tries to set a property value (which is not accessible) the  __set()  method is triggered and just shows an error. I show an error here because i want them all to be read-only.

To demonstrate, i’ll create a simple class which inherits from the above class.

Not bad eh? Because the code is trying to access properties that don’t exist, i can re-route the request to the  $Data  array using the magic methods, very neat indeed! But wait, there’s more.

Dynamic property loading

Say for example you have a huge class that is composed of smaller classes and that each of the smaller classes need database or file access in their constructors to initialise their objects properly. If you instantiated a huge object, all the little ones would usually be instantiated at the same time, accessing their individual resources whether you actually use them or not. What would be a better scenario is that you are able to instantiate a huge object and have each of the smaller ones instantiate themselves when actually accessed.

Using the above code as a starting point, i can add dynamically instantiating objects which initialise themselves when i actually access them as properties.

Here i’ve overridden the  __get()  magic method in the  User  class with one that dynamically loads the  Address  property when accessed for the first time. Subsequent access to the same property is from the  $Data  array because  array_key_exists()  returns true on account of the Address  property now exists in the  $Data  Array. Awesome!

I’ll stop now as this post is a lot longer than i anticipated but hopefully you can see that using PHP’s magic methods you can open up new avenues in dynamic object behaviour. Take a look at the magic methods page in the PHP documentation and see how they could help in your next project.

http://php.net/manual/en/language.oop5.magic.php

No comments yet.

Submit a Comment

We would love to hear your thoughts. Feel free to submit a comment and join the conversation!

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">