user3574492
user3574492

Reputation: 6435

Laravel 5.5 retrieve first record within nested relationship

How can I use the first() method on a relation in an Eloquent query builder?

I only want to return the first section and the first subsection within that section.

I have the following query in my Assessment service:

public function firstSubsection()
    {
        return $this->model->with(['sections.subsections' => function ($q) {
                $q->take(1);
        }])->first();
    }

This returns multiple sections:

 {
        "id": 1,
        "name": "Assessment 1",
        "description": "<p>Some description</p>",
        "created_at": "2018-03-09 17:14:43",
        "updated_at": "2018-03-09 17:14:43",
        "sections": [
            {
                "id": 5,
                "name": "Section 1",
                "description": null,
                "parent": null,

                "created_at": "2018-03-09 17:14:52",
                "updated_at": "2018-03-09 17:14:52",
                "pivot": {
                    "assessment_id": 1,
                    "section_id": 5
                },
                "subsections": [
                    {
                        "id": 6,
                        "name": "Subsection 1",
                        "description": "<p>Lorem ipsum dolor sit amet<br>\r\n</p>",
                        "parent": 5,
                        "position": 6,
                        "created_at": "2018-03-09 17:15:08",
                        "updated_at": "2018-03-21 11:40:10"
                    }
                ]
            },
        {
            "id": 10,
            "name": "Section 2",
            "description": null,
            "parent": null,
            "position": 10,
            "created_at": "2018-03-20 14:34:50",
            "updated_at": "2018-03-20 14:34:50",
            "pivot": {
                "assessment_id": 1,
                "section_id": 10
            },
            "subsections": []
        }
    ]
}

Any idea how I can achieve this?

I have the following relationships in my Eloquent models:

class Section extends Model
{
    use BelongsToSortedManyTrait, SortableTrait;

    public $fillable = [
        'id',
        'name',
        'description',
        'parent',
        'position'
    ];

    public static $rules = [
        // create rules
        'name' => 'required'
    ];

    public function assessments() {
        return $this->belongsToSortedMany('App\Models\Assessment');
    }

    public function subsections() {
        return $this->hasMany(self::class, 'parent')->sorted();
    }
}



class Assessment extends Model
{

    public $fillable = [
        'id',
        'name',
        'description'
    ];

    public static $rules = [
        // create rules
    ];

    public function sections()
    {
        return $this->belongsToMany('App\Models\Section')->whereNull('parent')->sorted();
    }


}

Upvotes: 1

Views: 1773

Answers (4)

user3574492
user3574492

Reputation: 6435

In the end I had to do it like this:

public function firstSubsection()
    {
        return $this->model->with(['sections' => function ($q) {
            $q->with(['subsections' => function ($q) {
                $q->first();
            }
            ])->first();
        }])->first();
    }

Thanks to @ab_in for leading me in the right direction.

Upvotes: 3

Ali &#214;zen
Ali &#214;zen

Reputation: 1609

Take(1) and first() doing same thing right now. But still its not a problem. Remove take(1) and add ->get() after first()

Give it a try.

Upvotes: 0

Chirag Patel
Chirag Patel

Reputation: 1642

I am not sure this will work or not, but you can try this logic:

If you want to eager load the first section and subsection of your model you should create a new relationship in your model :

public function firstSectionOnly()
{
    return $this->hasOne(Section::class)->orderBy('id', 'asc');
}

And in Section model define

public function firstSubSectionOnly()
{
    return $this->hasOne(Subsection::class)->orderBy('id', 'asc');
}

Then you can eager load it in your current model:

public function firstSubsection()
{
    return $this->model->with(['firstSectionOnly.firstSubSectionOnly'])->first();
}

After trying this. Tell me it is working or have errors.

Upvotes: 1

fishyfishphil
fishyfishphil

Reputation: 93

public function firstSubsection()
{
    return $this->model->with(['sections.subsections' => function ($q) 
    {
            $q->take(1)->first();
    }])->first();
}

Upvotes: 0

Related Questions