Reputation: 1116
I'm a little overwhelmed by managing a complex php oop application. In the past I've used static methods for my 'utils' classes but I'm writing a new app and I want to code to the highest standard possible so I'm look to avoid them where possible. Maintain testability etc.
I've looked at dependency injection but I'm planning to create a 'library' (so-to-speak) of helper classes that I can drop in-and-out of projects without too much trouble. My problem with this is that, because I'll have maybe five or six of these, I don't really want to set up constructs in which the user needs to pass all of these objects in to.
My research has brought me to factories - and I've created such a beast but I really don't know if this is the right way to go about things. It goes a little something like this...
class Create {
private static $validation = null;
private static $helper = null;
private static $html = null;
private static $form = null;
public static $user = null;
public static $db = null;
// --------------------------------------------------------------
// Initialize
// --------------------------------------------------------------
public static function load($object, $options, $dependencies = array('html', 'helper', 'db', 'user')) {
// Create specified object (without constructor)
// PHP version < 5.4
$$object = self::createInstanceWithoutConstructor($object);
// Inject specified options into new object
foreach($dependencies as $dependency):
if(is_null(self::$$dependency)): self::$$dependency = new $dependency; endif;
$$object->$dependency = self::$$dependency;
endforeach;
// Now call the constructor
// PHP version < 5.4
if(method_exists($$object, '__construct')):
$$object->__construct($options);
endif;
return $$object;
}
// --------------------------------------------------------------
// Create Instance of Object Without Calling it's Constructor
// --------------------------------------------------------------
// Workaround for PHP version < 5.4
// This will be updated to use
// ReflectionClass::newInstanceWithoutConstructor
// when 5.4 is more freely supported
// --------------------------------------------------------------
private static function createInstanceWithoutConstructor($class) {
$reflector = new ReflectionClass($class);
$properties = $reflector->getProperties();
$defaults = $reflector->getDefaultProperties();
$serealized = "O:" . strlen($class) . ":\"$class\":".count($properties) .':{';
foreach ($properties as $property){
$name = $property->getName();
if($property->isProtected()){
$name = chr(0) . '*' .chr(0) .$name;
} elseif($property->isPrivate()){
$name = chr(0) . $class. chr(0).$name;
}
$serealized .= serialize($name);
if(array_key_exists($property->getName(),$defaults) ){
$serealized .= serialize($defaults[$property->getName()]);
} else {
$serealized .= serialize(null);
}
}
$serealized .="}";
return unserialize($serealized);
}
// --------------------------------------------------------------
// Create User
// --------------------------------------------------------------
public static function User($options = array()) {
$user = self::load(__FUNCTION__, $options);
return $user;
}
// --------------------------------------------------------------
// Create Page
// --------------------------------------------------------------
public static function Page($options = array()) {
$page = self::load(__FUNCTION__, $options);
return $page;
}
// --------------------------------------------------------------
// Create Form
// --------------------------------------------------------------
public static function Form($name, $method = 'POST', $action = null, $attributes = array()) {
// Check to see if form was submitted
// If so, get form object, otherwise create new form object
if(isset($_POST[$name])):
$form = unserialize($_SESSION['formObj']);
$form->errors = array();
$form->rule = $form->rule;
$form->labels = $form->labels;
$form->errors = $form->errors;
else:
$form = self::load(__FUNCTION__, array(), array('html', 'validation'));
$form->name = $name;
endif;
// Open the form
$form->open($method, $action, $attributes);
return $form;
}
}
So it has separate functions for creating various objects, there is a default selection passed in unless the dependencies are explicitly set.
Now, I'm really not sure if this is a good approach, from more research, I've gathered it may be a better idea to have one factory for each class that is responsible for creating objects in that class. Is that the more 'correct' way of approaching this? If so, should those factory methods (not sure if that's the right term?) just be statics that can be called anywhere or can they just be normal methods which creates the new objects and then pass them in? Will this also need to extend a 'Factory' class which holds the created objects?
Hope that all made sense, any and all help would be appreciated.
Yours,
Confused N00b.
Upvotes: 0
Views: 147
Reputation: 87
What you listed is looks like bad attempt to make Service Locator. It's sort of registry pattern. Every class should have certain purpose. So make ServiceLocator class and number of factory classes/methods to return instances. Then set them to ServiceLocator on application startup.
Upvotes: 0
Reputation: 686
Looking at your code and reading your post, I feel like you are over-complicating things.
You don't need to focus on what is the "correct" way to do something. The correct way to do something is the way that works best for your given scenario. Look at what you need to do, look ahead to the future (but not too far!!), and try to find a solution that isn't over-designed, but gives you room to grow.
I say not too far into the future because developers often tend to get too caught up in their design, trying to plan for every possible eventuality, and you end up with a monster that is impossible to maintain.
If a series of factory functions contained in a static class is working for you, and you don't foresee any major issues with this any time soon, why do you need to keep designing? One of the hardest things to learn to do is to walk the line between designing for the future, and just getting things done :)
Upvotes: 3