Get "PHP 8 in a Nuthshell" (Now with PHP 8.4)
Amit Merchant

Amit Merchant

A blog on PHP, JavaScript, and more

The new withAttributes method for relationships and scopes in Laravel

Scopes in Laravel are a way to encapsulate common queries that you may need to run against a model. They allow you to define a query you can use in multiple places in your application.

This minimizes the code while writing the query and is an easy way to ensure every query for a given model receives certain constraints.

Here’s an example of a local scope in Laravel for instance.

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    /**
     * Scope a query to only include the most starred posts.
     *
     * @param  \Illuminate\Database\Eloquent\Builder  $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeStarred($query)
    {
        return $query->where('starred', '>', 30);
    }
}

// this will return all the 
// posts that have more than 30 stars
$posts = Post::starred()->get();

As you can tell, the starred scope is a local scope that returns all the posts that have more than 30 stars. The same goes for global scopes as well.

The new withAttributes method

To make scopes more powerful, the newest release brings a new method called withAttributes that allows you to add a where clause to the query with the given attribute constraints, and also applies the attributes to any model that are created via the relationship or scope.

This means that not only will the query be constrained by the attributes, but any models that are created via the relationship or scope will also have the attributes applied automatically.

Using it on scopes

Here’s an example of how you can use the withAttributes method on a scope.

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    /**
     * Scope a query to only include the most starred posts.
     *
     * @param  \Illuminate\Database\Eloquent\Builder  $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeFeatured($query)
    {
        return $query->withAttributes(['featured' => true]);
    }
}

Here’s how you can use this for both, creating a model and querying the model.

<?php

use App\Post;

// this will create a new post with 
// the `featured` attribute set to `true`
$post = Post::featured()->create([
    'title' => 'My featured post'
]);

$post->featured; // true

// this will return all the posts that 
// have the `featured` attribute set to `true`
$posts = Post::featured()->get();

Using it in relationships

You can also use the withAttributes method on relationships. Here’s an example.

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    public function posts()
    {
        return $this->hasMany(Post::class);
    }

    public function featuredPosts()
    {
        return $this->posts()->withAttributes(['featured' => true]);
    }
}

Here’s how you can use it to retrieve all the featured posts for a user.

<?php

use App\User;

$user = User::find(1);

// this will return all the posts
// that have the `featured` attribute set to `true`
$posts = $user->featuredPosts()->get();

Similarly, you can also set the attributes while creating a new model via the relationship.

<?php

use App\User;

$user = User::find(1);

// this will create a new post with
// the `featured` attribute set to `true`
$post = $user->featuredPosts()->create([
    'title' => 'My featured post'
]);

$post->featured; // true

In closing

I think this feature is pretty neat and it essentially combines two scenarios into one conveniently. It’s a nice addition to Laravel’s Eloquent ORM and I’m sure it will be useful in many instances.

Learn the fundamentals of PHP 8 (including 8.1, 8.2, 8.3, and 8.4), the latest version of PHP, and how to use it today with my new book PHP 8 in a Nutshell. It's a no-fluff and easy-to-digest guide to the latest features and nitty-gritty details of PHP 8. So, if you're looking for a quick and easy way to PHP 8, this is the book for you.

Like this article?

Buy me a coffee

👋 Hi there! I'm Amit. I write articles about all things web development. You can become a sponsor on my blog to help me continue my writing journey and get your brand in front of thousands of eyes.

Comments?