Rudra Framework
Rudra использует легковесный DI-контейнер, который обеспечивает автоматическое внедрение зависимостей (autowiring) без избыточной конфигурации.
Контейнер умеет:
✅Сервисы регистрируются через Rudra::set(). Поддерживаются три способа:
Rudra::set(['logger', [new Logger()]]);✅Один и тот же объект возвращается при каждом вызове Rudra::get('logger').
Rudra::set(['db', [fn() => new DatabaseConnection(...)]]);✅Новый объект создаётся при каждом вызове.
Rudra::set(['cache', [CacheService::class]]);✅Объект создаётся через DI-контейнер: все зависимости в конструкторе автоматически внедряются.
$logger = Rudra::get('logger');
$db = Rudra::get('db');Если сервис не зарегистрирован, но указан как класс ✅контейнер создаст его на лету с полным autowiring’ом.
Допустим, у вас есть сервис:
class Mailer
{
public function __construct(Database $db, Logger $logger)
{
// Зависимости будут автоматически внедрены
}
public function send(string $to, string $message): void
{
// Отправка письма
}
}✅Вы не регистрировали Mailer в contracts и не вызывали Rudra::set() — но можете использовать его напрямую:
#[Routing(url: 'send')]
public function send(Mailer $mailer): void
{
$mailer->send('user@example.com', 'Hello from Rudra!');
}Контейнер автоматически:
Rudra поддерживает полное автосвязывание по типам в:
#[Routing(url: 'autowire/:id')]
public function autowire(
RudraInterface $rudra,
Database $db,
CacheService $cache,
string $id = '1'
): void {
// Все объекты — автоматически внедрены
// $id — взят из URL-параметра
}⚠️Поддержка string, int, bool и других скаляров в параметрах метода — только если они соответствуют URL-маршрутам (например, :id).
Rudra автоматически выбирает способ вызова метода в зависимости от настройки PHP:
zend.exception_ignore_args = 11. Режим Reflection Используется ReflectionMethod — безопасно, быстро, с кэшированием.
zend.exception_ignore_args = 02. Fallback через исключения Rudra ловит TypeError/ArgumentCountError и подставляет зависимости на лету.
✅Каждый контейнер в Rudra может содержать файл config.php, в котором определяются:
Пример App/Containers/Demo/config.php:
use App\Containers\Demo\Factory\StdFactory;
use App\Containers\Demo\Factory\TestFactory;
use App\Containers\Demo\Interface\TestInterface;
return [
'contracts' => [
// Привязка класса к фабрике или callable
stdClass::class => 'callable',
TestInterface::class => TestFactory::class
],
'services' => [
// Именованный сервис как замыкание
'callable' => function () {
$std = new stdClass;
$std->method = __METHOD__ . '::Created from waiting';
return $std;
},
]
];Это позволяет:
class IndexController extends WebController
{
public function __construct(stdClass $std)
{
// $std автоматически создан и внедрён
$std->name = "Injected via DI";
dump($std);
}
#[Routing(url: '')]
public function index(stdClass $std): void
{
// Тот же $std доступен и в методе
render("layout", ["content" => "Hello"]);
}
}✅Объекты, созданные через DI, жизнеспособны на протяжении всего запроса — вы можете передавать их между методами и сервисами.
Rudra::set([LoggerInterface::class => [FileLogger::class]]);⚠️Не передавайте примитивы (строки, числа) в DI — они не создаются автоматически, если не пришли из URL