Сам __autoload:
function __autoload($class)
{
$class = @explode('\\', $class);
$path = ROOT . implode('/', $class) . '.php';
if( file_exists($path) ) require $path;
}
Ни чего особенного
Сегодня в проект решил подключить PHP Html Parser.
Все библиотеки я расположил в App/Libraries.
Данного пути нет в классах подключаемой библиотеки.
И получаю что то вроде:
Fatal error: Uncaught Error: Class 'App\Libraries\PHPHtmlParser\Dom' not found
Его конечно же можно дописать во все namespace, но это как то не тру.
Завтра будут другие библиотеки...
Решил попробовать так:
function __autoload($class)
{
$class = @explode('\\', $class);
$_aPath = implode('/', $class) . '.php';
$path1 = ROOT . $_aPath;
$path2 = ROOT . 'App/Helpers' . $_aPath;
$path3 = ROOT . 'App/Libraries' . $_aPath;
if( file_exists($path1) ) require $path1;
else if( file_exists($path2) ) require $path2;
else if( file_exists($path3) ) require $path3;
}
Все равно не нравится.
Можно как то во время require указать рутовый namespace?
Возможно есть какое то другое решение?
Или все все печально и таки придется дописывать?
UPDATE
Спасибо @Мелкий, переписал:
function autoloadClass($class)
{
$class = @explode('\\', $class);
$path = ROOT . implode('/', $class) . '.php';
if( file_exists($path) ) require $path;
}
spl_autoload_register('autoloadClass');
Прислушался к @etki и решили попробовать composer.
cd project
composer init && composer update
Было:
require_once ROOT.'Core/Autoload.php';
\Core\Database::$db = new \Core\Database(...);
Стало:
$loader = require 'vendor/autoload.php';
$loader->add('Core\\', __DIR__.'/Core/');
\Core\Database::$db = new \Core\Database(...);
И вот тут я наверное не дочитал что то:
Fatal error: Uncaught Error: Class 'Core\Database' not found
По старому ессно работает.
Что делаю не так?
Вариант без Composer
У меня уже есть работающий проект на/по PSR-0.
Повторюсь, вот так подгружаются классы в проекте:
function autoloadClass($class)
{
$class = @explode('\\', $class);
$path = ROOT . implode('/', $class) . '.php';
if( file_exists($path) ) require $path;
}
spl_autoload_register('autoloadClass');
По примеру автозагрузки PSR-4 делаем скрипт для внешних библиотек.
Я сделал так:
namespace Core;
class AutoLoaderPSR4
{
protected $prefixes = array();
public function register(){ spl_autoload_register(array($this, 'loadClass')); }
public function addNamespace($prefix, $base_dir, $prepend = false)
{
$prefix = trim($prefix, '\\') . '\\';
$base_dir = rtrim($base_dir, DIRECTORY_SEPARATOR) . '/';
if( isset($this->prefixes[$prefix]) === false ) $this->prefixes[$prefix] = array();
if( $prepend ) array_unshift($this->prefixes[$prefix], $base_dir);
else array_push($this->prefixes[$prefix], $base_dir);
}
public function loadClass($class)
{
$prefix = $class;
while( false !== $pos = strrpos($prefix, '\\') )
{
$prefix = substr($class, 0, $pos + 1);
$relative_class = substr($class, $pos + 1);
$mapped_file = $this->loadMappedFile($prefix, $relative_class);
if( $mapped_file ) return $mapped_file;
$prefix = rtrim($prefix, '\\');
}
return false;
}
protected function loadMappedFile($prefix, $relative_class)
{
if( isset($this->prefixes[$prefix]) === false ) return false;
foreach( $this->prefixes[$prefix] as $base_dir )
{
$file = $base_dir . str_replace('\\', '/', $relative_class) . '.php';
if( $this->requireFile($file) ) return $file;
}
return false;
}
protected function requireFile($file)
{
if( file_exists($file) )
{
require $file;
return true;
}
return false;
}
}
Далее в нужном месте (на примере того же PHPHtmlParser) :
$loader = new \Core\AutoLoaderPSR4();
$loader->addNamespace('PHPHtmlParser', ROOT.'App/Libraries/PHPHtmlParser');
$loader->addNamespace('stringEncode', ROOT.'App/Libraries/stringEncode');
$loader->register();
$dom = new \PHPHtmlParser\Dom();
$dom->load($strHTML);
Пока полет нормальный.
Надеюсь кому-то пригодится.
Изобретаете велосипед. Стандартными методами самого composer можно решить подгрузку классов намного проще. Например, у вас есть проект с такой структурой:
├── apps
│ ├── config
│ │ ...
│ └── controllers
│ ├── api
│ │ └── ContactsController.php
│ └── web
│ └── WebController.php
├── library
│ ...
├── views
│ ...
├── public
│ └── index.php
├── vendor
│ ├── autoload.php
│ ...
├── composer.json
└── composer.lock
Тогда вам достаточно поправить свой composer.json следующим образом, чтобы подгружать классы, в соответствующих папках и пространствах имен:
{
...
"autoload": {
"psr-4": {
"YourApp\\Controllers\\Web\\": "apps/controllers/web",
"YourApp\\Controllers\\API\\": "apps/controllers/api"
}
}
}
После этого вы можете спокойно использовать эти классы, через use YourApp\Controllers\Web\ContactsController, например.
Современные инструменты для криптотрейдинга: как технологии помогают принимать решения
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости