Клиентский код. Пространство имен

Привет, Хабр!

У меня появилась необходимость отделить проект от фреймворка. Благо кода фреймворка в проекте было не так много, но избавиться от него тоже нужно.

Поэтому было принято решение переписать функционал который он покрывал.
Одной из используемых функций фреймворка было - построение пространства имен.

Пространство имен, проще говоря, создано что-бы задавать область видимости кода для другого кода. Используя пространство имен можно гарантировать что клиентский код не будет зависеть от названия: переменных, функций, класса, и всего чего угодно в коде, в том числе при подключении нескольких библиотек тоже можно не переживать. Клиентский код будет зависить только от результата работы кода.

Удачно получилось что тема пересекается с моей статьей. Может если это будет серия статьей с пометкой Клиентский код, то мне получится лучше донести что же все-таки это за код такой.

Еще более удачно что язык PHP продуман разработчиками для удобства программиста (создателя клиентского кода). PHP позволяет привязать нам пространство имен к файловой структуре проекта в ОС. Делается это очень просто, для этого существует стандартная функция языка spl_autoload_register

В двух словах эта функция помещает обработку в очередь, которая запускается когда програмист пишет:

<?php
  
namespace Index;
use TestNamespace;

//\TestNamespace - это используемое пространство имен (через директиву use)
$MyVar = new TestNamespace\MyClass();

Файл с тестовым классом:

<?php

namespace TestNamespace

class MyClass {

  public function __construct() {
    echo 'test';
  }
  
}

Хочется добавить что вызывать эту функцию мы можем сколько угодно раз, а это значит что и обработчиков для поиска файла с классами мы можем сделать сколько угодно. Вообще, на самом деле, немного поразбиравшись в теме, я вижу что это достаточно гибкий инструмент. Может за это так не любят PHP, что он дает слишком большую свободу реализации. Получается что вся конструкция программы лежит на плечах программиста, что, наверное, не каждому по силам.

Например (из документации):

<?php
    spl_autoload_extensions(".php");
    spl_autoload_register();
?>

При такой реализации автозагрузки классов точка входа в приложение (index.php) должна располагаться вверху иерархии папок проекта. Этот пример я увидел при изучении документации когда писал код своей реализации пространства имен. Если честно размещение точки входа рядом с кодом приложения меня немного смущает с точки зрения безопасности, поэтому моя реализация приведена ниже.

Моя реализация:

class Init {

  private string $RootPath = '..' . 
    DIRECTORY_SEPARATOR . '..' . 
    DIRECTORY_SEPARATOR . '..' . 
    DIRECTORY_SEPARATOR . '..' . 
    DIRECTORY_SEPARATOR . '..' . 
    DIRECTORY_SEPARATOR;

public function __construct(
  private array $NamespacePath
    ) 
  {
    spl_autoload_register(function ($ClassName) use ($NamespacePath) {
  
      $PartialPath = strrpos($ClassName, '\\');
      $PathBefore = substr($ClassName, 0, $PartialPath);
      $FileName = substr(strrchr($ClassName, '\\'), 1);
  
      while($PartialPath !== false) {
  
        if(!empty($NamespacePath[$PathBefore])){
          $ClassNameToPath = str_replace('\\', DIRECTORY_SEPARATOR, $ClassName);
          include $this->RootPath . $ClassNameToPath . '.php';
          break;
        }
  
        $PartialPath = strrpos($PathBefore, '\\');
        $PathBefore = substr($ClassName, 0, $PartialPath);
  
      }
    });
  }
}

Теперь, при создании объекта, если в контексте видимости вызова не будет найден подходящий класс, запустится наша анонимная функция и попытается найти по заданной нам логике файл с классом.

Хочется отметить что такой подход к организации проекта дает нам следующие плюсы:

@SolidSnack
30.03.2025 19:05 UTC
Первоисточник

Комментарии

@ikrusenstern
30.03.2025 14:22 UTC
+2

Не хватает пояснений, зачем в 2025 году писать собственный автозагрузчик, если уже есть PSR-4

@SolidSnack
30.03.2025 14:40 UTC
0

Например если это внутренний проект компании где нужно свести использование библиотек к 0, и не зависеть от composer

30.03.2025 14:45 UTC
+1

Автозагрузчик можно сгенерировать на этапе сборки. Было бы полезно раскрыть, какие именно ограничения мешают использовать стандартный PSR-4?

31.03.2025 12:20 UTC
0

Хорошо, я не хочу генерить, хочу знать в коде каждый символ. Разве это плохо? И чем это противоречит PSR? Если я использую стандартную функцию языка для этого? В фреймворках думаете копировать, вставить?

31.03.2025 13:29 UTC
0

PSR это стандарт, который как раз и нужен, чтобы код был предсказуемым и совместимым, даже внутри компании.

Никто не мешает «знать каждый символ». Composer и другие автозагрузчики имеют открытый код, изучай сколько хочешь. Зачем изобретать велосипед, если стандартное решение уже работает и не противоречит Вашему подходу?

31.03.2025 13:38 UTC
0

Зачем мне его изучать, если я могу написать свою, на это буквально уходит от нескольких минут до рабочего дня. И все знать, и иметь её под свою структуру? Меня вот лично очень пугают языки которые навязывают код своей структурой, например int main в c++. Мне кажется про то что вы говорите, это больше про навязывание кода. Я считаю что использую стандарт за счет встроенной функции.

