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

musa11971's avatar

Custom Eloquent query scope with pivot

I had a look at Eloquent query scopes, but could not find a way to do the following:

User model:

class User extends Model {
    /**
     * Returns the items in the user's library.
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
     */
    function library() {
        return $this->belongsToMany(Item::class, UserItem::class, 'user_id', 'item_id')
            ->withPivot('status');
    }
}

Desired behavior:

// Return the items in the library as normal
$user->library()

// Returns the same as:
// $user->library()->wherePivot('status', 'being_processed');
$user->library()->beingProcessed()

// This should attach an item, the same way as:
// $user->library()->attach(1, ['status' => 'being_processed']);
$user->library()->beingProcessed()->attach(1)

Can this be achieved using Eloquent query scopes, or maybe some other way?

0 likes
5 replies
musa11971's avatar

@ismaile I added that to the model and got this:

$user->library()->beingProcessed();
BadMethodCallException with message 'Call to undefined method Illuminate/Database/Eloquent/Relations/BelongsToMany::beingProcessed()'
ismaile's avatar

@musa11971 Sorry, I have been a bit quick to respond and didn't pay attention. I have removed the answer since it was not relevant. Local scopes are used to filter a model not a relation.

This should work:

public function libraryBeingProcessed()
    {
        return $this->library()->wherePivot('status', 'being_processed');
    }

And you can use it like so:

$user->libraryBeingProcessed();
a4ashraf's avatar

@musa11971

Please try this following code in your model


public function scopeLibraryProcessed()
    {
        return $this->library()->wherePivot('status', 'being_processed');
    }

and call the query scope with this way


$user = App\User::find(2)->LibraryProcessed()->get();

or

$user = App\User::LibraryProcessed()->get();

musa11971's avatar

@ismaile This works for retrieving the models. However, as I mentioned in the original post, I would really like this behavior as well:

// This should attach an item, the same way as:
// $user->library()->attach(1, ['status' => 'being_processed']);
$user->libraryBeingProcessed()->attach(1);

Current using $user->libraryBeingProcessed()->attach(1);, attaches it without the correct status.

Is there a way around this?

ismaile's avatar
ismaile
Best Answer
Level 30

@musa11971

I don't think this is possible. attach expects the id and the pivot table values.

You can embed your logic in a method instead:

public function addALibraryBeingProcessed($library_id)
{
    $this->library()->attach($library_id, ['status' => 'being_processed']);
}

PS: On a side note, regarding the naming, I would change library to libraries for the methods library and libraryBeingProcessed since we are expecting many libraries per user.

1 like

Please or to participate in this conversation.