Laravel — это бесплатный фреймворк с открытым кодом (лицензия MIT) для разработки веб-приложений и API на PHP. Он берет на себя типовую инфраструктуру — маршрутизацию запросов, работу с базой данных, валидацию, сессии, очереди, аутентификацию, — а разработчик пишет только логику своего продукта.
Содержание
- Фреймворк, пакет, CMS: в чем разница
- Зачем нужен Laravel: что он берет на себя
- Как Laravel обрабатывает запрос
- Установка Laravel
- Маршруты, контроллер и Eloquent на одном примере
- Типовые ошибки новичка
- Что нужно до production
- Когда выбирать Laravel, а когда нет
- Версии и поддержка
- Выводы
- Где применяется / связь с практикой
- FAQ
Ниже — как Laravel устроен, как поставить его и собрать маленький API, какие ошибки встречаются первыми и в каких проектах фреймворк уместен, а в каких нет. Примеры проверены на Laravel 13.33 и PHP 8.4 (24.09.2026).
Фреймворк, пакет, CMS: в чем разница
Эти слова часто смешивают, поэтому коротко:
- Фреймворк (Laravel, Symfony) — каркас приложения. Он сам принимает запрос и вызывает ваш код в нужный момент; вы пишете контроллеры, модели, правила.
- Пакет Composer — отдельная библиотека, которую вызываете вы (например, для работы с датами). Сам Laravel устанавливается как набор таких пакетов и опирается на десятки сторонних (например, компоненты Symfony).
- CMS (WordPress, Bitrix) — готовый сайт с админкой: его настраивают и расширяют плагинами, а не пишут с нуля.
Laravel — не CMS: админки и готовых страниц в нем нет. Это инструмент, чтобы писать свое приложение быстрее, чем на чистом PHP.
Зачем нужен Laravel: что он берет на себя
| Задача | На чистом PHP | В Laravel |
|---|---|---|
| Разобрать URL и вызвать нужный код | свой роутер или цепочка if |
Route::get('/notes', ...) |
| Запрос к БД без SQL-инъекций | PDO и подготовленные выражения вручную | Eloquent ORM и Query Builder, параметры экранируются |
| Изменения схемы БД | SQL-скрипты, которые надо не забыть применить | миграции + php artisan migrate |
| Проверка входных данных | десятки if и сбор ошибок |
$request->validate([...]), ответ 422 |
| Защита форм от CSRF | генерировать и сверять токен самому | включена для routes/web.php по умолчанию |
| Шаблоны HTML | echo с ручным экранированием |
Blade: {{ $x }} экранирует вывод |
| Фоновые задачи, почта, кеш | отдельные библиотеки | очереди, Mail, Cache с единым API |
| Генерация заготовок | копирование файлов | Artisan: php artisan make:model |
Главный выигрыш — не в «меньше кода вообще», а в том, что типовые вещи уже сделаны единообразно и с безопасными умолчаниями. Новый разработчик в команде открывает Laravel-проект и сразу знает, где маршруты, где модели и где миграции.
Как Laravel обрабатывает запрос
Упрощенная цепочка одного HTTP-запроса:
- Веб-сервер отдает запрос в
public/index.php— единственную публичную точку входа. - Запрос проходит middleware — слои-фильтры: сессия, проверка CSRF, аутентификация, ограничение частоты.
- Маршрутизатор находит маршрут по методу и URL (
GET /api/notes). - Вызывается контроллер — класс, где лежит логика обработки.
- Контроллер работает с данными через модель Eloquent (класс, связанный с таблицей).
- Возвращается ответ: HTML из шаблона Blade, JSON или редирект.
Эту схему часто называют MVC (модель — представление — контроллер). Это упрощение: Laravel не требует строгого MVC. В API-проекте представлений (View) может не быть вовсе, а часть логики живет в очередях, событиях и отдельных сервисных классах.
Установка Laravel
Laravel 13 требует PHP 8.3 или новее (проверено по composer.json свежего проекта) и Composer — менеджер пакетов PHP. Для примеров также нужно расширение pdo_sqlite.
composer create-project laravel/laravel notes-app
cd notes-app
php artisan --version
php artisan serve
php artisan --version выведет версию фреймворка (у меня — Laravel Framework 13.33.0), а php artisan serve запустит встроенный сервер разработки на http://127.0.0.1:8000. Альтернатива — установщик laravel new notes-app, он дополнительно предлагает стартовые наборы с React, Vue или Livewire.
С Laravel 11 новый проект по умолчанию использует SQLite (DB_CONNECTION=sqlite в файле .env), поэтому для первых шагов отдельный сервер БД не нужен. Для MySQL или PostgreSQL меняются настройки DB_* в .env.
Куда смотреть в проекте:
| Путь | Что там |
|---|---|
routes/web.php |
маршруты для браузера: сессии, cookie, CSRF |
routes/api.php |
маршруты API с префиксом /api (появляется после php artisan install:api) |
app/Http/Controllers/ |
контроллеры |
app/Models/ |
модели Eloquent |
database/migrations/ |
миграции — история изменений схемы БД |
resources/views/ |
шаблоны Blade |
.env |
настройки окружения и секреты, в git не коммитится |
public/ |
единственная папка, доступная из веба |
Маршруты, контроллер и Eloquent на одном примере
Соберем API заметок: список, одна заметка и создание новой. Сначала подключим файл API-маршрутов и сгенерируем модель, миграцию и контроллер одной командой:
php artisan install:api
php artisan make:model Note -mc
install:api ставит пакет Sanctum (токены для API), создает routes/api.php и подключает его к приложению. Флаг -mc у make:model означает «плюс миграция и контроллер».
Миграция описывает таблицу. В созданном файле database/migrations/..._create_notes_table.php дополняем метод up():
Schema::create('notes', function (Blueprint $table) {
$table->id(); // BIGINT, автоинкремент, первичный ключ
$table->string('title', 100); // VARCHAR(100), обязательное
$table->text('body')->nullable(); // текст, может быть пустым
$table->timestamps(); // created_at и updated_at
});
Модель app/Models/Note.php — класс, связанный с таблицей notes по соглашению об именах:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Note extends Model
{
// поля, которые разрешено заполнять массово через create()/fill()
protected $fillable = ['title', 'body'];
}
Контроллер app/Http/Controllers/NoteController.php:
<?php
namespace App\Http\Controllers;
use App\Models\Note;
use Illuminate\Http\Request;
class NoteController extends Controller
{
public function index()
{
// SELECT * FROM notes ORDER BY id DESC
return Note::orderByDesc('id')->get();
}
public function show(Note $note)
{
// $note уже найден по {note} из URL, иначе Laravel вернет 404
return $note;
}
public function store(Request $request)
{
$data = $request->validate([
'title' => 'required|string|max:100',
'body' => 'nullable|string',
]);
$note = Note::create($data);
return response()->json($note, 201);
}
}
Маршруты routes/api.php:
<?php
use App\Http\Controllers\NoteController;
use Illuminate\Support\Facades\Route;
Route::get('/notes', [NoteController::class, 'index']);
Route::get('/notes/{note}', [NoteController::class, 'show']);
Route::post('/notes', [NoteController::class, 'store']);
Применяем миграцию, запускаем сервер и шлем запросы из второго терминала:
php artisan migrate
php artisan serve
curl -X POST -H 'Accept: application/json' -d 'title=Learn routing' -d 'body=web.php vs api.php' http://127.0.0.1:8000/api/notes
curl http://127.0.0.1:8000/api/notes
Первый запрос создаст заметку и вернет ее с кодом 201, второй — список:
{"title":"Learn routing","body":"web.php vs api.php","updated_at":"2026-09-24T11:09:59.000000Z","created_at":"2026-09-24T11:09:59.000000Z","id":1}
[{"id":1,"title":"Learn routing","body":"web.php vs api.php","created_at":"2026-09-24T11:09:59.000000Z","updated_at":"2026-09-24T11:09:59.000000Z"}]
Что здесь сделал фреймворк за нас:
- Маршрутизация.
php artisan route:list --path=notesпокажет три маршрутаapi/notesиapi/notes/{note}: префикс/apiфайлapi.phpдобавляет сам. - Привязка модели к маршруту. В
show(Note $note)Laravel сам выполнил поиск по id из URL. ЗапросGET /api/notes/42к несуществующей записи вернет 404 без единой строки проверки в коде. - Eloquent.
Note::orderByDesc('id')->get()превращается в SQL. Увидеть его можно вphp artisan tinker:Note::where('title', 'like', '%milk%')->orderByDesc('id')->toRawSql()вернетselect * from "notes" where "title" like '%milk%' order by "id" desc. - Валидация. Если правило не выполнено,
validate()прерывает обработку и возвращает 422 со списком ошибок — контроллер дальше не выполняется.
Запрос без поля title и запрос с title длиннее 100 символов:
{"message":"The title field is required.","errors":{"title":["The title field is required."]}}
HTTP 422
{"message":"The title field must not be greater than 100 characters.","errors":{"title":["The title field must not be greater than 100 characters."]}}
HTTP 422
Для обычной формы в браузере (маршрут в web.php, без Accept: application/json) Laravel вместо JSON сделает редирект назад и положит ошибки в сессию.
Типовые ошибки новичка
POST-маршрут в web.php отвечает 419. Неверно: положить Route::post('/notes', ...) в routes/web.php и вызвать его через curl или из стороннего клиента. Фактический результат — HTTP 419 (страница «Page Expired»), а в JSON-режиме сообщение CSRF token mismatch. Причина: маршруты web.php проходят проверку CSRF-токена (в Laravel 13 это middleware PreventRequestForgery, который дополнительно сверяет источник запроса по Origin). Исправление: для API — маршрут в routes/api.php; для HTML-формы — директива @csrf внутри <form> в шаблоне Blade. Отключать проверку CSRF для веб-маршрутов не стоит.
Массовое присваивание без $fillable. Неверно: убрать из модели protected $fillable и вызвать Note::create($data). Фактический результат — исключение Add [title] to fillable property to allow mass assignment on [App\Models\Note]. и ответ 500. Исправление — перечислить разрешенные поля в $fillable (в Laravel 13 есть и вариант атрибутом класса #[Fillable(['title', 'body'])]). В нашем контроллере лишние поля уже отсекает validate(): он возвращает только проверенные ключи. $fillable — вторая линия защиты для кода, где в create() попадает весь запрос ($request->all()): тогда поле id=777 будет молча отброшено, и запись получит следующий обычный id.
Если не получилось — по симптому:
| Симптом | Причина | Что сделать |
|---|---|---|
No application encryption key has been specified. |
пустой APP_KEY в .env |
php artisan key:generate |
SQLSTATE[HY000]: General error: 1 no such table: notes |
не применена миграция | php artisan migrate |
404 на /notes, хотя маршрут есть |
маршрут в api.php, а адрес без /api |
проверить php artisan route:list |
| 419 на POST | нет CSRF-токена для маршрута web.php |
@csrf в форме или маршрут в api.php |
500 MassAssignmentException |
поле не указано в $fillable |
добавить поле в $fillable |
Что нужно до production
Учебный пример выше специально минимален и не готов к публикации в интернете. Минимальный чек-лист:
APP_DEBUG=false. Сtrueответ на ошибку содержит путь к файлам и стек вызовов. Сfalseв JSON остается только полеmessage.- Аутентификация и права. В примере создать заметку может любой. Для API обычно используют Sanctum (токены) и политики (Policies) для проверки прав на конкретную запись.
- Ограничение частоты запросов через middleware
throttle, особенно для POST. - Сырые запросы — только с параметрами. Eloquent и Query Builder экранируют значения, но
whereRaw/DB::selectсо склейкой строки — нет:whereRaw('title = ?', [$title]), а не конкатенация. - Секреты в
.env, файл не попадает в git; корень сайта на сервере — папкаpublic/, а не корень проекта.
Когда выбирать Laravel, а когда нет
| Ситуация | Laravel уместен? | Комментарий |
|---|---|---|
| Веб-приложение, SaaS, личный кабинет, внутренняя система | да | типовые задачи уже решены, быстрый старт |
| REST API для мобильного или SPA-клиента | да | api.php, Sanctum, валидация, ресурсы |
| Команда уже пишет на PHP | да | большой рынок пакетов и специалистов |
| Сайт-визитка, блог, контент без логики | скорее нет | CMS или генератор статических сайтов проще |
| Микросервис из пары эндпоинтов | зависит | микрофреймворк (Slim) может быть легче |
| Сложный корпоративный проект с долгим сроком жизни | да, или Symfony | оба подходят; Symfony гибче в сборке из компонентов |
| Много долгоживущих соединений (чат, стриминг) | с оговорками | нужны WebSocket-сервер (Reverb) или Octane; иногда проще другой стек |
Laravel выбирают, когда важна скорость разработки и предсказуемая структура проекта. Цена — порог входа (много соглашений и «магии» фасадов) и накладные расходы на загрузку фреймворка по сравнению с маленьким скриптом на чистом PHP.
Версии и поддержка
Laravel создал Тейлор Отвелл, первая версия вышла в 2011 году. Сейчас мажорные версии выходят раз в год: Laravel 12 — в феврале 2025, Laravel 13 — в марте 2026. По политике проекта каждая мажорная версия получает исправления ошибок 18 месяцев и исправления безопасности 2 года. На сентябрь 2026 это значит: Laravel 13 (PHP 8.3-8.5) получает исправления ошибок до III квартала 2027 года и исправления безопасности до 17 марта 2028 года; у Laravel 12 исправления ошибок закончились 13 августа 2026 года, остались только исправления безопасности до 24 февраля 2027 года. Для нового проекта разумно брать Laravel 13, а проекты на 12 планировать к обновлению.
Выводы
- Laravel — PHP-фреймворк для веб-приложений и API: маршруты, контроллеры, Eloquent, миграции, валидация и безопасные умолчания в одном каркасе.
- Базовый цикл: маршрут -> контроллер -> модель Eloquent -> ответ; схема MVC здесь упрощение, а не обязательство.
- Первые ошибки почти всегда одни и те же: 419 из-за CSRF в
web.php, 422 из-за валидации, 500 из-за$fillable, пустогоAPP_KEYили непримененной миграции. - До production обязательны
APP_DEBUG=false, аутентификация, ограничение частоты и секреты вне репозитория. - Laravel уместен, когда нужна быстрая разработка приложения со своей логикой; для простого контентного сайта удобнее CMS.
Где применяется / связь с практикой
Освойте тему на практике
Laravel — частый стек в вакансиях PHP-разработчиков: на нем пишут SaaS-сервисы, личные кабинеты, внутренние системы компаний и API для мобильных приложений. Если хотите пройти путь от учебного API, как в этой статье, до приложения с очередями, тестами и деплоем, посмотрите курс по Laravel в Otus. Отдельные темы можно разобрать на бесплатных открытых уроках.
FAQ
Нужно ли знать PHP перед изучением Laravel?
Да, хотя бы на уровне классов, пространств имен и Composer: Laravel активно использует ООП, и без этой базы код фреймворка выглядит как набор заклинаний.
Laravel — это бэкенд или фронтенд?
Бэкенд. Фронтенд можно отдавать шаблонами Blade, связкой Livewire или Inertia с React/Vue, а можно сделать Laravel только API для отдельного клиента.
Можно ли использовать Eloquent без остального Laravel?
Да, ORM распространяется отдельным пакетом illuminate/database, но в самостоятельном режиме его нужно настраивать вручную.



