1

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

有许多 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_accountmodels/model_xxx_account.phpmodels/model_account.phpmodel_account

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

本质上,我们希望做的是在满足条件时创建不同类的实例,但来自同一个实例化调用。

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

4

4 回答 4

5

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

如果你这样做$account = new SomeClass()了,那么最终得到一个对象就没有任何意义了class Bumblebee

从技术上讲,您应该有某种帐户工厂来决定给您哪个类。

您的代码最终看起来更像$account = AccountFactory::retrieveModel(),然后它可以确定您要加载的模型,而无需委托给您的自动加载器。

自动加载器的要点本质上是说“我想要这个确切的类”,而不是摇摆不定或特别是做出任何类型的决定。您的工厂实际上可以通过您的文件结构并确定要在函数调用中传回哪个类,并且在您的代码中您不依赖于new获取您想要的模型,因为理论上您的所有帐户模型都将是共享相同的接口或至少扩展model_account.

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

于 2012-10-16T21:48:27.290 回答
2

我认为你不能。自动加载器仅帮助您选择要包含的文件,不允许您更改类。

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

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

于 2012-10-16T21:34:55.020 回答
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-

保持安全。这样您就可以确切地知道您在哪里寻找 Account Model 类。

于 2012-10-16T21:42:51.037 回答
-1

你肯定可以这样做:

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

您可以在哪里根据您的条件动态定义 $className 。

于 2012-10-16T21:35:09.627 回答