Модели и конвенции
Создание модели
php artisan make:model Post
Флаги:
php artisan make:model Post -m # + миграция
php artisan make:model Post -f # + фабрика
php artisan make:model Post -s # + сидер
php artisan make:model Post -c # + контроллер
php artisan make:model Post -msfc # всё сразу
php artisan make:model Post -a # всё (включая политику, запросы)
Таблица
По умолчанию Post → posts. Множественное число (англ.).
Своё имя:
protected $table = 'my_posts';
Если отключить автоматическое множественное число:
protected $table = 'post';
Первичный ключ
По умолчанию: id, автоинкремент, целое.
Другое имя:
protected $primaryKey = 'post_id';
Не автоинкремент:
public $incrementing = false;
Строковый (UUID):
protected $keyType = 'string';
Пример UUID-модели:
class Post extends Model
{
protected $primaryKey = 'uuid';
protected $keyType = 'string';
public $incrementing = false;
protected static function booted(): void
{
static::creating(function ($post) {
$post->uuid ??= (string) Str::uuid();
});
}
}
Массовое присваивание
Eloquent защищает от подмены полей. По умолчанию все запрещены.
Белый список ($fillable):
protected $fillable = ['title', 'body', 'published_at'];
Чёрный список ($guarded):
protected $guarded = ['id'];
Разрешить всё:
protected $guarded = [];
⚠️ Опасно — можно подменить is_admin через форму.
Правило: используй $fillable. Никогда не открывай всё.
Что делает:
Post::create($request->all()); // только поля из $fillable
Приведение типов — Casts
Поля из БД приходят строками. Casts приводят их к нужному типу.
protected $casts = [
'published_at' => 'datetime', // Carbon
'is_active' => 'boolean', // true/false
'options' => 'array', // JSON ↔ массив
'meta' => 'json', // JSON
'price' => 'decimal:2', // 2 знака
'settings' => AsCollection::class, // Laravel Collection
'status' => OrderStatus::class, // Enum
];
Что даёт:
$post->published_at; // Carbon, не строка
$post->is_active; // bool
$post->options['theme']; // массив
$post->status; // OrderStatus::Active
Полный список casts:
int,integerreal,float,doubledecimal:2stringbool,booleanobjectarray,jsoncollectiondate,datetime,immutable_date,immutable_datetimetimestampencrypted,encrypted:arrayhashed- Имя Enum-класса
- Имя класса Cast (
AsCollection)
Timestamps
Eloquent автоматически управляет created_at и updated_at.
Отключить:
public $timestamps = false;
Переименовать:
const CREATED_AT = 'creation_date';
const UPDATED_AT = 'updated_date';
Изменить формат:
protected $dateFormat = 'U'; // Unix timestamp
Скрытые и видимые поля
Не показывать в JSON:
protected $hidden = ['password', 'remember_token'];
Только эти в JSON:
protected $visible = ['id', 'name', 'email'];
Применяется при toArray() и toJson().
Добавление в JSON
Виртуальное поле (вычисляемое):
protected $appends = ['full_name'];
protected function fullName(): Attribute
{
return Attribute::make(
get: fn () => "{$this->first_name} {$this->last_name}",
);
}
Соединение с БД
По умолчанию — default connection. Своё:
protected $connection = 'mysql';
Проверка модели
php artisan model:show Post
Покажет: таблицу, первичный ключ, поля, casts, связи.
Практика: полная модель
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Post extends Model
{
use SoftDeletes;
protected $fillable = [
'user_id', 'title', 'slug', 'body',
'published', 'published_at',
];
protected $casts = [
'published' => 'boolean',
'published_at' => 'datetime',
'meta' => 'array',
'views' => 'integer',
];
protected $hidden = ['deleted_at'];
protected $appends = ['excerpt'];
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
public function comments(): HasMany
{
return $this->hasMany(Comment::class);
}
protected function excerpt(): Attribute
{
return Attribute::make(
get: fn () => mb_substr($this->body, 0, 100) . '...',
);
}
}
Частые ошибки
1. Забыть $fillable:
Post::create($request->all()); // все поля проигнорированы
2. Добавить is_admin в $fillable:
protected $fillable = ['name', 'email', 'is_admin']; // ⚠️
your
3. $guarded = [] на продакшене. Открывает всё.
4. Забыть про casts для дат:
$post->published_at; // строка, а не Carbon
5. Ошибка в имени таблицы:
class UserGroup extends Model // таблица 'user_groups', не 'usergroups'
Итог
- Модель → таблица во множественном числе.
$fillable— белый список.$casts— типы.$hidden— скрыть в JSON.$appends— добавить в JSON.- Timestamps — авто, отключаются через
$timestamps = false. - Правило: заполняй явно, скрывай секреты.
Дальше — CRUD: создание и чтение.