Laravel retrieving multiple rows of data

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company

Mastering Multi-Level Relationships in Laravel: Efficiently Retrieving Nested Data

As a senior developer, I frequently encounter scenarios where we need to pull data from multiple related models—think three-way relationships involving Movies, Cinemas, and Sessions. The challenge often lies not just in getting the data, but in efficiently structuring the database queries so that Eloquent can handle the heavy lifting for us.

The scenario you presented—finding sessions linked to cinemas where those cinemas are tied to a specific movie ID—is a perfect example of where understanding Eloquent's relationship loading mechanisms saves significant development time and improves performance.

Let’s dive into why your current approach is cumbersome and how we can leverage Laravel's power to solve this cleanly.

The Pitfalls of Manual Querying in Eloquent

Your attempt to manually fetch related data by querying IDs iteratively, as seen in your controller snippet, highlights a common pitfall: trying to replicate what Eloquent is designed to do automatically.

When you execute separate queries like $query = Session::where('movie_id', "$id")->get(); and then try to extract linked IDs one by one, you are essentially forcing the application layer (your PHP code) to perform complex joins that the database could handle much more efficiently. This method is often less readable, harder to maintain, and significantly slower when dealing with large datasets because it involves multiple round trips to the database instead of a single, optimized query.

The core issue you identified—how to use $query to retrieve all associated cinema IDs for every session—is precisely what Eloquent's Eager Loading feature is designed to solve.

The Eloquent Solution: Mastering Eager Loading

The most idiomatic and performant way to handle these multi-level relationships in Laravel is through Eager Loading using the with() method. Eager loading instructs Eloquent to fetch all necessary related models in a minimal number of optimized SQL queries (usually just two or three joins) rather than executing many separate queries.

To solve your specific problem, you need to define the relationships between your models and then load them together. Assuming standard relationships where Session belongs to Movie, and Cinema belongs to Movie, we can structure the retrieval elegantly.

Step 1: Define Your Relationships (The Foundation)

Ensure your Eloquent models have the correct relationships defined. For example, a Session should link to a Movie, and perhaps indirectly through that movie, you access the associated cinemas.

// Example Models Setup
class Movie extends Model
{
    public function cinemas()
    {
        return $this->belongsToMany(Cinema::class); // If movies have many cinemas directly
    }
}

class Session extends Model
{
    public function movie()
    {
        return $this->belongsTo(Movie::class);
    }

    // To get the cinema related to this session, we chain the relationship:
    public function cinema()
    {
        return $this->belongsTo(Cinema::class);
    }
}

Step 2: Retrieving Nested Data Efficiently

Instead of querying for sessions and then looping, you load everything in one go. For instance, to get all sessions for a movie and their associated cinemas:

public function ticketpage($movieId)
{
    // Eager load the related data in a single query set.
    $movie = Movie::with('cinemas')->find($movieId);

    // Now fetch sessions for that movie, eagerly loading the cinema for each session.
    $sessions = Session::where('movie_id', $movieId)
        ->with('cinema') // Eager load the related cinema for every session found
        ->get();

    // Accessing the data is now direct and clean:
    foreach ($sessions as $session) {
        echo "Session ID: " . $session->id . ", Cinema ID: " . $session->cinema->id;
    }

    return view('movies/ticketpage/index', compact('movie', 'sessions'));
}

By using with('cinema') on the Session query, Laravel constructs a highly efficient SQL query that pulls all required session data and their corresponding cinema data in one go. This is far superior to manually querying IDs and then performing subsequent lookups for each row. This principle of efficient data retrieval is fundamental to building fast applications, as emphasized by best practices found on the Laravel Company website.

Conclusion

When dealing with complex, multi-level relationships in Laravel, resist the urge to manually piece together results from separate queries. Embrace Eloquent's relationship features—specifically Eager Loading (with()). It transforms complex data retrieval into clean, highly optimized database interactions, making your code more readable, maintainable, and significantly faster. Always aim to let the ORM handle the complexity; that is the mark of a senior developer.