31.03.2025 13:40 UTC
0

То есть PSR-4 «навязывает», а своя кастомная схема — нет? Написать свой автозагрузчик — не проблема, вопрос в том, зачем. Удобство, поддержка и совместимость важнее желания «всё знать». Можно и свой HTTP-сервер на сокетах поднять, но почему-то все используют Nginx.

Скрытый текст

А так все мы через это проходили, когда были джунами — такой огромный мир, и так хочется переписать его под себя! Но чем больше опыта, тем яснее: вместо того, чтобы изобретать велосипед, проще взять готовый и тратить время на написание кода, который реально решает проблемы, а не создает новые.

Можно, конечно, гордиться своим автозагрузчиком, но это как строить свою машину, потому что «не хочу изучать, как работает заводской двигатель». Главное, не забыть потом написать свой компилятор и TCP/IP-стек — вдруг C++ тоже что-то «навязывает».

31.03.2025 13:49 UTC
0

Вы мне пытаетесь сказать что моя кастомность это потомучто я не так инклюд написал? А использование специальной функции языка, это как-бы ничего не значит? Мне совместимость как раз таки и не нужна, в коде нет библиотек, и фреймворк из него выпиливается (там и не компосер, и не копировать, вставить, а своя реализация, тоже через функцию языка).

31.03.2025 13:54 UTC
0

То есть, если вам «совместимость не нужна», то стандартные решения уже не имеют смысла? Логика железная! Тогда зачем вообще PHP? Напишите свой язык — так точно будете знать каждый символ. А если серьезно, то reinvent the wheel — классическая стадия. Пройдет.

31.03.2025 14:10 UTC
0

На среднем распределение, слева от центра и справа пишут свое, (для какого-то человека, все эти PSR, самописный код). Очень важно одно с другим не перепутать, вы мне все предлагаете что-то реализовать, но то что вы предлагаете не влияет на мою структуру папок веб приложения, логику подключения (вплоть до логирования) и всего того что мне нужно в моей архитектуре, большие вещи написаны, они классные, я ими пользуюсь.

31.03.2025 14:16 UTC
0

Представим будущее. Ваш проект разросся, и вдруг понадобилось переиспользовать модули в другом проекте. Или вы устроились в компанию, где люди уже используют Composer. И тут вопрос: будете писать еще один кастомный загрузчик для своих же библиотек? Или вручную инклюдить их по всему коду? А если решите объединить их в свой фреймворк, то что, напишете свой пакетный менеджер?

С такими темпами, глядишь, через пару лет дойдете до своего интерпретатора PHP, чтобы вообще ничего «не навязывало». Главное, чтобы потом не пришлось объяснять новому поколению разработчиков, почему ваш код живет в параллельной вселенной, где стандарты — это зло.

31.03.2025 14:18 UTC
0

Есть разработчики которые прямо сейчас развивают достаточно неплохой фреймворк на своём ответвлении PHP. (Вконтакте?) И што?)

31.03.2025 14:23 UTC
0

Информация за 20-какой год? ВКонтакте, как и все старые PHP-компании, давно переходит на Go. Их KittenPHP был нужен не ради кастомного автозагрузчика, а для трансляции кода в C++ ради производительности. Так что ваш пример как раз подтверждает, что изобретать свой велосипед в 2025 году — это больше про хобби, чем про реальную необходимость.

31.03.2025 14:24 UTC
0

А я и не про ВК :)

31.03.2025 14:33 UTC
0

Любопытный пример, но хотелось бы больше — поделитесь закулисьем индустрии! Какие еще компании в 2025 году массово отказываются от стандартов в пользу кастомных решений? Было бы интересно посмотреть реальные кейсы, где это дает объективное преимущество, а не просто «мне так удобнее».

P.S.

Это мой последний комментарий, увы, времени на эту дискуссию больше нет. Напомню лишь, что стандарты не просто так появились — бизнесу важна предсказуемость. Проще и быстрее найти специалиста, который умеет работать с общепринятым инструментом, чем тратить время и деньги на обучение его вашей уникальной системе.

Мы тут все, конечно, профессионалы, но в итоге нам нужно решать задачи, а не бесконечно рефакторить автозагрузчик. Продакшен требует проверенных решений, которые работают предсказуемо и масштабируемо, а не самописного кода ради самописного кода.

30.03.2025 15:10 UTC
+1

не понятно чем composer не угодил можно ведь в нем сделать загрузку с приватных репо или локальных файлов

стандартный универсальный инструмент

31.03.2025 05:53 UTC
0

вы можете это реализовать и при этом не зависеть от composer (что чрезвычайно странно и не нужно, проект, вероятно ужасен внутренне)

https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader-examples.md

и стандарт к которому все привыкли, будете соблюдать, и внешние библиотеки не будете подгружать

@koreychenko
31.03.2025 11:31 UTC
0

В комментариях к статье, на которую далась ссылка вам уже все рассказали про стандарты, паттерны и вот это вот все. Здесь вы опять пытаетесь рассказать всему PHP сообществу, как на самом деле нужно жить.

Грусть

А потом люди из других языков смотрят на это и думают что PHP говно.

@SolidSnack
31.03.2025 12:09 UTC
0

Я в статье подчёркиваю, рядом с этой ссылкой, что сделать это можно множеством способов (и показал самый короткий из тех же комментариев), а потом показал как сделал я. В чем принуждение?