CRUD: создание и чтение
Создание
new + save
Классический способ:
$post = new Post();
$post->title = 'Заголовок';
$post->body = 'Текст';
$post->save();
save() возвращает true или false.
create
Массовое присваивание:
$post = Post::create([
'title' => 'Заголовок',
'body' => 'Текст',
]);
Требует $fillable. Поля, которых нет в $fillable, будут проигнорированы.
firstOrCreate
Найти или создать:
$post = Post::firstOrCreate(
['slug' => 'hello-world'], // по этим полям ищем
['title' => 'Hello World', 'body' => '…'], // эти ставим при создании
);
Если найдено — возвращает существующее. Если нет — создаёт с обоими массивами.
Пример:
$tag = Tag::firstOrCreate(['name' => 'Laravel']);
// если тега нет — создаст только с name
firstOrNew
Как firstOrCreate, но не сохраняет:
$post = Post::firstOrNew(['slug' => 'hello']);
// $post->exists === false
$post->title = 'Hello';
$post->save();
updateOrCreate
Обновить или создать:
$post = Post::updateOrCreate(
['slug' => 'hello-world'],
['title' => 'Новый заголовок'],
);
Если найдено — обновит. Если нет — создаст.
Частое использование — сохранение формы, sync данных.
insert
Массовая вставка без моделей:
Post::insert([
['title' => 'A', 'body' => 'Text A'],
['title' => 'B', 'body' => 'Text B'],
]);
Что НЕ работает:
- Не запускает события (
creating,created). - Не проставляет timestamps.
- Не возвращает ID.
- Не проходит через касты.
Быстро, но осторожно.
createMany
Массово через модель:
$user->posts()->createMany([
['title' => 'A', 'body' => 'Text A'],
['title' => 'B', 'body' => 'Text B'],
]);
Возвращает коллекцию моделей.
upsert
INSERT ... ON CONFLICT UPDATE:
Post::upsert([
['id' => 1, 'title' => 'A', 'slug' => 'a'],
['id' => 2, 'title' => 'B', 'slug' => 'b'],
], ['id'], ['title']);
Аргументы:
- Данные.
- Уникальные поля (по ним определяется конфликт).
- Поля для обновления.
Один запрос вместо N. Быстро.
Чтение
find
По ID:
$post = Post::find(1);
// null, если нет
Массив ID:
$posts = Post::find([1, 2, 3]);
// Collection
findOrFail
404, если не найдено:
$post = Post::findOrFail(1);
// ModelNotFoundException → 404
В контроллере:
public function show(int $id)
{
$post = Post::findOrFail($id);
return view('posts.show', compact('post'));
}
findMany
Как find, но с массивом:
$posts = Post::findMany([1, 2, 3]);
first
Первая запись:
$post = Post::where('status', 'published')->first();
// null, если нет
firstOrFail
$post = Post::where('slug', 'hello')->firstOrFail();
// 404, если нет
all
Все записи:
$posts = Post::all();
⚠️ Осторожно — если записей миллион, всё в память.
get
После условий:
$posts = Post::where('status', 'published')->get();
value
Одно значение:
$title = Post::where('id', 1)->value('title');
Быстрее, чем find(1)->title.
pluck
Колонка значений:
$titles = Post::pluck('title');
// Collection: ['A', 'B', 'C']
$titles = Post::pluck('title', 'id');
// Collection: [1 => 'A', 2 => 'B']
⚠️ pluck возвращает Collection, не модель.
count
$count = Post::where('status', 'published')->count();
exists
if (Post::where('slug', 'hello')->exists()) {
// есть
}
if (Post::where('slug', 'hello')->doesntExist()) {
// нет
}
Агрегаты
Post::max('views');
Post::min('views');
Post::sum('views');
Post::avg('rating');
Обновление
Через атрибут
$post = Post::find(1);
$post->title = 'Новый';
$post->save();
update
$post->update(['title' => 'Новый']);
Требует $fillable.
Массовое
Post::where('status', 'draft')->update(['status' => 'archived']);
⚠️ НЕ запускает события модели (updating, updated).
⚠️ НЕ обновляет updated_at.
С updated_at:
Post::where('status', 'draft')->update([
'status' => 'archived',
'updated_at' => now(),
]);
increment / decrement
$post->increment('views'); // +1
$post->increment('views', 5); // +5
$post->decrement('likes'); // -1
Быстро — один UPDATE без чтения.
Удаление
delete
$post->delete();
destroy
По ID:
Post::destroy(1);
Post::destroy([1, 2, 3]);
С SoftDeletes — помечает как удалённые.
Массовое
Post::where('status', 'draft')->delete();
⚠️ Не запускает события.
truncate
Post::truncate();
Удаляет всё. Сбрасывает auto-increment. ⚠️ Нельзя откатить.
Практика
// Создание
$user = User::find(1);
$post = $user->posts()->create([
'title' => 'Первый пост',
'body' => 'Текст',
'status' => 'draft',
]);
// Обновление
$post->update(['status' => 'published', 'published_at' => now()]);
// Массовое обновление
Post::where('user_id', $user->id)
->where('status', 'draft')
->update(['status' => 'archived', 'updated_at' => now()]);
// Чтение
$published = Post::where('status', 'published')
->orderBy('published_at', 'desc')
->limit(10)
->get();
// Удаление
$post->delete();
Частые ошибки
1. create без $fillable:
protected $fillable = [];
Post::create(['title' => 'X']); // создастся пустая запись
2. insert вместо create:
Post::insert(['title' => 'X']);
// timestamps = NULL, events не сработали
3. update без updated_at:
Post::where('x', 1)->update(['y' => 2]);
// updated_at остался старым
4. firstOrCreate с логикой в первом массиве:
// Плохо: если найдено, второй массив игнорируется
Post::firstOrCreate(['slug' => 'x', 'title' => 'Y']);
Итог
- Создание:
create,firstOrCreate,updateOrCreate,insert,upsert. - Чтение:
find,findOrFail,first,all,get,pluck,value. - Обновление:
update,increment, массовое. - Удаление:
delete,destroy,truncate. - Правило: для моделей — методы модели, для массовых — Query Builder.
Дальше — массовые операции и upsert.