Previous slide Next slide Toggle fullscreen Toggle overview view Open presenter view
Разработка веб-приложений с использованием программных платформ
Тема 3. Основы Laravel
Разработка веб-приложений с использованием программных платформ
План лекции
Основные вопросы
Установка и структура проекта
MVC и цикл HTTP-запроса
Маршруты и контроллеры
Blade и HTML-форма
SQLite, миграции и Eloquent
Валидация и диагностика
Цели лекции
Запустить новый проект Laravel
Проследить запрос до ответа
Создать модель и таблицу posts
Вывести и сохранить посты
Обработать ошибки формы
Проверить готовность мини-блога
Разработка веб-приложений с использованием программных платформ
Версия и границы темы
На 1 сентября 2026 года
Laravel 13 выпущен 17 марта 2026 года
Требуется PHP 8.3 или новее
Поддерживаются PHP 8.3-8.5
В примерах используется Laravel 13
В этой лекции
Один серверный Blade-интерфейс
Два маршрута для Post
SQLite и одна миграция
Inline validation в контроллере
Без аутентификации и REST API
Разработка веб-приложений с использованием программных платформ
Что нужно до установки
php -v
composer --version
php -m
Компонент
Для чего нужен
PHP 8.3-8.5
выполнение приложения
Composer 2.x
зависимости и Laravel Installer
PDO SQLite
локальная база данных
Терминал
команды Installer и Artisan
Браузер
интерфейс и DevTools
Node.js не нужен для минимального PHP-only примера без Vite.
Разработка веб-приложений с использованием программных платформ
Создание проекта
composer global require laravel/installer
laravel new mini-blog
cd mini-blog
laravel/installer ставится глобально для текущего пользователя
laravel new создает каркас и устанавливает зависимости
В интерактивных вопросах выбираем SQLite
Sail и Docker не добавляем в этот локальный сценарий
Все следующие команды выполняются из mini-blog
Разработка веб-приложений с использованием программных платформ
Два режима запуска
Минимальный пример
php artisan serve
Достаточно для Blade без @vite
Приложение доступно на локальном адресе
Процесс останавливается сочетанием Ctrl+C
Полный frontend workflow
npm install && npm run build
composer run dev
Нужен, когда проект использует Vite и frontend-ресурсы
Требует Node.js и npm
composer run dev запускает процессы разработки проекта
Разработка веб-приложений с использованием программных платформ
Окружение и секреты
Файлы
.env.example хранит образец переменных
.env содержит настройки конкретной машины
Laravel читает окружение через конфигурацию
Новый проект генерирует локальный APP_KEY
Правила
Не коммитить .env
Не хранить пароли и токены в Git
Использовать APP_DEBUG=true только локально
Для общего шаблона обновлять .env.example
APP_ENV=local
APP_DEBUG=true
DB_CONNECTION=sqlite
Разработка веб-приложений с использованием программных платформ
Структура прикладного кода
Путь
Назначение в мини-блоге
app/Http/Controllers
прием запроса и выбор ответа
app/Models
Eloquent-модели предметных данных
routes/web.php
маршруты браузерного интерфейса
resources/views
Blade-шаблоны HTML
database/migrations
изменения схемы базы данных
Пространства имен повторяют структуру app
Сгенерированные файлы сначала читают, затем изменяют
Разработка веб-приложений с использованием программных платформ
Структура выполнения
Веб-часть
public/index.php принимает веб-запрос
public является корнем веб-сервера
Остальные исходники не должны раздаваться напрямую
Состояние и диагностика
storage содержит runtime-файлы приложения
storage/logs/laravel.log хранит журнал Laravel
database/database.sqlite содержит локальную SQLite-базу
bootstrap запускает и настраивает приложение
Разработка веб-приложений с использованием программных платформ
Роли MVC в примере
Model
Post представляет записи таблицы posts
Eloquent строит запросы к базе
Модель задает допустимые поля массового заполнения
View
Blade получает подготовленные данные
Шаблон создает HTML-ответ
{{ }} экранирует вывод
Controller
Принимает объект запроса
Координирует модель и представление
Возвращает View или перенаправление
Разработка веб-приложений с использованием программных платформ
Цикл запроса Laravel
browser
-> public/index.php
-> bootstrap приложения
-> middleware и router
-> PostController
-> Eloquent -> SQLite
-> Blade
-> HTTP response -> browser
Middleware работает до или после контроллера
Router сопоставляет HTTP-метод и URI с обработчиком
Не каждый запрос обращается к базе или Blade
В нашем GET /posts задействована вся показанная цепочка
Разработка веб-приложений с использованием программных платформ
Что дает routes/web.php
Группа web
Назначается маршрутам файла по умолчанию
Поддерживает cookies и состояние сессии
Делает доступными flash-данные и старый ввод
Проверяет CSRF-токен для изменяющих запросов
Следствие для форм
GET читает страницу
POST создает данные
Для POST, PUT, PATCH, DELETE нужен @csrf
Метод и URI должны совпасть с маршрутом
Разработка веб-приложений с использованием программных платформ
Маршрут и ограничение параметра
use Illuminate \Support \Facades \Route ;
Route ::get ('/demo/posts/{postId}' , function (string $postId ) {
return "Post {$postId} " ;
})->whereNumber ('postId' )
->name ('posts.show-demo' );
get задает допустимый HTTP-метод
{postId} извлекает сегмент URI
whereNumber принимает только цифры
name отделяет имя маршрута от его URI
Это отдельная демонстрация вне маршрутов мини-блога
Разработка веб-приложений с использованием программных платформ
Маршруты мини-блога
use App \Http \Controllers \PostController ;
use Illuminate \Support \Facades \Route ;
Route ::get ('/posts' , [PostController ::class , 'index' ])
->name ('posts.index' );
Route ::post ('/posts' , [PostController ::class , 'store' ])
->name ('posts.store' );
php artisan route:list --except-vendor
Один URI может иметь разные обработчики для GET и POST
Blade строит адрес через route('posts.store')
Разработка веб-приложений с использованием программных платформ
Генерация файлов примера
php artisan make:model Post -m
php artisan make:controller PostController
Первая команда
Создает app/Models/Post.php
Флаг -m создает миграцию для posts
Имя таблицы выводится из имени модели
Вторая команда
Создает контроллер в app/Http/Controllers
Не добавляет маршруты автоматически
Методы index и store пишем явно
Разработка веб-приложений с использованием программных платформ
SQLite в новом Laravel 13
Значения по умолчанию
Свежий проект использует SQLite
Соединение задает DB_CONNECTION=sqlite
База находится в database/database.sqlite
Отдельный сервер базы не требуется
Что проверить
Файл базы существует и доступен на запись
В PHP включено расширение PDO SQLite
Приложение читает нужный .env
Миграции применены к текущему окружению
Разработка веб-приложений с использованием программных платформ
Миграция таблицы posts
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 ::create ('posts' , function (Blueprint $table ) {
$table ->id ();
$table ->string ('title' );
$table ->text ('body' );
$table ->timestamps ();
});
}
public function down ( ): void
{
Schema ::dropIfExists ('posts' );
}
};
Разработка веб-приложений с использованием программных платформ
Управление миграциями
php artisan migrate
php artisan migrate:status
up
Применяет изменение схемы
Создает таблицу posts
Состояние записывается в таблице миграций
down
Описывает обратное изменение
Используется при rollback
Удаление таблицы уничтожает ее данные
php artisan migrate:rollback применяйте осторожно и только локально, когда понимаете состав последнего пакета миграций.
Разработка веб-приложений с использованием программных платформ
Модель Post
namespace App \Models ;
use Illuminate \Database \Eloquent \Model ;
class Post extends Model
{
protected $fillable = [
'title' ,
'body' ,
];
}
Eloquent связывает Post с таблицей posts
$fillable разрешает массовое заполнение только указанных полей
Это граница mass assignment, но не замена validation
В create() передаем только массив $validated
Разработка веб-приложений с использованием программных платформ
Чтение и создание через Eloquent
$posts = Post ::query ()
->latest ()
->get ();
$post = Post ::create ([
'title' => 'Первый пост' ,
'body' => 'Текст первого поста' ,
]);
Чтение
query() начинает построение запроса
latest() сортирует по created_at от новых к старым
get() выполняет запрос и возвращает коллекцию
Создание
create() массово заполняет модель
Поля сверяются с $fillable
Eloquent устанавливает timestamps
Разработка веб-приложений с использованием программных платформ
Тонкий PostController
namespace App \Http \Controllers ;
use App \Models \Post ;
use Illuminate \Contracts \View \View ;
use Illuminate \Http \RedirectResponse ;
use Illuminate \Http \Request ;
class PostController extends Controller
{
public function index ( ): View
{
return view ('posts.index' , [
'posts' => Post ::query ()->latest ()->get (),
]);
}
public function store (Request $request ): RedirectResponse
{
$validated = $request ->validate ([
'title' => ['required' , 'string' , 'max:255' ],
'body' => ['required' , 'string' , 'max:10000' ],
]);
Post ::create ($validated );
return redirect ()->route ('posts.index' )
->with ('status' , 'Пост добавлен' );
}
}
Разработка веб-приложений с использованием программных платформ
Почему контроллер остается тонким
index
Получает коллекцию постов
Передает ее в posts.index
Объявляет результат как View
store
Валидирует только два входных поля
Передает $validated модели
Возвращает RedirectResponse
Кладет status во flash-сессию
SQL, разметка и ручная работа с CSRF в контроллер не попали
Разработка веб-приложений с использованием программных платформ
Обычный сбой валидации
$validated = $request ->validate ([
'title' => ['required' , 'string' , 'max:255' ],
'body' => ['required' , 'string' , 'max:10000' ],
]);
Браузерная форма
Laravel перенаправляет назад
Ошибки попадают в error bag
Введенные значения доступны через old()
Запись в базе не создается
XHR или JSON-запрос
Laravel возвращает HTTP 422
Ответ содержит ошибки по полям
Клиент сам решает, как их показать
Разработка веб-приложений с использованием программных платформ
Post/Redirect/Get после успеха
POST /posts
-> validate
-> INSERT
-> 302 redirect to posts.index
GET /posts
-> render updated list
Успешный POST не возвращает страницу списка напрямую
Redirect меняет следующий запрос на GET
Обновление страницы повторяет GET, а не вставку
Flash status живет до следующего запроса
Ошибка валидации использует другой redirect back
Разработка веб-приложений с использованием программных платформ
Минимальный Blade-layout
{{-- resources/views/layouts/app.blade.php --}}
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>@yield('title', 'Мини-блог')</title>
</head>
<body>
<main>
@yield('content')
</main>
</body>
</html>
Layout содержит общую HTML-оболочку
@yield отмечает место дочернего содержимого
Разработка веб-приложений с использованием программных платформ
Форма создания поста
<form method="POST" action="{{ route('posts.store') }}">
@csrf
<label for="title">Заголовок</label>
<input id="title" name="title" value="{{ old('title') }}">
@error('title') <p>{{ $message }}</p> @enderror
<label for="body">Текст</label>
<textarea id="body" name="body">{{ old('body') }}</textarea>
@error('body') <p>{{ $message }}</p> @enderror
<button type="submit">Добавить</button>
</form>
@csrf добавляет скрытый токен
route() использует имя маршрута, а не жесткий URL
Разработка веб-приложений с использованием программных платформ
Страница списка постов
{{-- resources/views/posts/index.blade.php --}}
@extends('layouts.app')
@section('title', 'Посты')
@section('content')
<h1>Посты</h1>
@if (session('status'))
<p>{{ session('status') }}</p>
@endif
@include('posts._form')
@forelse ($posts as $post)
<article>
<h2>{{ $post->title }}</h2>
<p>{{ $post->body }}</p>
</article>
@empty
<p>Постов пока нет.</p>
@endforelse
@endsection
Разработка веб-приложений с использованием программных платформ
Экранирование в Blade
<h2>{{ $post->title }}</h2>
<p>{{ $post->body }}</p>
{{ }}
Blade вызывает экранирование на основе htmlspecialchars
HTML-теги из пользовательского текста не исполняются
Это обычный выбор для данных формы
{!! !!}
Выводит значение без экранирования
Не использовать для пользовательских данных
Validation длины не превращает HTML в безопасный
Разработка веб-приложений с использованием программных платформ
Порядок сборки мини-блога
Создать проект и проверить .env
Сгенерировать Post с миграцией
Описать up() и down(), выполнить migrate
Задать $fillable в модели
Создать контроллер и два named route
Добавить layout, форму и список
Проверить успешный и ошибочный сценарии
После каждого шага запускайте приложение, не откладывая проверку до конца.
Разработка веб-приложений с использованием программных платформ
Инструменты диагностики
В терминале и файлах
php artisan route:list --except-vendor
php artisan migrate:status
storage/logs/laravel.log
вывод процесса php artisan serve
В браузере
адрес и HTTP-метод запроса
вкладка Network в DevTools
status code и response body
поля формы и redirect chain
APP_DEBUG=true допустим только в локальной среде
Разработка веб-приложений с использованием программных платформ
Частые коды и причины
Код
Что проверить сначала
404
URI, HTTP-метод, ограничение параметра, route:list
419
наличие @csrf, cookies, срок сессии
422
правила validation и поля JSON/XHR-запроса
500
laravel.log, stack trace локально, подключение к БД
Для обычной HTML-формы validation чаще виден как redirect назад
Ошибка no such table: posts означает, что нужная миграция не применена
Mass assignment exception требует проверить $fillable и входной массив
Разработка веб-приложений с использованием программных платформ
Готовность к лабораторной 1
Установка, структура, маршруты и Blade
Проект mini-blog запускается через php artisan serve
Студент объясняет назначение семи основных путей проекта
GET /posts связан с PostController@index
POST /posts связан с PostController@store
Оба маршрута имеют имена и видны в route:list
Layout и страница списка открываются без Vite
В форме есть method="POST" и @csrf
Разработка веб-приложений с использованием программных платформ
Готовность к лабораторной 2
SQLite, Eloquent и обработка формы
Миграция создает posts и корректно удаляет таблицу в down()
migrate:status показывает примененную миграцию
Post содержит $fillable для title и body
Валидный POST создает запись один раз
Невалидный POST показывает ошибки и сохраняет старый ввод
После успеха работает PRG и flash status
Пользовательский текст выводится через {{ }}
Причины 404, 419, 422 и 500 проверяются по плану
Разработка веб-приложений с использованием программных платформ
Что остается для лекции 4
Полноценная аутентификация и starter kits
Авторизация через Gates и Policies
Form Requests вместо inline validation
REST API и отдельные JSON-контракты
Файлы и storage
Cache
Tests
Deployment
В лекции 3 строим базовую серверную цепочку. Расширения добавляются после того, как она понятна и работает.
Разработка веб-приложений с использованием программных платформ
Резюме
Каркас приложения
public/index.php принимает запрос
Router выбирает контроллер
Blade формирует HTML
Группа web дает сессию и CSRF
Данные и форма
Миграция версионирует схему
Eloquent работает с Post
Validation проверяет входные поля
PRG завершает успешный POST
Безопасная разработка
.env и секреты остаются вне Git
$fillable ограничивает mass assignment
{{ }} экранирует пользовательский текст
Диагностика начинается с status code
Разработка веб-приложений с использованием программных платформ
Вопросы для самопроверки: устройство
Установка и структура
Какие версии PHP поддерживает Laravel 13?
Когда достаточно php artisan serve?
Чем различаются .env и .env.example?
Какие файлы нельзя хранить в Git?
Запрос и MVC
Как запрос проходит от браузера до ответа?
Как разделены роли Model, View и Controller?
Что дает группа middleware web?
Зачем маршруту задают имя?
Разработка веб-приложений с использованием программных платформ
Вопросы для самопроверки: мини-блог
Данные
Что делают методы up() и down()?
Почему $fillable не заменяет validation?
Когда Eloquent выполняет запрос с get()?
Почему в Post::create() передают $validated?
Форма и ошибки
Что происходит при сбое $request->validate()?
Для чего форме нужен @csrf?
Как PRG защищает от повторной вставки?
С чего начать проверку ошибок 419 и 500?
Разработка веб-приложений с использованием программных платформ
Ресурсы: версия и устройство
Версия и установка
Архитектура
Разработка веб-приложений с использованием программных платформ
Ресурсы: HTTP и представление
Маршруты и контроллеры
Формы и Blade
Разработка веб-приложений с использованием программных платформ
Ресурсы: данные
Схема базы
Модели и запросы
Лекция 3, 90 минут. Свяжите Laravel с HTTP, MVC, PHP, формами и PDO из лекций 1-2. Цель занятия: собрать минимальный мини-блог и подготовить студентов к первым двум лабораторным работам по Laravel.
Отведите около 20 минут на устройство Laravel, 45 минут на сквозной пример, 15 минут на диагностику и лабораторные, 10 минут на повторение.
Зафиксируйте дату версии. Документацию следует открывать в ветке 13.x, а не считать номер версии вечным.
Проверьте наличие `pdo_sqlite`. Если расширения нет, миграция завершится ошибкой еще до работы контроллера.
Выполните команды заранее или покажите короткую живую установку. Не переключайтесь на Sail: это другой способ организации среды.
Покажите, что выбранный далее layout не содержит `@vite`, поэтому для лекционного примера достаточно `php artisan serve`.
Откройте `.gitignore` и убедитесь вместе со студентами, что `.env` исключен. Не выводите реальные ключи на экран.
Быстро откройте каждый путь в редакторе. Попросите студентов заранее назвать, где они будут искать маршрут, модель и HTML.
Подчеркните, что веб-сервер направляет запрос в `public/index.php`, а не в `routes/web.php` напрямую.
Не называйте контроллер мозгом приложения. Его задача здесь узкая: связать HTTP, запрос модели и ответ.
Пройдите по цепочке дважды: сначала для GET списка, затем для POST формы. Во втором случае отметьте CSRF и валидацию.
Свяжите сессию сразу с тремя вещами: CSRF-токеном, ошибками валидации и `old()` после возврата к форме.
Сравните `/demo/posts/15` и `/demo/posts/new`: второй адрес не пройдет числовое ограничение и даст 404.
В выводе `route:list` найдите методы, URI, имена и действия обоих маршрутов.
После генерации покажите `git diff` или дерево проекта. Artisan дает заготовки, но не принимает архитектурные решения за разработчика.
Покажите файл SQLite в дереве проекта. Не открывайте его как текстовый файл: содержимое двоичное.
Сопоставьте `string` и `text` с ограничениями формы. `timestamps()` добавляет `created_at` и `updated_at`.
Покажите `migrate:status` до и после `migrate`. Не используйте `migrate:fresh` в проекте с нужными данными.
Спросите, почему нельзя передавать в `create()` весь `$request->all()`. Лишнее поле не должно попасть в массовое заполнение.
Уточните, что реальный контроллер ниже передает в `create()` результат валидации, а не вручную составленный учебный массив.
Проследите четыре действия `store`: получить запрос, проверить данные, создать запись, вернуть перенаправление.
Сравните роли с MVC-слайдом. Контроллер координирует шаги, но не формирует HTML и не пишет SQL вручную.
Отправьте пустую форму. Это штатная ветка приложения, а не исключительная поломка сервера.
После создания поста обновите страницу. Объясните, почему браузер не предлагает повторно отправить форму.
Сначала откройте страницу без CSS. Цель примера состоит в серверной цепочке, а не в оформлении интерфейса.
В DevTools откройте payload POST-запроса и найдите `_token`, `title` и `body`. Сам токен не нужно читать вслух или сохранять.
Создайте первый пост и покажите flash-сообщение. После следующего запроса оно исчезнет, а запись останется в SQLite.
Введите в заголовок `<script>alert(1)</script>` и покажите его как текст. Не заменяйте `{{ }}` на сырой вывод ради демонстрации.
Выполняйте шаги вертикально: сначала короткая рабочая цепочка, затем сообщения об ошибках и пояснения.
Разберите одну ошибку от внешнего симптома к источнику: status code, маршрут, журнал, строка приложения.
Не предлагайте сразу очищать все кеши или пересоздавать проект. Сначала установите код ответа и воспроизведите конкретный запрос.
Используйте список как приемочный чек-лист первой лабораторной, а не как дополнительную теорию.
Попросите показать оба сценария формы. Наличие записи в таблице без корректной обработки ошибки еще не означает готовность работы.
Не начинайте установку starter kit в этом проекте на занятии. Она изменит frontend workflow и отвлечет от базового цикла запроса.
Попросите восстановить полную цепочку запроса без подсказки, используя только названия трех групп.
Просите не перечислить термины, а объяснить путь конкретного `GET /posts`.
Выберите по одному вопросу из каждой группы. Остальные оставьте для самостоятельной проверки перед лабораторной.
Откройте оглавление документации 13.x и покажите, как перейти от метода из примера к полному справочному разделу.