Как сделать админ-панель на Laravel
За несколько лет работы с Laravel я перепробовал, кажется, все подходы к созданию админок, какие только существуют. Писал наполовину вручную (не повторяйте — удовольствие на любителя), пробовал быстрые готовые пакеты, которые устанавливаются за считаные минуты… В общем, знаю это болото изнутри. А с приходом Laravel 13 стало еще приятнее: многие вещи банально упростились и ускорились. Сейчас поделюсь свежим взглядом: расскажу по-честному о плюсах и граблях каждого пути — и покажу живой пример развертывания административной панели для вашего проекта.
Зачем вообще городить отдельную админку?
Вот пример из жизни: запускаешь сайт, вроде бы контент заливает только разработчик. Через пару недель маркетолог просит выложить новость, за ним потянулся редактор с просьбой исправить описание товара… И вот ты уже поддерживаешь проект в режиме “ручного кустаря”. Рано или поздно почти любой проект доходит до того этапа, когда управление данными становится задачей не разработчика, а менеджера или клиента. Тут всплывает классический вопрос: собрать самому или довериться готовой админ-панели?
За все время я для себя вывел формулу — если проект совсем маленький или с какими-то странностями (“нам нужна в админке рисовалка графиков на канвасе!”), иногда проще накодить нужный минимум под задачу вручную. Но честно говорю: в подавляющем большинстве случаев (у меня это 9 проектов из 10) гораздо разумнее взять готовый инструмент — экономия времени просто колоссальная, а надежность выше, чем у самопальных костылей.
Что изменилось в Laravel 13?
Перед тем как перейти к практике — пара быстрых заметок об экосистеме. В версии 13 разработчики двинулись дальше по пути минимализма — после революции с 11-й версией теперь структура проекта еще компактнее: никакой свалки ненужных провайдеров или middleware – просто максимально легковесный bootstrap/app.php. Для работы нужен PHP не ниже 8.3 (а лучше сразу ставить 8.4). Современные пакеты типа Filament подтянулись своевременно и никаких головных болей с совместимостью больше нет — можно спокойно обновлять старый код.
Главные способы собрать админку
1. Писать полностью самому
Это вариант для максималистов и тех, кто хочет держать под контролем каждую строчку: бэкенд пишете сами, фронт — сами (Blade + Tailwind или Bootstrap), админские фичи добавляете ровно те, что нужны… Денег не стоит, зато времени съедает вагон! Почему? Все базовые задачи вроде ввода-вывода данных, загрузки файлов, фильтрации записей приходится решать заново каждый раз. Я лично беру такой маршрут только если проект уж очень необычный по логике.
2. Готовые административные пакеты
Вот тут начинается магия скорости! Ставишь пакет через composer — и через полчаса у тебя рабочий прототип панели с авторизацией, CRUD’ами и даже графиками на бекенде. Расскажу про мои основные инструменты:
- Filament — любимец последних лет! Абсолютно бесплатный, современный и работает на стеке TALL (Tailwind + Alpine.js + Laravel + Livewire). Хочешь интерактивности без возни с Vue/React? Здесь всё решено элегантно.
- Laravel Nova — фирменная панель от авторов Laravel. Всё красиво из коробки — но придется заплатить за лицензию.
- Backpack for Laravel — гибкий зверь: есть бесплатная версия и куча платных дополнений.
- Orchid — чуть более экзотический игрок со своим взглядом на управление интерфейсами.
3. Headless-админка
Когда проект крупный или хочется тотальной свободы на фронте: Laravel превращается исключительно в API-сервер; весь интерфейс управления живет отдельно – например на Vue или React в виде SPA-приложения. Такой способ требует опыта и солидного бюджета времени/ресурсов – годится для сервисов уровня Enterprise.
Почему именно Filament?
Я перепробовал почти всё вышеперечисленное – и всё чаще возвращаюсь именно к Filament:
- Не нужно платить ни копейки за стандартные фишки
- Буквально одна команда конструирует весь CRUD-модуль
- Современный стек (Livewire вместо головной боли с написанием JS)
- Обалденная расширяемость за счет виджетов и плагинов
- Документация приятно удивляет полнотой и быстротой обновления
Давайте лучше один раз покажу «вживую» – как это выглядит на деле: сейчас быстро поднимем рабочую административную панель на базе Filament внутри свежего проекта на Laravel 13.
Шаг 1. Установка
Предполагаю, что у вас уже развёрнут проект на Laravel 13 и PHP 8.3+. Устанавливаем Filament через Composer:
composer require filament/filament -W
Composer подтянет актуальную версию, совместимую с Laravel 13. Далее запускаем установочную команду панели:
php artisan filament:install --panels
Эта команда создаёт провайдера панели в app/Providers/Filament/AdminPanelProvider.php и автоматически регистрирует его в bootstrap/providers.php — обратите внимание, что в новой структуре Laravel провайдеры хранятся именно здесь, а не в config/app.php.
Шаг 2. Создание администратора
Чтобы войти в панель, создаём администратора:
php artisan make:filament-user
Система спросит имя, email и пароль. После этого можно перейти по адресу /admin и авторизоваться.
Шаг 3. Подготовка модели
Допустим, у нас блог, и нам нужно управлять статьями. Создаём модель с миграцией:
php artisan make:model Post -m
В миграции описываем поля:
public function up(): void
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->string('slug')->unique();
$table->text('content');
$table->boolean('is_published')->default(false);
$table->timestamp('published_at')->nullable();
$table->timestamps();
});
}
Запускаем миграцию:
php artisan migrate
Теперь опишем модель app/Models/Post.php. В Laravel 13 для приведения типов удобнее использовать метод casts(), а не свойство:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
protected $fillable = [
'title',
'slug',
'content',
'is_published',
'published_at',
];
protected function casts(): array
{
return [
'is_published' => 'boolean',
'published_at' => 'datetime',
];
}
}
Шаг 4. Генерация ресурса
Самое приятное — создание CRUD-интерфейса одной командой:
php artisan make:filament-resource Post --generate
Флаг —generate автоматически проанализирует поля модели и создаст форму и таблицу. В результате появится ресурс в директории app/Filament/Resources/.
Шаг 5. Настройка формы
Открываем класс схемы ресурса и настраиваем поля под наши нужды:
use Filament\Forms;
use Filament\Schemas\Schema;
use Illuminate\Support\Str;
public static function form(Schema $schema): Schema
{
return $schema->components([
Forms\Components\TextInput::make('title')
->required()
->maxLength(255)
->live(onBlur: true)
->afterStateUpdated(fn ($state, callable $set) =>
$set('slug', Str::slug($state))
),
Forms\Components\TextInput::make('slug')
->required()
->unique(ignoreRecord: true),
Forms\Components\RichEditor::make('content')
->required()
->columnSpanFull(),
Forms\Components\Toggle::make('is_published')
->label('Опубликовано'),
Forms\Components\DateTimePicker::make('published_at')
->label('Дата публикации'),
]);
}
Здесь я использую реактивность: при вводе заголовка автоматически формируется slug.
Шаг 6. Настройка таблицы
Теперь оформим список статей с сортировкой, поиском и фильтрами:
use Filament\Tables;
use Filament\Tables\Table;
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('title')
->label('Заголовок')
->searchable()
->sortable(),
Tables\Columns\IconColumn::make('is_published')
->label('Статус')
->boolean(),
Tables\Columns\TextColumn::make('published_at')
->label('Публикация')
->dateTime('d.m.Y H:i')
->sortable(),
])
->filters([
Tables\Filters\TernaryFilter::make('is_published')
->label('Опубликованные'),
])
->recordActions([
Tables\Actions\EditAction::make(),
Tables\Actions\DeleteAction::make(),
])
->toolbarActions([
Tables\Actions\DeleteBulkAction::make(),
]);
}
Шаг 7. Добавляем виджет статистики
На главную страницу панели можно вывести полезную аналитику. Создаём виджет:
php artisan make:filament-widget PostStats --stats-overview
Заполняем его данными:
use Filament\Widgets\StatsOverviewWidget as BaseWidget;
use Filament\Widgets\StatsOverviewWidget\Stat;
use App\Models\Post;
class PostStats extends BaseWidget
{
protected function getStats(): array
{
return [
Stat::make('Всего статей', Post::count()),
Stat::make('Опубликовано', Post::where('is_published', true)->count()),
Stat::make('Черновики', Post::where('is_published', false)->count()),
];
}
}
Виджет автоматически подключится к дашборду.
Пара советов по продакшену
Перед тем как выкатывать админку на прод — остановитесь на минутку и проверьте пару моментов. Первое: обязательно прогоните php artisan optimize. Эта команда не просто «подчищает хвосты» — она реально ускоряет приложение, кэшируя настройки, маршруты и эвенты. И запускать её не лень: две секунды работы — и код сразу начинает дышать свободнее.
Второй момент связан с безопасностью. Настройте ограничения доступа: сделайте так, чтобы в админку попадали только те, кому действительно туда можно (ну серьёзно — зачем рядовому пользователю рисковать вашими таблицами?). В Filament это как раз делается через метод canAccessPanel() в юзер-модели. Один небольшой кусочек логики — и ваша панель уже значительно защищённее. Далее пример как это сделать.
1. Добавим в таблицу users поле is_admin
Создадим миграцию:
php artisan make:migration add_is_admin_to_users_table --table=users
В созданную миграцию добавим:
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->boolean('is_admin')->default(false)->after('password');
});
}
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('is_admin');
});
}
};
Запустим миграцию:
php artisan migrate
2. Обновим модель User
Открываем модель app/Models/User.php и правим:
namespace App\Models;
use Filament\Models\Contracts\FilamentUser;
use Filament\Panel;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable implements FilamentUser
{
use Notifiable;
protected $fillable = [
'name',
'email',
'password',
'is_admin',
];
protected $hidden = [
'password',
'remember_token',
];
protected function casts(): array
{
return [
'email_verified_at' => 'datetime',
'password' => 'hashed',
'is_admin' => 'boolean',
];
}
public function canAccessPanel(Panel $panel): bool
{
return $this->is_admin === true;
}
}
Теперь обычный пользователь с параметром is_admin = false не сможет войти в админ-панель.
Что в итоге?
Если честно, меня до сих пор удивляет, насколько быстро можно собрать полноценный административный интерфейс на свежем Laravel 13: CRUD-операции? Есть. Поиск, фильтры? Пожалуйста. Статистика с визуализацией и редактор для контента? Всё из коробки — занимает буквально пару чашек кофе по времени. Для сравнения: вручную такую штуку клепать пришлось бы день-два минимум.
Личный совет от души: если речь идёт о стандартных бэк-офисах или административных частях для быстрого MVP, не пытайтесь изобрести свою ракету там, где уже есть отличный авиаперевозчик. Filament реально экономит часы (а иногда и недели!) разработки и даёт возможность сосредоточиться на тех фишках продукта, которые действительно уникальны для вашего бизнеса. Всё остальное за вас уже придумали — остаётся только взять и внедрить.