Mass assignment — $fillable vs $guarded, security implications
Intermediate5 min read·lv-12-003
securityinterview
Concept
Eloquent querying uses a fluent builder API that translates PHP method calls to SQL. The key principle: calling query methods on a Model class returns a Builder instance; calling get(), first(), find(), count(), etc. executes the query.
Finding records:
Model::find($id): Find by primary key, returnsModel|null.Model::findOrFail($id): ThrowsModelNotFoundExceptionif not found.Model::findOrNew($id, $attributes): Find or create an unsaved model.Model::findMany([1, 2, 3]): Find multiple by primary key.Model::first(): First matching row or null.Model::firstOrFail(): First or throws.Model::firstOrCreate($attributes, $values): Find first matching or create.Model::firstOrNew($attributes, $values): Find first matching or instantiate (not saved).Model::updateOrCreate($attributes, $values): Update if found, create if not.
Retrieving collections:
Model::all(): All rows — avoid on large tables; useget()with constraints.Model::get(): Execute query, returnCollection.Model::cursor(): Returns aLazyCollectionwith PHP generators — memory-efficient for large result sets (streams one row at a time).Model::chunk(int $size, callable $callback): Retrieves in batches, passing each batch to the callback. Better thanall()for large datasets.
Aggregates: count(), sum($column), avg($column), max($column), min($column) — execute immediately, return scalars.
Code Example
php
<?php
use App\Models\User;
use App\Models\Order;
// Finding by primary key
$user = User::find(42); // null if not found
$user = User::findOrFail(42); // throws ModelNotFoundException
$users = User::findMany([1, 2, 3]); // Collection of users
// First or create / update
$user = User::firstOrCreate(
['email' => 'alice@example.com'], // search criteria
['name' => 'Alice', 'role' => 'customer'] // additional values if creating
);
User::updateOrCreate(
['email' => 'alice@example.com'], // search criteria
['name' => 'Alice Updated', 'last_login' => now()] // set these values
);
// Querying with constraints
$activeAdmins = User::where('active', true)
->where('role', 'admin')
->orderBy('name')
->get();
// Pagination
$users = User::where('active', true)->paginate(15); // LengthAwarePaginator
$users = User::where('active', true)->simplePaginate(15); // SimplePaginator (no total count)
$users = User::where('active', true)->cursorPaginate(15); // CursorPaginator (stable, no offset)
// Memory-efficient iteration for large tables
// chunk — batch processing
Order::where('status', 'pending')
->chunk(500, function($orders) {
foreach ($orders as $order) {
$order->process();
}
});
// cursor — generator-based, one row at a time
foreach (Order::cursor() as $order) {
ProcessOrder::dispatch($order);
}
// Aggregates
$total = Order::where('status', 'completed')->count(); // int
$revenue = Order::where('status', 'completed')->sum('total'); // float
$avgOrder = Order::avg('total');
// select specific columns
$users = User::select('id', 'name', 'email')->get();
// exists / doesntExist
if (User::where('email', 'alice@example.com')->exists()) {
// email is taken
}