Laravel, the PHP web application framework, is renowned for its elegant and efficient approach to handling databases through its ORM (Object-Relational Mapping) called Eloquent.
Whether you're a seasoned Laravel developer or just starting your journey, mastering Eloquent and its accompanying database models can significantly streamline your development process.
In this article, we'll dive straight into the heart of Laravel's Eloquent ORM and explore a series of quick tips that can make your database interactions smoother, your code more concise, and your applications more powerful.
These tips are designed to be practical, actionable, and immediately beneficial to your Laravel projects.
From optimizing queries to leveraging relationships and handling common scenarios, we'll cover a range of essential Eloquent techniques. Each tip comes with code examples to illustrate its implementation and show how it can enhance your Laravel applications.
Let's see Laravel Tips, Laravel Tricks, top 10 Tricks and Tips Laravel, 10 laravel eloquent Tips and Tricks, Laravel Tips and Tricks 2023, and laravel advanced tips.
1. New `rawValue()` method
Laravel 9.37 has a new rawValue()
method to get a value from an SQL expression.
$first = PostModel::orderBy('date_at', 'ASC')
->rawValue('YEAR(`date_at`)');
$last = PostModel::orderBy('date_at', 'DESC')
->rawValue('YEAR(`date_at`)');
$fullname = UserModel::where('id', $id)
->rawValue('CONCAT(`first_name`, " ", `last_name`)');
2. Eloquent scopes inside of other relationships
You can use Eloquent scopes inside of defining other relationships.
app/Models/Lesson.php
public function scopePublished($query)
{
return $query->where('is_published', true);
}
app/Models/Course.php
public function lessons(): HasMany
{
return $this->hasMany(Lesson::class);
}
public function publishedLessons(): HasMany
{
return $this->lessons()->published();
}
3. Transaction-aware code
Using DB::afterCommit
method you can write code that will only be executed if the transaction gets committed and discarded if the transaction is rolled back.
If there is no transaction, the code will be executed right away
DB::beginTransaction(); // Start a transaction
// Perform database operations
DB::commit(); // Commit the transaction
// OR
DB::rollback(); // Rollback the transaction
Example:
DB::transaction(function () {
$user = User::create([...]);
$user->teams()->create([...]);
});
The afterCommit
method in Laravel is a feature that allows you to define actions that should be executed after a database transaction is successfully committed. This can be particularly useful when you want to perform certain tasks only when changes to the database have been permanently saved, ensuring data consistency.
class User extends Model
{
protected static function booted()
{
static::created(function ($user) {
// Will send the email only if the
// transaction is committed
DB::afterCommit(function () use ($user) {
Mail::send(new WelcomeEmail($user));
});
});
}
}
4. Perform operation without modifying updated_at field
In Laravel, the withoutTimestamps
method is used to specify that a model should not automatically manage the created_at
and updated_at
timestamp columns.
By default, Laravel's Eloquent ORM automatically manages these columns, updating created_at
when a new record is created and updated_at
when a record is updated.
However, in some cases, you may want to exclude these timestamps from certain operations or models.
You can disable timestamps for specific operations using the withoutTimestamps
method. This is helpful if you want to override the global timestamp configuration for specific cases.
Available from Laravel 9.31.
Example:
use App\Models\YourModel;
// Disable timestamps for a specific operation
YourModel::withoutTimestamps()->create([...]);
// Perform other operations without timestamps
YourModel::withoutTimestamps()->update([...]);
$user = User::first();
// `updated_at` is not changed...
User::withoutTimestamps(
fn () => $user->update(['reserved_at' => now()])
);
5. Merging eloquent collections
The Eloquent collection's merge method uses the id to avoid duplicated models. Merging Eloquent collections in Laravel allows you to combine multiple collections into one, which can be useful for tasks like combining query results or aggregating data from different sources.
You can merge collections using various methods provided by Laravel's Eloquent ORM. Here's how you can merge Eloquent collections.
1. Using concat()
Method:
The concat()
method is a straightforward way to merge two or more Eloquent collections. You can use it like this:
$collection1 = Model::where(...)->get();
$collection2 = Model::where(...)->get();
$mergedCollection = $collection1->concat($collection2);
2. Using the merge()
Method:
The merge()
method is another way to combine Eloquent collections. It works similarly to concat():
$collection1 = Model::where(...)->get();
$collection2 = Model::where(...)->get();
$mergedCollection = $collection1->merge($collection2);
Both concat()
and merge()
methods return a new collection containing the merged data, leaving the original collections unchanged.
3. Using union()
Method:
The union()
method is useful when you want to merge collections and remove duplicate items. It combines the collections while ensuring that each item is unique:
$collection1 = Model::where(...)->get();
$collection2 = Model::where(...)->get();
$mergedCollection = $collection1->union($collection2);
6. Full-Text Search with Laravel on MySQL
Implementing full-text search in Laravel with MySQL can greatly enhance the search capabilities of your application, allowing users to find relevant information more efficiently.
Migration:
Schema::create('comments', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('description');
$table->fullText(['title', 'description']);
});
Natural language
Search for something
Comment::whereFulltext(['title', 'description'], 'something')->get();
Natural language with Query Expansion
Search for something
and use the results to perform a larger query
Comment::whereFulltext(['title', 'description'], 'something', ['expanded' => true])->get();
7. Bindings raw queries
In Laravel, you can use query bindings in raw SQL queries to improve security and maintainability. Query bindings help prevent SQL injection and make your code more readable. Here's how to use query bindings in raw queries in Laravel:
// This is vulnerable to SQL injection
$fullname = request('full_name');
User::whereRaw("CONCAT(first_name, last_name) = $fullName")->get();
// Use bindings
User::whereRaw("CONCAT(first_name, last_name) = ?", [request('full_name')])->get();
$query = "SELECT * FROM users WHERE id = :userId";
$results = DB::select(DB::raw($query), ['userId' => 1]);
8. Reuse or clone query()
Typically, we need to query multiple time from a filtered query. So, most of the time we use query()
method.
In Laravel, the clone
method is not directly available for the query()
builder instance. However, you can achieve similar functionality by creating a new query builder instance and copying the desired parts of the original query. Here's how you can clone a query()
builder instance in Laravel
let's write a query for getting today created active and inactive products.
$query = Product::query();
$today = request()->q_date ?? today();
if($today){
$query->where('created_at', $today);
}
// lets get active and inactive products
$active_products = $query->where('status', 1)->get(); // this line modified the $query object variable
$inactive_products = $query->where('status', 0)->get(); // so here we will not find any inactive products
After getting $active products
the $query
will be modified. So, $inactive_products
will not find any inactive products from $query
and that will return blank collection every time. Cause, that will try to find inactive products from $active_products
($query
will return active products only).
To solve this issue, we can query multiple times by reusing this $query
object. So, We need to clone this $query
before doing any $query
modification action.
$active_products = $query->clone()->where('status', 1)->get(); // it will not modify the $query
$inactive_products = $query->clone()->where('status', 0)->get(); // so we will get inactive products from $query
9. Eloquent where date methods
Laravel's Eloquent ORM provides several methods for querying database records based on date and time values. These methods allow you to easily filter records based on various date-related criteria. Here are some common Eloquent where
methods related to date and time.
In Eloquent, check the date with functions whereDay()
, whereMonth()
, whereYear()
, whereDate()
and whereTime()
.
$users = User::whereDate('created_at', '=', '2023-01-15')->get();
$users = User::whereMonth('created_at', 2)->get();
$users = User::whereDay('birthdate', 5)->get();
$users = User::whereYear('birthdate', 1990)->get();
$users = User::whereTime('created_at', '=', '14:30:00')->get();
$users = User::whereBetween('birthdate', ['1990-01-01', '1999-12-31'])->get();
$users = User::whereDate('created_at', '2023-01-15')
->orWhereDate('updated_at', '2023-01-15')
->get();
10. Soft-deletes: multiple restore
In Laravel's Eloquent ORM, soft deletes are a way to "softly" delete records by marking them as deleted without actually removing them from the database.
This allows you to retain a record of the deleted item while excluding it from regular queries. You can restore soft-deleted records individually using the restore
method or restore multiple records at once using various techniques.
Here's how you can restore multiple soft-deleted records in Laravel:
1. Using the whereIn
Method:
You can restore multiple soft-deleted records by specifying a list of primary keys for the records you want to restore. Here's an example:
$idsToRestore = [1, 2, 3];
User::whereIn('id', $idsToRestore)->restore();
2. Using the restore
Method with a Query:
You can also restore multiple records using a query to filter the soft-deleted records you want to restore. For example:
Post::onlyTrashed()->where('author_id', 1)->restore();
Users::where('deleted_at', '<>', null)->restore();
You might also like: