That is the question!
I’m re-doing some legacy PHP code and converting a lot of it from procedural to OOP. I’ve written a few classes that are needed by lots of other classes, like Database, Config and Prefs classes. But these classes only need to be instantiated or “initialized” once, but accessible to all classes or objects that need them. I was introduced to Singletons with a static method that instantiates itself, which works well. But I thought there could be a simpler, “cleaner” way of doing this.
After doing a bit more research, I found this interesting comment in an interesting thread on Stack Overflow about instantiated vs. static classes: http://stackoverflow.com/questions/1185605/when-to-use-static-vs-instantiated-classes/31282644#31282644
I happen to completely agree with him and like this approach. I am considering converting the 3 classes I mentioned above to have all static properties and methods, no instantiation, and instead a method called init()
that basically works like the __construct()
class and does any setup needed by the class, such as filling all the properties in the Prefs class with user preferences from the database that can be accessed from any other class, sort of like this:
class Prefs
{
private static $init = false;
public static $timezone;
public static $language;
public static $theme;
function __construct() {} // not needed, will never be instantiated
public static function init()
{
if (!self::$init) {
$prefs = DB::select("SELECT * FROM prefs WHERE id=9999");
self::$timezone = $prefs['timezone'];
self::$language = $prefs['language'];
self::$theme = $prefs['theme'];
// set flag to avoid re-loading if init() called again
self::$init = true;
}
}
// Other functions related to Preferences will follow
}
This would allow me to simply call Prefs:init()
in my main script once, and then all other classes can access its properties and methods using Prefs::$timezone
, for example. I’d like to set up a static version of the __get()
magic method so I can make all the properties protected, but I’m still working out the best way to do that.
If you read any of the other comments in that Stack Overflow thread, you’ll see lots of people saying to avoid static stuff and to pass instantiated objects to other classes that need it, blah blah blah. But I find this very cumbersome for certain classes that are needed by many other classes. I wish there were global objects, that would make things a lot easier (why aren’t there any?). But that solution I linked to above would achieve exactly what I want without self-instantiation or creating singletons.
So, what’s wrong with setting things up the way he described? Why are static properties and methods available in OOP if they should be avoided? Why is it necessary to instantiate all classes?
To be clear, I’m not developing an application that’s going to be sold or used by lots of people, so portability or unit testing is not a high priority. I know I could achieve something similar with a function library, but, I like how classes with static properties and methods keep things compartmentalized yet global without cluttering the global space.