Every Eloquent model maps to a table whose name is the snake_case plural of the class — Post ↔ posts. Migrations describe the table; the model handles queries.
// database/migrations/…create_posts_table.php
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
$table->string('title');
$table->text('body');
$table->boolean('is_published')->default(false);
$table->timestamps();
});
// app/Models/Post.php
class Post extends Model
{
protected $fillable = ['user_id', 'title', 'body', 'is_published'];
protected $casts = ['is_published' => 'boolean'];
}
Mass assignment safety
Without $fillable, Post::create($request->all()) will silently let users set anything in the request body — including columns like is_admin. Define $fillable (allowlist) or $guarded (denylist). Pick one.
Casts
$casts tells Eloquent how to convert a column's raw value to/from PHP — boolean, array, datetime, decimal:2, hashed, and so on.