Reputation: 385
I'm currently working on a project where we are developing an application that will be used to power content on multiple sites from a single set of files / hosting environment.
There are a number of PHP classes with names such as model_account
and model_vehicle
which are defined in seperate files named the save as the class name. We are using spl_autoload_register
to load the class files as below (simplified):
function my_autoloader($class_name) {
if(substr($class_name, 0, 6)=='model_') {
require_once('models/'.$class_name.'.php');
}
}
What we want to do, is if the visitor is accessing site xxx and we create an instance of a class, eg $account = new model_account();
- actually create an instance of class model_xxx_account
if the file exists (models/model_xxx_account.php
), but if it doesn't, just include the models/model_account.php
file and create an instance of model_account
.
Likewise, if a visitor came from site yyy, we would want to use model_yyy_account
if exists, but full back to model_account
if it doesn't.
Essentially what we wish to do is create an instance of a different class if conditions are met, but from the same instantiation call.
We're not using an off-the-shelf framework like CI or Cake. Also, I've slightly simplified the naming conventions for this post. Sorry if my OO terminology isn't spot on.
Upvotes: 1
Views: 490
Reputation: 1844
It actually sounds like you should be using some sort of factory pattern to deal with your class loading.
If you do $account = new SomeClass()
, it does not make any sense to ever really end up with an object of class Bumblebee
.
You should technically have some sort of account factory that decides which class to give you.
You code will end up looking more like $account = AccountFactory::retrieveModel()
, which then can determine which model you want to load WITHOUT delegating to your autoloader.
The point of the autoloader is to essentially say "I want THIS exact class", and isn't to be wibbly wobbly or in particular be making any sort of decisions of that sort. Your factory can actually go through your file structure and determine which class to pass back in the function call, and in your code you aren't relying on new
to get the model you want, since it seems in theory all of your account models will be sharing the same interface or at least extending model_account
.
AccountFactory can essentially say, "model_yyy_account
exists, thus return new model()
.
Upvotes: 5
Reputation: 12985
$SiteID = 'xxx'; // Modify as you wish from your subdomain or whatever
// class_exists triggers the autoloader
if(!class_exists($ClassName = "model_{$SiteID}_account")){
// If class is missing, fall back to default
$ClassName = "model_account"; // This should exist
}
$Model = new $ClassName(); // Instantiate your Account Model
Just make sure $SiteID contains _ and alphanumerics hence is class name friendly.
And never do require_once from relative paths. Alway do:
require_once __DIR__.'/models/'.$class_name.'.php'; // PHP 5.3+
// or
require_once dirname(__FILE__).'/models/'.$class_name.'.php'; // PHP 5.2-
to stay safe. This way you know exactly where you are seeking the Account Model class.
Upvotes: 1
Reputation: 3065
You can certain do this:
$className = "MyClassName";
$myObject = new $className();
Where you can dynamically define $className based on what your conditions are.
Upvotes: -1
Reputation: 116100
I think you can't. The autoloader only helps you selecting a file to include, not allowing you to change the class.
But that shouldn't be a problem. You can just name the classes for each website model_account
. The site determines which file gets included and thus which version of model_account
is instantiated. Because you will never (assumption) need both model_xxx_account
and model_yyy_account
in a single request, they won't interfere which each other, even if they have the same name.
PS: I would name the files the same as well, and create a separate folder for each site and a folder with defaults. That will make it easier to spot overriden files per site and shrinks the risk of name clashes.
Upvotes: 2