关注此question,似乎只需使用下面的__autoload
代码即可解决重复问题,
function __autoload($class_name)
{
include AP_SITE."classes_1/class_".$class_name.".php";
}
$connection = new database_pdo(DSN,DB_USER,DB_PASS);
var_dump($connection);
结果,
object(database_pdo)[1]
protected 'connection' =>
object(PDO)[2]
但这仅从一个目录加载类,其他目录呢?因为我将类分组在不同的目录中。因此,如果我想从其他目录加载类,我将收到错误
function __autoload($class_name)
{
include AP_SITE."classes_1/class_".$class_name.".php";
include AP_SITE."classes_2/class_".$class_name.".php";
}
消息
警告: 包括(C:/wamp/www/art_on_your_doorstep_2011_MVC/global/applications/CART/classes_2/class_database_pdo.php) [function.include]:无法打开流:没有这样的文件或目录 在......
引用此行 - include AP_SITE."classes_2/class_".$class_name.".php";
所以,我的问题是 - 如何使用__autoload
从多个目录加载类?
可能的解决方案:
function autoload_class_multiple_directory($class_name)
{
# List all the class directories in the array.
$array_paths = array(
'classes_1/',
'classes_2/'
);
# Count the total item in the array.
$total_paths = count($array_paths);
# Set the class file name.
$file_name = 'class_'.strtolower($class_name).'.php';
# Loop the array.
for ($i = 0; $i < $total_paths; $i++)
{
if(file_exists(AP_SITE.$array_paths[$i].$file_name))
{
include_once AP_SITE.$array_paths[$i].$file_name;
}
}
}
spl_autoload_register('autoload_class_multiple_directory');
答案 0 :(得分:5)
您可以使用spl_autoload_register
而不是单__autoload
个功能注册多个自动加载功能。这是推荐的方式。
如果一个自动加载器能够加载该文件,则不会调用堆栈中的下一个。
然而,每个自动加载器只应加载它所用的类,因此您需要通过类名和/或is_file
来检查它。通过classname通常会更好,因为如果应用程序增长,在文件系统上疯狂地尝试会给系统带来压力。
为了不重新发明轮子,你甚至可以使用已经存在的自动加载器,它能够处理文件名调用的PSR-0标准。这些通常允许在基本目录上注册特定的命名空间。在您的情况下,这意味着您必须根据PSR-0 convention重新命名和整理文件。
快速解决方案(绑定到您的问题):
function __autoload($class_name)
{
$file = sprintf('%sclasses_1/class_%s.php', AP_SITE, $class_name);
if (is_file($file))
{
include $file;
return;
}
$file = sprintf('%sclasses_2/class_%s.php', AP_SITE, $class_name);
if (is_file($file))
{
include $file;
return;
}
}
正如您所看到的,已经存在重复的代码(如在您的代码中)。因此,这应该只是一个临时解决方案,因为您最终会为要测试的每个目录提供越来越多的重复行。如果您考虑更改设计,请考虑PSR-0 shema,它有助于简化一个代码库,并且可以轻松地重用PHP世界中的其他现有组件。
function autoload_class_multiple_directory($class_name)
{
# List all the class directories in the array.
$array_paths = array(
'classes_1/',
'classes_2/'
);
foreach($array_paths as $path)
{
$file = sprintf('%s%s/class_%s.php', AP_SITE, $path, $class_name);
if(is_file($file))
{
include_once $file;
}
}
}
spl_autoload_register('autoload_class_multiple_directory');
答案 1 :(得分:2)
执行此操作的正确方法是采用PSR-0 naming convention,然后使用兼容PSR-0的自动加载器,例如来自Symfony2的ClassLoader组件的UniversalClassLoader
。
例如:
<强>一个/ SRC /项目A /数据库/ Pdo.php 强>:
<?php
namespace ProjectA\Database;
class Pdo
{
// your code
}
<强> B / SRC /项目B /邮件/ Smtp.php 强>:
<?php
namespace ProjectB\Mail;
class Smtp
{
// your code
}
symfony ClassLoader位于vendor/symfony/src/Symfony/Component/ClassLoader
。
<强> autoload.php 强>:
<?php
require __DIR__.'/vendor/symfony/src/Symfony/Component/ClassLoader';
use Symfony\Component\ClassLoader\UniversalClassLoader;
$loader = new UniversalClassLoader();
$loader->registerNamespace('ProjectA', __DIR__.'/a/src');
$loader->registerNamespace('ProjectB', __DIR__.'/b/src');
$loader->register();
这实际上是使用spl_register_autoload
来注册自动加载器,它尝试将所请求的类与所有已注册的路径匹配,如果匹配,则需要。否则自动装带器将继续搜索。
所以你的引导代码所做的是包括autoload.php
,之后所有其他类都将被自动加载。