覆盖PHP类实例

时间:2012-10-16 21:27:48

标签: php class object

我目前正在开发一个项目,我们正在开发一个应用程序,用于从一组文件/托管环境中为多个站点上的内容提供支持。

有许多PHP类的名称如model_accountmodel_vehicle,它们在名为save作为类名的单独文件中定义。我们使用spl_autoload_register加载类文件,如下所示(简化):

function my_autoloader($class_name) {
    if(substr($class_name, 0, 6)=='model_') {
        require_once('models/'.$class_name.'.php');
    }
}

我们想要做的是,如果访问者访问网站xxx并且我们创建了一个类的实例,例如$account = new model_account(); - 如果文件存在,实际上创建了一个类model_xxx_account的实例({ {1}}),但如果没有,只需包含models/model_xxx_account.php文件并创建models/model_account.php的实例。

同样,如果访问者来自网站yyy,我们会希望使用model_account(如果存在),但如果不存在则完全返回model_yyy_account

基本上我们希望做的是在满足条件的情况下创建不同类的实例,但是从同一个实例化调用中创建。

我们没有使用像CI或Cake这样的现成框架。另外,我略微简化了这篇文章的命名约定。很抱歉,如果我的OO术语没有出现。

4 个答案:

答案 0 :(得分:5)

实际上听起来你应该使用某种工厂模式来处理你的类加载。

如果您执行$account = new SomeClass(),那么使用class Bumblebee的对象真的没有任何意义。

你在技术上应该有某种帐户工厂决定给你哪个班级。

您的代码最终会更像$account = AccountFactory::retrieveModel(),然后可以确定要加载哪个模型而不委托自动加载器。

自动加载器的意思是基本上说“我想要这个确切的类”,并且不要轻易摇晃或特别是做出那种类型的决定。您的工厂实际上可以通过您的文件结构并确定在函数调用中传回哪个类,并且在您的代码中您不依赖于new来获取您想要的模型,因为理论上似乎所有您的帐户模型将共享相同的界面,或至少扩展model_account

AccountFactory基本上可以说“model_yyy_account存在,因此return new model()

答案 1 :(得分:2)

我想你不能。自动装带器仅帮助您选择要包含的文件,而不允许您更改班级。

但那应该不是问题。您只需为每个网站model_account命名类。该站点确定包含哪个文件,从而实例化model_account的版本。因为您永远不会(假设)在单个请求中同时需要model_xxx_accountmodel_yyy_account,所以即使它们具有相同的名称,它们也不会相互干扰。

PS:我会将文件命名为相同,并为每个站点创建一个单独的文件夹,并为默认文件夹创建一个文件夹。这样可以更容易地发现每个站点覆盖文件并降低名称冲突的风险。

答案 2 :(得分:1)

$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

只需确保 $ SiteID 包含_和字母数字,因此对类名称友好。

永远不要从相对路径做 require_once 。总是这样:

require_once __DIR__.'/models/'.$class_name.'.php'; // PHP 5.3+
// or
require_once dirname(__FILE__).'/models/'.$class_name.'.php'; // PHP 5.2-

保持安全。通过这种方式,您可以确切地知道您在寻找帐户模型类的位置。

答案 3 :(得分:-1)

你可以肯定这样做:

$className = "MyClassName";
$myObject = new $className();

您可以根据条件动态定义$ className。