Найти в Дзене

php первый класс который я написал. Автозагрузка классов.

Сегодня закончил писать класс автозагрузки классов. Задача для меня была сложная, но резукльтат понравился.
Так и хочется процитировать великого классика — «Ай да Пушкин! ...

Сегодня закончил писать класс автозагрузки классов. Задача для меня была сложная, но результат понравился.

Так и хочется процитировать великого классика — «Ай да Пушкин! Ай да сукин сын!». Безусловно я адекватно понимаю, что моя сегодняшняя работа может мне нравится только на том уровне обучения на котором я нахожусь сейчас. Более того я знаю что есть composer который решает проблему автозагрузки намного проще и вообще похоже является стандартом.

Так почему же я доволен как слон после клизмы изобретя очередной велосипед?

Да очень просто я сделал что-то сам. Решил задачу которая мне раньше казалось архисложной. А тут вот сел, подумал и решил! Эмоции переполняют, хочется продолжать учиться дальше, писать новый код, решать следующие задачи.

Так же Autoloader должен загружать классы через namespace из разрешённых папок app и vendor, а вслучае если приложение работает в режиме разработчика, тогда классы должны загружаться ещё и из папки test.Теперь о самом классе автозагрузки.
Перед собой я поставил задачу написать класс который будет автоматически загружать классы без постоянных require в каждом файле. При этом все системные классы должны загружаться из так называемой карты классов. Карта классов это массив в котором содержатся имена всех классов и пути к файлам.

И ещё один момент нужно учесть. Для себя я принял соглашение заканчивать имена всех классов .class.php. Однако если я захочу использовать стороннюю библиотеку. Но где гарантия что разработчик библиотеку которого я решу установить будет делать также? Конечно нигде и высока вероятность что в сторонней библиотеке файлы будут иметь расширение .php без явного указания, что это именно класс.

Вот что у меня получилось:

<?php

class Autoloader
{
private static $istance;

private function __construct()
{
spl_autoload_register( [ $this , 'load' ] , true , false );
}

public static function getInstance()
{
if (!isset(self::$istance)) {
self::$istance = new self;
}
return self::$istance;
}

private function load ( $class )
{
require_once $this->getClass( $class );
}

private function getClass($class)
{
$namespace = explode( '\\' , $class );
$path = isset($namespace[1]) ? $this->otherClasses($class) : $this->systemClasses($class);

try {
if ( !is_readable( $path )) {
throw new Exception( 'Нет файла с классом: ' . $class );
}
return $path;
} catch (Exception $e) {
echo $e->getMessage();
die();
}
}

private function systemClasses ( $class )
{
$map = './core/config/MapClasses.php';
require $map;

try {
if ( !isset( $mapClasses[$class] )) {
throw new \Exception( ' Класс ' . $class . ' не зарегистрирован' );
}
return $mapClasses[$class];
} catch (Exception $e) {
echo $e->getMessage();
die();
}
}

private function allowedFoldersLoadingClasses()
{
$folders = [
'app',
'vendor'
];
if ( 'DEV' === MODE ) {
$folders[] = 'test';
}

return $folders;
}

private function otherClasses ( $class )
{
foreach ($this->allowedFoldersLoadingClasses() as $dir) {
$file = './' . $dir . '/' . str_replace( '\\' , '/' , $class ) . '.class.php';
if (!is_file($file)) {
$file = './' . $dir . '/' . str_replace( '\\' , '/' , $class ) . '.php';
}

if (is_file( $file )) {
$path = $file;
return $path;
}
}
return false;
}

private function __clone () {}
}

Попутно прилось немного поправить файл с картой классов теперь он выглядит так:

<?php

$mapClasses = [
'Route' => './core/classes/utils/Route.class.php',
'UrlParse' => './core/classes/utils/UrlParse.class.php'
];

Тесты я пока писать не научился, однако в целях тестирования я всё же создал несколько файлов с классами для тестов.

В папке app/blog я создал файл Controller.class.php с кодом

<?php
namespace blog;

class Controller
{
public function __construct()
{

}

public static function blog()
{
echo __METHOD__;
}
}

Здесь один статический метод который просто выводин на экран название метода blog.

Так же в файле Route.class.php

<?php

class Route
{
public static function bootstrap()
{
echo __METHOD__;
}

}

И в файле UrlParse.class.php

<?php

class UrlParse
{
public function __construct()
{

}

public static function urlParse()
{
echo __METHOD__;
}
}

И в папке test/testAutoloader создал файл TestAutoloader.php

<?php

namespace testAutoloader;

class TestAutoloader
{
public function test($a)
{
$a = $a+$a;
echo $a;

}

}

Таким образом Controller.class.php и TestAutoloader.php должны загрузиться с помощью namespace. При этом класс TestAutoloader имеет расширение .php в отличие от класса Controller у которого расширение .class.php. Классы Route и UrlParse прописанны в карте классов.

Открываю файл index.php и вношу в него несколько строк для вызова вновь созданных классов:

<?php

$systemCofig = __DIR__ . '/core/config/SystemConfig.php';

if (!is_readable($systemCofig)) {
header('location:install.php');
die('Нет файла конфигурации');
}

require_once $systemCofig;
Route::bootstrap();
echo '<hr>';
UrlParse::urlParse();
echo '<hr>';
\blog\Controller::blog();
echo '<hr>';
$test = new \testAutoloader\TestAutoloader;
$test->test(10);

Иду в браузер и вижу результат

-2

Олично все 4 класса загрузились, всё работает как я и планировал!

Продолжение следует…