This previous question显示了如何强制所有类的自动加载。
但是我需要自己强制自动加载一个类。我怎么能这样做?
它不能:
此外,最好不要将类的名称编码为字符串。 (帮助IDE重构等)。
我到目前为止找到的最佳选择是使用spl_autoload_call()
:
spl_autoload_call("Jodes\\MyClass");
或非命名空间类:
spl_autoload_call("MyClass");
答案 0 :(得分:1)
我最近有同样的需求。执行require_once
不是一个选项,因为由于一些更复杂的规则,自动加载器确实需要定位类,所以无法准确知道该类文件的路径。
虽然函数spl_autoload_call($classname)
的目的是为了做到这一点,但是它存在一个根本性的缺陷:它会抛出致命错误,以防你为同一个类名调用它两次甚至如果该类的某些子类已经加载。这是因为它无法在PHP中重新声明类:
<?php
spl_autoload_call('TheClass');
// no problem
spl_autoload_call('TheClass');
// PHP Fatal error: Cannot declare class TheClass, because the name is already in use in ... on line ...
我对此问题的解决方案不依赖于class_exists($classname)
的副作用,这种副作用并非为此目的而设计,而是更具可配置性,因此可以更好地控制触发自动加载器。
更好的是,它在多次调用或者已经在继承链中加载了某些内容时完全没有问题。它只是具有需要文件的副作用(如果你想),如果该类还没有!
<?php
class_exists('TheClass');
// no problem
class_exists('TheClass');
// already exists. No need to autoload it and no fatal errors!
通过这种方式,您可以通过自动加载器加载类,这是一种安全且幂等的方法。
而且,如果您不想在其中使用类名对字符串进行硬编码,那么从PHP 5.5开始,您可以使用::class
伪常量,该常量在编译时解析为具有完全限定类名的字符串(包括名称空间):
<?php
class_exists(TheClass::class);
答案 1 :(得分:0)
我对此采取了不同的方法,可能不是最好的方法,但它对我来说是最好的方法之一。它确实涉及修改源代码,但实现起来非常简单。
我通常有一个名为Core
<?php
require_once("{$_SERVER['DOCUMENT_ROOT']}\Matilda\class\Settings.class.php");
require_once("{$_SERVER['DOCUMENT_ROOT']}\Matilda\class\Auth.class.php");
require_once("{$_SERVER['DOCUMENT_ROOT']}\Matilda\class\Permissions.class.php");
require_once("{$_SERVER['DOCUMENT_ROOT']}\Matilda\class\Procedures.class.php");
require_once("{$_SERVER['DOCUMENT_ROOT']}\Matilda\class\Audit.class.php");
class Core {
/**
* @var External class
*/
public $Settings,$Sql,$Auth,$Permissions,$Payroll,$Customers,$Plans,$Billing,$Engin,$AAPT,$Stock,$Prospects,$Freeside,$Audit;
/**
* @var Base Config
*/
private $InitConfig = array(
'Payroll' => false,
'Customers' => false,
'Plans' => false,
'Billing' => false,
'Engin' => false,
'AAPT' => false,
'Stock' => false,
'Prospects' => false,
'Freeside' => false,
);
public function __construct($Config = array()) {
// Session instantiation
if (!isset($_SESSION)) session_start();
if (!is_array($Config)) die('Core instantiation parameter must be an array, even if its empty');
$this->InitConfig = array_merge($this->InitConfig, $Config);
// Base classes
$this->Settings = new Settings();
$this->Sql = new MySQLi(/* Mysql info */)
$this->Audit = new Audit($this->Settings, $this->Sql);
$this->Auth = new Auth($this->Settings, $this->Sql, $this->Audit);
$this->Permissions = new Permissions($this->Settings, $this->Sql, $this->Auth, $this->Audit);
// Optional class handling
foreach ($this->InitConfig as $Dependency => $State) {
if ($State == true) {
require_once($this->Settings->RootDir . "/class/{$Dependency}.class.php");
$this->$Dependency = new $Dependency($this->Settings, $this->Sql, $this->Auth, $this->Permissions, $this->Audit);
}
}
}
这几乎说明了我如何提供可选的加载配置。
它有5个默认类,因此无论如何都会加载:设置,验证,权限,程序和审计
然后我可以实例化可选类:$Core = new Core(array('Payroll' => true))
,它将实例化Payroll.class.php
并可通过$Core->Payroll
这几乎是存储树级功能的好方法
$Core->Members->FetchMemberByID($ID);
$Core->Plans->CreateNewPlan($PlanName, $Monthly, $Attributes = array())
etc etc.
有些人可能会因此而打我,但我个人认为这是一种相对不错的方式来实现你想要的,尽管不是你通常喜欢的方法(不是改变代码)。
同样方便的是允许为您正在制作的任何内容创建插件:)