tags:

views:

105

answers:

3

Hi

This is probably a really straightforward answer - but a bit of advice would be appreciated.

I have a small system where all of my objects use the same load() and loadMultiple() methods. Exactly the same code in each. Very simple, example below.

public static function load($id) {
 // Instantiate the object
 $object = new self($id);
 return $object;
}

The example code above can't go in an interface obviously, but neither can it go in an abstract class as I am instantiating the object (same in the loadMultiple method).

What is the most elegant solution to this? I am currently planning to create a parent class such as:

 class Object_Model {
    public function load() {
     // Code here
    }
    public function loadMultiple() {
     // Code here
    }
}

class Object1 extends Object_Model {
}

class Object2 extends Object_Model {
}

But I am sure there must be a better way. Is there?

A: 

As your current code uses a static method, I believe it would be just fine to have a function which takes two arguments: the name of the class to instantiate and that id:

function load($class, $id) {
    return new $class($id);
}

It's OK to implement factories using functions. Or is there more logic that you do in there that cannot be extracted in a function?

Ionuț G. Stan
A: 

If you're using PHP 5.3 you can indeed use a parent class and the new static keyword to determine the class of the child that had the static function called on it.

However I think you're best off just using the tried and true new Object1($id); method while doing all your setup tasks in your __construct method. Your code will be a little easier to read and maintain.

The load multiple example you may want to abstract out into a separate function to expedite the process.

dcousineau
Sorry dcousineau - Peter explained lsb a bit better so i gave him the answer
PJE
A: 

I agree with Ionut - just go with a traditional factory method.

<?php
abstract class A
{
  protected $id;

  protected function __construct( $id )
  {
    $this->id = $id;
  }

  final public static function factory( $subclass, $id )
  {
    // Instantiate the object
    if ( is_subclass_of( $subclass, __CLASS__ ) )
    {
      return new $subclass($id);
    }
    throw new Exception( "$subclass is not a valid class for this factory." );
  }
}

class B extends A{}
class C extends A{}
class D{}

try {
  $b = A::factory( 'B', 1 );
  $c = A::factory( 'C', 2 );
  $d = A::factory( 'D', 2 );
}
catch ( Exception $e )
{
  echo "Oops! " . $e->getMessage();
}

You might be able to do something with late static binding, but that's PHP 5.3 only

Peter Bailey
Thanks Peter. Late static binding looks perfect. But I don't think our servers will support it.I understand what you and Ionut are saying, but it just seems like a step backwards when I was so close to the elegance 5.3 is offering.
PJE