views:

226

answers:

5

I'm thinking about putting every class into a separate file and doing the static initialization outside of the class definition.

The problem with this is the fact that the initialization will happen before the said class is actually needed (it will happen when the file which contains the class is included for the first time). It's a problem, because it may happen that the class won't be used at all, hence the initialization is unnecessary. And I think the practice of including the used files not in the beginning of your code is simply a dirty technique.

If anybody has a viable solution to this problem, I would greatly appreciate it.

+3  A: 

Take a look at code like this. It uses a singleton instance of the database yet you can still create instances of the class:

class DB
{
    private static $_db;

    public static function pdo()
    {
        if (is_null(self::$_db))
        {
            self::$_db=new PDO('pgsql:host=localhost;
                                port=5432;
                                dbname=testdb;
                                user=postgres;
                                password=abc123');
            self::$_db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        }

        return self::$_db;
    }

public static function factory()
{
    return new self;
}

private function __construct() {}

When you want an instance of the DB, you do DB::factory(). DB uses self::pdo() to return the singleton to access the database.

ryeguy
Thank you, but I've already done this. My problem is that you will have to perform the null check every time you define further methods that would use the static $_db variable to avoid throwing exceptions. This may imply some serious performance penalty.
kahoon
A single null check is hardly a performance hit at all. If you want to use this kind of design pattern, then this is your only choice. You asked for a workaround for something PHP does not natively support; you have to give something up.
ryeguy
I just checked, I can do about 1 million is_null comparisons per second on an older dual core laptop. Do you really think that matters? There is a point where performance doesn't matter if expressibility and ease-of-use is affected.
ryeguy
Extra 2-3 lines of code on top of every function is not a good idea and IMO its a smelly code. What if you forgot to check on top of a function which is always called after another. You will not notice it until to a point where maintenance guy changes the order of calls and find himself in trouble.
Cem Kalyoncu
+1  A: 

You might look up for __autoload when a class is not found it is called and supposed to include the file contains that class. You can put static initializers in that function.

Cem Kalyoncu
You can put static initializers to the PHP files that includes the class and let __autoload to include class files for you. That way manually including class file will not cause any problem.
Cem Kalyoncu
I didn't know about __autoload, and I really like this solution. I believe this is the closest I can get to emulate the desired functionality. Another good thing is that I can avoid including every single needed file one by one; I'll just make a file which contains the __autoload method and let it do the work when it's needed. Thank you!
kahoon
This is what we do for our classes, managing 40-50 classes using includes is very hard. I wish there was a method to do the same for JS. We end up adding lots of unnecessary JS files.
Cem Kalyoncu
A: 

Use singleton pattern instead of static calls:

<?php
class Foo {

   protected static $_instance;

   /**
   * @return Foo
   */
   public static function getInstance() {
        return (null === self::$_instance)? 
            self::$_instance :
            self::$_instance = new Foo();
   }

   protected function __construct() {
        // initialize here
   }
}
disjunction
A: 

This is the way I do this. The only cost is testing the $doneinit static member each time you construct.

class Foo {
   private static $doneinit=false;

   private static init() {
      // do static initialisation here

      self::$doneinit=true;
   }

   public function __construct() {
      if (!self::$doneinit) self::init();

      // go on to do the rest of construction
   }
}

Simple, and it keeps everything within the class.

Peter Bagnall
A: 

The singleton answer has a problem here... if you use the static methods before an instance of the class is created... then the static initializer has not run... so you might say that one can run the initializer in every static method... that is true but what about just getting and setting static variables... I suppose one could also use __get and __set magic functions for this... there is just a problem with the language in that it does not support static intialization... here is the way it can be done...

in file Hi.php: class Hi{ public static $v = "0"; }

Hi::$v= "2"; // end of Hi.php file

simple use a .php file per class... and do the static initialization outside of the class definition...

Ed Roberts