Лучший способ автозагрузки классов в PHP
Я работаю над проектом, в котором у меня есть следующая структура файла:
index.php
|---lib
|--|lib|type|class_name.php
|--|lib|size|example_class.php
Я хотел бы автоматически загрузить классы class_name и example_class (названные так же, как и классы PHP), чтобы в index.php классы уже были созданы, чтобы я мог сделать:
$class_name->getPrivateParam('name');
Я посмотрел в сети, но не могу найти правильный ответ - кто-нибудь может мне помочь?
РЕДАКТИРОВАТЬ
Спасибо за ответы. Позвольте мне расширить мой сценарий. Я пытаюсь написать плагин WordPress, который можно добавить в проект и добавить дополнительные функциональные возможности, поместив класс в папку "функциональные возможности", например, внутри плагина. Там никогда не будет 1000 классов, на толчок, может быть, 10?
Я мог бы написать метод для перебора структуры папок в папке 'lib', включая каждый класс, затем присвоение его переменной (имени класса), но не думал, что это очень эффективный способ сделать это, но это возможно, кажется, что это лучший способ добиться того, что мне нужно?
8 ответов
Пожалуйста, если вам нужно автозагрузить классы - используйте пространства имен и соглашения о именах классов с автозагрузкой SPL, это сэкономит ваше время на рефакторинг. И, конечно же, вам нужно создать экземпляр каждого класса как объекта. Спасибо.
Как в этой теме: автозагрузка PHP в пространствах имен
Но если вам нужен сложный обходной путь, взгляните на класс автозагрузки Symfony: https://github.com/symfony/ClassLoader/blob/master/ClassLoader.php
Или вот так (я сделал это в одном из моих проектов):
<?
spl_autoload_register(function($className)
{
$namespace=str_replace("\\","/",__NAMESPACE__);
$className=str_replace("\\","/",$className);
$class=CORE_PATH."/classes/".(empty($namespace)?"":$namespace."/")."{$className}.class.php";
include_once($class);
});
?>
и тогда вы можете создать экземпляр своего класса следующим образом:
<?
$example=new NS1\NS2\ExampleClass($exampleConstructParam);
?>
и это ваш класс (находится в /NS1/NS2/ExampleClass.class.php):
<?
namespace NS1\NS2
{
class Symbols extends \DB\Table
{
public function __construct($param)
{
echo "hello!";
}
}
}
?>
Если у вас есть доступ к командной строке, вы можете попробовать это с помощью composer в разделе classMap примерно так:
{
"autoload": {
"classmap": ["yourpath/", "anotherpath/"]
}
}
тогда у вас есть плагин WordPress для включения композитора в WordPress Cli: http://wordpress.org/plugins/composer/
function __autoload($class_name) {
$class_name = strtolower($class_name);
$path = "{$class_name}.php";
if (file_exists($path)) {
require_once($path);
} else {
die("The file {$class_name}.php could not be found!");
}
}
ОБНОВИТЬ:__autoload()
устарело с версии PHP 7.2
У меня есть пример, который я использую для автозагрузки и инициализации.
По существу, лучшая версия spl_autoload_register, поскольку она пытается запросить файл класса только при инициализации класса.
Здесь он автоматически получает каждый файл в папке вашего класса, запрашивает файлы и инициализирует его. Все, что вам нужно сделать, это назвать класс так же, как файл.
index.php
<?php
require_once __DIR__ . '/app/autoload.php';
$loader = new Loader(false);
User::dump(['hello' => 'test']);
autoload.php
<?php
class Loader
{
public static $library;
protected static $classPath = __DIR__ . "/classes/";
protected static $interfacePath = __DIR__ . "/classes/interfaces/";
public function __construct($requireInterface = true)
{
if(!isset(static::$library)) {
// Get all files inside the class folder
foreach(array_map('basename', glob(static::$classPath . "*.php", GLOB_BRACE)) as $classExt) {
// Make sure the class is not already declared
if(!in_array($classExt, get_declared_classes())) {
// Get rid of php extension easily without pathinfo
$classNoExt = substr($classExt, 0, -4);
$file = static::$path . $classExt;
if($requireInterface) {
// Get interface file
$interface = static::$interfacePath . $classExt;
// Check if interface file exists
if(!file_exists($interface)) {
// Throw exception
die("Unable to load interface file: " . $interface);
}
// Require interface
require_once $interface;
//Check if interface is set
if(!interface_exists("Interface" . $classNoExt)) {
// Throw exception
die("Unable to find interface: " . $interface);
}
}
// Require class
require_once $file;
// Check if class file exists
if(class_exists($classNoExt)) {
// Set class // class.container.php
static::$library[$classNoExt] = new $classNoExt();
} else {
// Throw error
die("Unable to load class: " . $classNoExt);
}
}
}
}
}
/*public function get($class)
{
return (in_array($class, get_declared_classes()) ? static::$library[$class] : die("Class <b>{$class}</b> doesn't exist."));
}*/
}
Вы можете легко управлять с небольшим количеством кода, требуя классов в разных папках тоже.
Надеюсь, это может быть полезным для вас.
http://php.net/manual/de/function.spl-autoload-register.php
spl_autoload_register(function ($class) {
@require_once('lib/type/' . $class . '.php');
@require_once('lib/size/' . $class . '.php');
});
сделайте это в файле и назовите его как-нибудь вроде (mr_load.php), это были все ваши классы
spl_autoload_register(function($class){
$path = '\Applicaton/classes/';
$extension = '.php';
$fileName = $path.$class.$extension;
include $_SERVER['DOCUMENT_ROOT'].$fileName;
})
;
- затем создайте еще один файл и включите mr_load.php; $load_class = новая автобусная остановка(); $load_class->метод()
С помощью этого автозагрузчика можно указать удобную для пространств имен автозагрузку.
<?php
spl_autoload_register(function($className) {
$file = __DIR__ . '\\' . $className . '.php';
$file = str_replace('\\', DIRECTORY_SEPARATOR, $file);
if (file_exists($file)) {
include $file;
}
});
Убедитесь, что вы правильно указали расположение файла класса.
spl_autoload_register(function ($class_name) {
$iterator = new DirectoryIterator(dirname(__FILE__));
$files = $iterator->getPath()."/classes/".$class_name.".class.php";
if (file_exists($files)) {
include($files);
} else {
die("Warning:The file {$files}.class.php could not be found!");
}
});