skip to Main Content

In my Setting model. I have a local scope that accepts $data array argument. The $data contains two keys group and property and any of them can be null as you can see in my query.

 public function scopeSettingFilters($query, array $data)
    {
        $query->when(!empty($data['group']), fn($q) => $q->where("group", $data["group"]));

        $query->when(!empty($data['property']), function ($q) use ($data) {
            $property = $data['property'];

            if (str_contains($property, '.')) {
                [$group, $property] = $this->splitKey($data['property']);
                $q->where(["group" => $group, "name" => $property]);

            } else {
                $q->where("name", $property);
            }
        });

        return $query;
    }

Now I want to convert $data array keys to Named Arguments for better code understanding and one major reason for conversion is, that currently the group is accepting only string but now it is either a string or array.

My Setting Table

id user_id group property value
1 1 notifications event_email true
1 1 onboarding welcome_video_watched false

Note: I’m using Laravel 9 Version

Expected Syntax:

After making the required changes I would able to call Laravel query scope using named argument something like that:

Setting::settingFilters(group: "onboarding")->get()    //filter single group

Setting::settingFilters(group: ["onboarding", "notifications"])->get()    //filter multiple groups

2

Answers


  1. Chosen as BEST ANSWER

    I had fixed it using following code:

     public function settingFilters(string|array $group = null, string $property = null)
        {
            $query = $this->settings();
    
            $group = is_array($group) ? $group : [$group];
    
    
            $query->when(!empty($group), fn($q) => $q->whereIn("group", $group));
    
            $query->when(!empty($data['property']), function ($q) use ($property) {
    
                if (str_contains($property, '.')) {
                    [$group, $property] = $this->splitKey($property);
                    $q->where(["group" => $group, "name" => $property]);
    
                } else {
                    $q->where("name", $property);
                }
            });
    
            return $query;
        }
    

  2. If you want to refactor your code to use named arguments, you can change the function signature of scopeSettingFilters to accept named arguments instead of a single $data array. You can set default values for the arguments to null to make them optional.

    Here’s an example that shows how you could refactor your code:

    public function scopeSettingFilters($query, string|array|null $group = null, string|null $property = null)
    {
        // Filter by 'group'
        $query->when(!empty($group), function ($q) use ($group) {
            if (is_array($group)) {
                $q->whereIn('group', $group);
            } else {
                $q->where('group', $group);
            }
        });
    
        // Filter by 'property'
        $query->when(!empty($property), function ($q) use ($property) {
            if (str_contains($property, '.')) {
                [$group, $property] = $this->splitKey($property);
                $q->where(['group' => $group, 'name' => $property]);
            } else {
                $q->where('name', $property);
            }
        });
    
        return $query;
    }
    

    Key changes:

    The function now accepts named arguments $group and $property, both of which have default values set to null.

    Inside the lambda function for the when() method, I’ve added a check for $group being an array. If it is an array, it uses whereIn to filter by multiple group names; otherwise, it uses where as you did before.

    Now you can call this scope with named arguments like so:

    // With a single group name
    $query->settingFilters(group: 'someGroup');
    
    // With multiple group names
    $query->settingFilters(group: ['group1', 'group2']);
    
    // With a property
    $query->settingFilters(property: 'someProperty');
    
    // With both a group and a property
    $query->settingFilters(group: 'someGroup', property: 'someProperty');
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search