Модели в Laravel 11: короткая инструкция для начала
За полчаса вы создадите модель Eloquent, свяжете её с таблицей через миграцию и научитесь читать и записывать строки без ручного SQL. Подходит тем, кто впервые открыл Laravel.

К концу этой инструкции у вас будет модель Post, связанная с таблицей posts, заполненной парой строк, которые вы прочитаете и обновите из кода без единого запроса SQL руками. На чистом Laravel 11 это занимает 20–30 минут вместе с настройкой базы. Мы не будем разбирать, как Eloquent устроен внутри — только шаги, которые дают результат.
Что нужно иметь до начала
Проверьте это заранее, чтобы не упереться в нехватку прав или пакета на середине пути.
- PHP 8.2 или новее — требование Laravel 11. Проверьте:
php -v. - Composer — менеджер пакетов PHP1. Проверьте:
composer --version. - Готовый проект Laravel 11.x. Если проекта нет, создайте:
composer create-project laravel/laravel my-app, затемcd my-app. - База данных. Для старта проще всего SQLite: файл лежит внутри проекта, ничего ставить не нужно.
Настройте SQLite (самый быстрый вариант)
Откройте файл .env в корне проекта и приведите блок базы к такому виду, лишние строки DB_* удалите или закомментируйте:
DB_CONNECTION=sqlite
Создайте пустой файл базы:
# из корня проекта
touch database/database.sqlite
Проверка: файл database/database.sqlite появился в проекте. В свежем Laravel 11 путь к нему подставляется автоматически, отдельно DB_DATABASE прописывать не нужно.
Шаг за шагом
-
Создайте модель вместе с миграцией. Флаг
-mсразу генерирует файл миграции для таблицы.php artisan make:model Post -mПроверка: в терминале появятся строки
INFO Model [app/Models/Post.php] created successfully.иINFO Migration [...] created successfully. -
Опишите поля таблицы в миграции. Откройте файл в
database/migrations/с датой в имени и словомcreate_posts_table. Внутри методаup()замените тело функции:Schema::create('posts', function (Blueprint $table) { $table->id(); $table->string('title'); // заголовок, строка до 255 символов $table->text('body'); // текст поста $table->boolean('published')->default(false); $table->timestamps(); // created_at и updated_at });Проверка: файл сохранён, синтаксических ошибок редактор не подсвечивает.
-
Примените миграцию. Команда создаст таблицу
postsв базе.php artisan migrateПроверка: в выводе будет строка вида
DONEнапротив вашей миграцииcreate_posts_table. -
Разрешите массовое заполнение полей. По умолчанию Eloquent блокирует запись через массив — это защита от подстановки лишних полей. Откройте
app/Models/Post.phpи добавьте свойство$fillable:<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class Post extends Model { // поля, которые можно записывать через массив protected $fillable = ['title', 'body', 'published']; }Проверка: файл сохранён, класс
PostнаследуетModel. -
Проверьте всё в интерактивной консоли. Tinker запускает код в контексте приложения — удобно, чтобы не писать контроллер ради теста.
php artisan tinkerВнутри создайте и прочитайте запись:
// создать строку в таблице $post = App\Models\Post::create([ 'title' => 'Первый пост', 'body' => 'Текст поста для проверки', 'published' => true, ]); // прочитать все записи App\Models\Post::all(); // найти по id App\Models\Post::find(1);Проверка: после
::all()Tinker покажет коллекцию с одной записью, у которой заполненыid,titleи автоматическиеcreated_at/updated_at.
Базовые операции с моделью
Эти четыре действия закрывают большинство задач на старте. Все примеры работают в Tinker и в контроллере одинаково.
| Задача | Код |
|---|---|
| Создать запись | Post::create([...]) |
| Прочитать одну | Post::find($id) |
| Отфильтровать | Post::where('published', true)->get() |
| Обновить | $post->update(['title' => 'Новый']) |
| Удалить | $post->delete() |
Разница между find и findOrFail: первый вернёт null, если строки нет, второй выбросит исключение и отдаст 404 в HTTP-контексте. В контроллере обычно берут второй.
Соглашение об именах — не мелочь. МодельPostсама ищет таблицуposts: единственное число в верхнем регистре превращается во множественное в нижнем. Назовёте модель не так — придётся вручную указыватьprotected $table, и половина «магии» перестанет работать молча.
Если не получилось
SQLSTATE[HY000] [14] unable to open database file— файлdatabase/database.sqliteне создан или к нему нет прав. Создайте его командойtouchи проверьте, что путь совпадает с настройками.Base table or view not found: ... posts— таблицы нет, миграция не применялась. Запуститеphp artisan migrate. Если сомневаетесь в состоянии базы на учебном проекте —php artisan migrate:freshпересоздаёт все таблицы с нуля (удаляет данные).Add [title] to fillable property to allow mass assignment— вы забыли перечислить поле в$fillable. Добавьте его в массив в модели.Изменили миграцию, но столбца в базе нет —
migrateне перезапускает уже применённые файлы. Правьте схему и выполняйтеphp artisan migrate:freshна учебной базе либо создавайте отдельную миграцию на изменение.Class "App\Models\Post" not foundв Tinker — опечатка в пространстве имён. В Laravel 11 модели лежат вApp\Models, обращайтесь с полным путём или подключите черезuse.
Что делать дальше
Когда модель читает и пишет, следующий логичный шаг — связи между таблицами: hasMany, belongsTo. Например, у поста может быть автор (User) и много комментариев. Это отдельная тема, и её стоит открывать после того, как одиночная модель работает уверенно. Дальше пригодятся сидеры (php artisan make:seeder) для наполнения базы тестовыми данными и валидация входящих данных в контроллере перед записью. Точные сигнатуры методов связей сверяйте в разделе Eloquent Relationships официальной документации под вашу минорную версию Laravel.
IT-архитектор / SQL-оптимизатор: Поиск N+1, оптимизация запросов, code review, поиск багов.
Спросить за 20 ₽Источники: Laravel Documentation — Eloquent: Getting Started, Laravel Documentation — Database: Migrations
Частые вопросы
У меня Laravel 10, а не 11 — инструкция подойдёт?
Обязательно использовать SQLite? У меня MySQL.
Что делать, если после migrate таблица не появилась?
Почему запись через create падает с ошибкой mass assignment?
Можно ли обойтись без Tinker и проверить модель иначе?
Модель и таблица должны называться одинаково?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.