Skip to content

Чеклисты

Копируемые списки для типовых операций. Проходить сверху вниз — не полагаться на память.

Новый проект

  • [ ] laravel new (L12 стабильный или L13 для нового) → см. структура L12/13
  • [ ] Свой starter применён (или собран): Breeze + Filament + Spatie-набор
  • [ ] docker-compose студии: app/nginx/postgres(mysql)/redis/queue/scheduler
  • [ ] .env заполнен, .env.example в git, секреты не в git
  • [ ] phpunit.xml: DB_DATABASE={project}_test — защита рабочей БД
  • [ ] Тестовая БД создана + extensions (PostGIS и т.п.)
  • [ ] Pint + Larastan (level 6+) + Pest настроены
  • [ ] .claudeignore (vendor, node_modules, storage/logs)
  • [ ] .mcp.json сгенерирован (setup.ps1), boost установлен, проект активирован в ~/.claude.json
  • [ ] trustProxies + URL::forceScheme под Caddy (если публичный)
  • [ ] Кастомные stubs под declare(strict_types=1) + $casts

Новая модель

  • [ ] make:model X -mf (+ --requests если есть форма)
  • [ ] Миграция: FK constrained() + index(), JSON nullable(), enum-столбцы, down()
  • [ ] declare(strict_types=1)
  • [ ] $fillable (whitelist) — не $guarded = [] при пользовательском вводе
  • [ ] $casts на КАЖДЫЙ json/date/bool/enum/decimal столбец
  • [ ] Обе стороны связей (hasManybelongsTo)
  • [ ] Scope для WHERE, используемых 2+ раз
  • [ ] Фабрика заполнена
  • [ ] Нет $with в модели, нет бизнес-логики в модели
  • [ ] Индексы на WHERE/ORDER BY столбцы

Новый роут / контроллер

  • [ ] Роут именован через ->name()
  • [ ] Route model binding: slug (публичные) / id (admin)
  • [ ] Контроллер тонкий (≤10 строк логики) — остальное в Service
  • [ ] Валидация в FormRequest, не в контроллере
  • [ ] ->with() явно (нет N+1)
  • [ ] Ссылки в коде — route('name'), не хардкод URL
  • [ ] Feature-тест: GET 200, несуществующий slug 404, наличие h1/title
  • [ ] Если форма: POST валидные → success, невалидные → 422/errors
  • [ ] Если менялся URL: 301 redirect со старого + тест на него

Новый Filament-ресурс

  • [ ] make:filament-resource X --generate
  • [ ] Русские $modelLabel / $pluralModelLabel / лейблы полей
  • [ ] Navigation group на русском + $navigationSort
  • [ ] Поля сгруппированы в Section (доп. — collapsible())
  • [ ] Slug: unique(ignoreRecord: true)
  • [ ] FK: Select::relationship(); медиа: SpatieMediaLibraryFileUpload; bool: Toggle
  • [ ] Таблица: searchable/sortable где нужно, FK как relation.name, дата d.m.Y H:i
  • [ ] afterSave()Cache::tags([...])->flush() (гранулярно, не весь кеш)
  • [ ] Бизнес-логика — в Service, не в Resource

Новая форма (публичная)

  • [ ] FormRequest с правилами (max:255 на строки, email:rfc,dns, exists для FK)
  • [ ] authorize() осознанно, messages() на русском
  • [ ] spatie/laravel-honeypot против спама
  • [ ] throttle на POST-endpoint
  • [ ] для вывода (не {!! !!} с пользовательским вводом)
  • [ ] Уведомление о заявке (mail/Telegram) через Job (не синхронно)
  • [ ] Тест валидации + сохранения

Новая миграция большой таблицы (>1M строк)

  • [ ] CREATE INDEX CONCURRENTLY + $withinTransaction = false
  • [ ] Functional index для lower() при ILIKE с кириллицей
  • [ ] GIN на tsvector для полнотекста (STORED generated column)
  • [ ] После массового импорта — ANALYZE table
  • [ ] down() с DROP INDEX CONCURRENTLY

Перед коммитом (стандарт студии)

  • [ ] Нет dd(), dump(), console.log, закомментированного кода
  • [ ] Строки UI через __(), числа/статусы в config/Enum/Constants
  • [ ] Новый роут → ->name() + тест; новая модель → $casts + relations + factory
  • [ ] Новая миграция → down(), FK constrained() + index()
  • [ ] Новая форма → FormRequest; изменён URL → 301 redirect
  • [ ] Filament → afterSave + Cache::tags()->flush()
  • [ ] Pint + тесты зелёные (проверено, а не «должно»), нет секретов в diff

Безопасность (быстрая проверка периметра)

  • [ ] SQL — только Eloquent/bindings, нет DB::raw() с конкатенацией
  • [ ] XSS — , {!! !!} только для доверенного HTML из админки
  • [ ] CSRF — на всех POST-формах (Laravel по умолчанию, не отключать)
  • [ ] Права — Policy/Gate на защищённые действия
  • [ ] Секреты — .envconfig(), никогда env() в коде
  • [ ] ID в публичных URL — UUID/хеш/slug, не автоинкремент
  • [ ] Rate limiting на API POST/PUT/DELETE

Внутренняя база знаний студии