Rudra Framework
В Rudra доступ к данным построен на трёх согласованных уровнях, которые позволяют начать с минимума и масштабироваться без переписывания кода.
Эта архитектура даёт полную гибкость, не навязывая ORM, наследование от монолитных моделей или жёсткие правила.
Вы всегда начинаете с одного класса — и добавляете слои только когда они нужны.Три слоя доступа к данным
В Rudra доступ к данным построен на трёх согласованных уровнях, которые позволяют начать с минимума и масштабироваться без переписывания кода.
Эта архитектура даёт полную гибкость, не навязывая ORM, наследование от монолитных моделей или жёсткие правила.
Вы всегда начинаете с одного класса — и добавляете слои только когда они нужны.
Уровень | Назначение | Когда использовать |
|---|---|---|
Entity | Точка входа. Лёгкий класс с именем таблицы. | Всегда — с него начинается работа. |
Model | Бизнес-логика, статические методы, фабрики, валидация. | Когда нужна доменная логика поверх данных. |
Repository | Запросы к БД, JOIN’ы, пагинация, кэширование. | Когда нужны сложные SQL-операции или оптимизация. |
✅При вызове User::method() Rudra автоматически ищет реализацию в порядке:
Model → Repository → Базовый Repository.
// App/Entity/User.php
namespace App\Entity;
use Rudra\Model\Entity;
class User extends Entity
{
public static ?string $table = 'users';
}Теперь вы можете:
$user = User::find(1);
$admins = User::findBy('role', 'admin');
User::create(['name' => 'Alice', 'email' => 'alice@example.com']);→ Все методы делегируются Rudra\Model\Repository, так как Model и Repository ещё не созданы.
// App/Model/User.php
namespace App\Model;
use Rudra\Model\Model;
class User extends Model
{
public static function createAdmin(string $email, string $name): array
{
// Инкапсулируем доменную операцию
return (new \App\Repository\UserRepository('users'))->create([
'email' => $email,
'name' => $name,
'role' => 'admin',
'active' => true
]);
}
// Можно даже переопределить базовый метод
public static function find(int $id): array|false
{
$user = parent::find($id); // или вызов через репозиторий напрямую
if ($user) {
// Например, логируем, обогащаем данные и т.п.
}
return $user;
}
}Теперь:
User::createAdmin('boss@example.com', 'Admin'); // → вызывается Model
User::find(1); // → тоже Model✅ Model имеет приоритет над Repository. Это позволяет переопределять поведение, не трогая инфраструктуру.
// App/Repository/UserRepository.php
namespace App\Repository;
use Rudra\Model\Repository;
use Rudra\Pagination;
class UserRepository extends Repository
{
public function getActiveWithProfile(Pagination $pagination)
{
return $this->qBuilder($this->qb()
->select('users.*, profiles.bio, roles.name as role_name')
->from($this->table)
->join('profiles')->on('users.id = profiles.user_id')
->join('roles')->on('users.role_id = roles.id')
->where('users.active = 1')
->orderBy('users.created_at DESC')
->limit($pagination->getPerPage())
->offset($pagination->getOffset())
->get()
);
}
public function activate(int $id): void
{
$this->update(['id' => $id, 'active' => 1]);
$this->clearCache('database', 'getActiveWithProfile');
}
}→ Этот метод автоматически становится доступен через User::getActiveWithProfile(...).
// Статический стиль — лаконичный и выразительный
$admins = User::findBy('role', 'admin');
// Объектный стиль — удобен при DI (внедрении зависимости)
public function actionIndex(User $user): void
{
$me = $user->find($this->auth->id());
}Оба вызова проходят одну и ту же цепочку делегирования.
Три слоя — не обязанность, а возможность.
Вы не обязаны создавать Model и Repository, если не нужно.
Но когда проект растёт — архитектура уже готова к этому.
Это Rudra:
минимализм по умолчанию,
мощь по требованию,
контроль всегда.