Using laravel eloquent relation to retrieve all records except NULL
Stefan Bogdanescu
Founder & Senior Architect · 2026-06-29
# Using Eloquent Relations to Retrieve Records That Have Existing Relationships (Not NULL)
As a senior developer working with Laravel and Eloquent, you frequently encounter scenarios where you need to filter data based on the *existence* of related records rather than just retrieving the relation itself. The common pitfall, as you discovered, is that simply using `with()` followed by `get()` will happily return all parent records, including those where the foreign key linking them to the related table is `NULL`.
This post will dive deep into the correct and most efficient ways to retrieve Eloquent models only when a specific relationship actually exists. We will explore techniques for both one-to-one and many-to-many relationships, ensuring your database queries are lean and accurate.
## The Problem with Simple Retrieval
When you execute a query like this:
```php
$plates = \App\Models\Plate::with('project')->get();
```
Eloquent performs an `INNER JOIN` or uses the structure defined by the relationship. If a `Plate` record has no corresponding entry in the `projects` table (meaning its foreign key is `NULL`), it is still included in the result set, even though the relation itself is empty. This is because Eloquent's default behavior when using lazy loading with `with()` is to fetch all parent records first.
To solve this, we need to introduce explicit filtering mechanisms into our Eloquent queries that check for the existence of the related data.
## Solution 1: Filtering Based on Relationship Existence (`whereHas`)
The most idiomatic and expressive way in Eloquent to filter a model based on whether it has related models is by using the `whereHas()` method. This method constrains the query to only return models that satisfy the specified relationship condition.
For your scenario (retrieving plates that *have* projects), you use `whereHas` on the `project` relationship:
```php
use App\Models\Plate;
$platesWithProjects = Plate::whereHas('project')->get();
```
### How `whereHas()` Works
The `whereHas('relation_name')` method translates directly into a SQL `EXISTS` clause. This is highly efficient because the database stops searching as soon as it confirms that at least one matching record exists in the related table, rather than performing a full join and checking for null values on the result set afterward.
To retrieve the plates along with their projects:
```php
$platesWithProjects = \App\Models\Plate::whereHas('project')->with('project')->get();
```
This query will only return `Plate` records that successfully have a corresponding entry in the `projects` table, ensuring you only deal with valid relationships. This approach aligns perfectly with Laravel's focus on expressive data fetching, as promoted by resources like the official [Laravel documentation](https://laravelcompany.com).
## Solution 2: Filtering Based on Foreign Key Existence (`whereNotNull`)
If you are dealing with a simple `belongsTo` relationship where the foreign key column is guaranteed to be populated *if* the relationship exists (and assuming standard database constraints), you can directly query the foreign key column using `whereNotNull()`.
For your specific case, if the `plates` table has a `project_id` column:
```php
$platesWithProjects = \App\Models\Plate::whereNotNull('project_id')->get();
```
### When to Use Which Method?
| Method | Use Case | Performance Note |
| :--- | :--- | :--- |
| **`whereHas('relation')`** | Checking for the *existence* of a related model (the relationship itself). | Excellent. Uses an optimized `EXISTS` clause. Recommended for general filtering. |
| **`whereNotNull('foreign_key')`** | Checking if the specific foreign key value is not null. | Very fast, often results in a direct index lookup on the foreign key column. Best when you only need to filter based on the ID presence. |
While both methods achieve the goal of filtering out `NULL` records, `whereHas()` is generally preferred when working with Eloquent relations because it keeps your query tightly coupled to the model relationships, offering greater readability and maintainability.
## Handling Many-to-Many Relationships
The same principle applies seamlessly to many-to-many relationships, which typically involve pivot tables (e.g., `plate_project` table). To retrieve all plates that are linked to at least one project:
```php
use App\Models\Plate;
// Retrieve plates that have at least one project relationship defined via the pivot table
$platesWithProjects = Plate::whereHas('projects')->with('projects')->get();
```
In this context, `whereHas('projects')` checks the existence of entries in the pivot table linking to the `Plate` model. This pattern demonstrates how powerful Eloquent's query builder is for managing complex relational data efficiently.
## Conclusion
Retrieving records that possess a relationship requires moving beyond simple retrieval methods. By leveraging Eloquent's powerful query constraintsâspecifically `whereHas()` for checking existence and `whereNotNull()` for direct foreign key checksâyou ensure that your data fetching is not only accurate but also highly performant. Always favor these methods when dealing with relational data, keeping the principles of clean, efficient database interaction central to your Laravel development workflow.