Как сделать админ-панель на Laravel

Как сделать админ-панель на 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 реально экономит часы (а иногда и недели!) разработки и даёт возможность сосредоточиться на тех фишках продукта, которые действительно уникальны для вашего бизнеса. Всё остальное за вас уже придумали — остаётся только взять и внедрить.