Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

wordxpression's avatar

Hierarchical 'one to many' relationships...

Delving into the documentation of all the kinds of relationships, I wonder if there is also a direct relation possible in Eloquent like described below.

I have three tables. Cities, States and Countries.

Every city has one State, every State one Country, and as such of course, also every city belongs to one country.

So I want to create a 'direct' relationship between the city and the country, so if I would call a method country() from a city and I would retrieve the country.

Of course I can do it with a query builder, but I'm curious if there is some method I'm overlooking to do it more efficiently.

Thanks in advance Wilko

0 likes
3 replies
LaryAI's avatar
LaryAI
AI
Best Answer
Level 58

Certainly! In Eloquent, you can define relationships across multiple levels by chaining the relationship methods together. However, to directly access a country from a city, you can define an accessor on the City model that retrieves the country through the state. Here's how you can set it up:

First, define the relationships in your models:

// City model
class City extends Model
{
    public function state()
    {
        return $this->belongsTo(State::class);
    }

    // Define an accessor to get the country directly
    public function getCountryAttribute()
    {
        return $this->state->country;
    }
}

// State model
class State extends Model
{
    public function country()
    {
        return $this->belongsTo(Country::class);
    }

    public function cities()
    {
        return $this->hasMany(City::class);
    }
}

// Country model
class Country extends Model
{
    public function states()
    {
        return $this->hasMany(State::class);
    }
}

With these relationships set up, you can now access the country of a city directly by using the country accessor:

$city = City::with('state.country')->find($cityId);
$country = $city->country; // This will use the accessor we defined

By using the with('state.country') method, you're eager loading the state and country relationships, which is more efficient than lazy loading them later.

Remember that the getCountryAttribute method is an accessor, and by default, Laravel will make it available as a property ($city->country) rather than a method. If you want to use it as a method, you can simply call it like so:

$country = $city->getCountryAttribute();

This approach allows you to efficiently retrieve the country associated with a city without having to write a custom query builder logic each time you need it.

1 like
wordxpression's avatar

@amitsolanki24_

Thanks, I didn't get a notification from Laryai, so I didn't notice it, but I got one for your answer. And indeed, it works. So both @amitsolanki24_ and the one who built the Laryai interface: Thanks a lot :D

Please or to participate in this conversation.