Cryank's avatar

Using scope and pagination in a accessor ?

Hello everyone ,

I have a question about using Scope, Paginate, and HasMany Relationship together...

In a Batch Model

    /**
     * A Batch has many applicants
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function applicants()
    {
        return $this->hasMany('App\Applicant');
    }

By relationship defined, I can access Applicants in a specific Batch using $batch->applicants,

However, what I have to do if I want Applicants result being searched by scope and paginated as well ?

I did something for pagination but have no idea to apply scope search into this accessor

    /**
     * accessor
     * Return Applicants linked to this Batch
     *
     * @return int
     */
    public function getRecordsAttribute()
    {
        return $this->applicants()->paginate(12);
    }

Applicant Model

    /**
     * Scope a query to search by keyword
     *
     * @param $query
     * @param $keyword
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeSearch($query, $keyword)
    {
        return $query->where(function($query) use ($keyword) {
            $query->where('code', 'LIKE', "%{$keyword}%")
                ->orWhere('name', 'LIKE', "%{$keyword}%")
                ->orWhere('foo', 'LIKE', "%{$keyword}%")
                ->orWhere('bar', 'LIKE', "%{$keyword}%");
        });
    }

Please advice, thanks a lot

Ps - result will return in JSON and not for blade template,

0 likes
7 replies
ahuggins's avatar

I think your issue is coming from calling paginate() in your accessor.

When you do this: $model->records you are executing the query because of the paginate() call.

So if you try something like this: $model->records->search() it's going to not like it.

You could do this though: $model->applicants()->search() That should allow your search to be appended to the query.

pmall's avatar
pmall
Best Answer
Level 56

However, what I have to do if I want Applicants result being searched by scope and paginated as well ?

No need for accessors here. You can chains relationship queries with scopes like any other queries.

$batch = Batch::findOrFail($batch_id);

$applicants = $batch->applicants()->search()->paginate($nb_applicants_per_page);

$batch->applicants return the batch's collection of applicants, $batch->applicants() return the query for selecting the batch's collection of applicants.

Cryank's avatar

@ahuggins @pmall Thanks for the reply, I agree with you guys. One more question about the usage, I am going to get a Batch by BatchID on my frontend application, which showing info related to that batch as well as its Applicants list.

At this point I can use $batch->applicants for the result of Applicants, but I am wondering how the handle paginate and search in this batch->applicants list.

It seems that I have to separate batch and applicants to make it works ?

    $batch = Batch::findOrFail($batch_id);
    $applicants = $batch->applicants()->search()->paginate($nb_applicants_per_page);

    return Response::json( compact('batch', 'applicants')) ; 

    // So as the result I will get applicants list twice in batch.applicants and  applicants in my JSON ?
pmall's avatar

It seems that I have to separate batch and applicants to make it works ?

Yes of course.

// So as the result I will get applicants list twice in batch.applicants and applicants in my JSON ?

Formatting json output is a completely separate task. You may use a separate package or homemade class to handle json response formatting. You cal also set the hidden/visible fields in your model but I dont like this approach.

Cryank's avatar

@pmall Thank you! Would you mind to give me advice about doing this in a better way instead of hidden fields in model ?

pmall's avatar

You can use the fractal package from php league for this purpose.

Cryank's avatar

@pmall Thank you so much. I will figure it out when I get back to work ! Cheers

Please or to participate in this conversation.