Pass Variable from Component to Model Scope

2019-07-07 17:19发布

问题:

I'm using OctoberCMS based on Laravel.

I'm trying to get the identifier from URL and pass it to the Scope to filter database results.

$this->property('username') works and returns the username from the URL.

But how do you pass it to the Model and into the Scope function?

Here is the guide, under Dynamic Scopes.

https://octobercms.com/docs/database/model#query-scopes

Page

URL: localhost/user/matt

Identifier: /user/:username

Results Component

public function init()
{
    // get username from url
    $username = $this->property('username'); //matt

    // pass username to scope
    Gallery::applyUser($username);
}

Gallery Model

// return results that match username
public function scopeApplyUser($query, $username)
{
    return $query->where('username', $username);
}

Error

Missing argument 2 for MyVendor\Gallery\Models\Gallery::scopeApplyUser()

Solution?

I found adding ($query, $username = null) allows the variable to pass without error.

But now the problem is that $username is both 'matt' and null at the same time and never makes it to the query return.

// return results that match username
public function scopeApplyUser($query, $username = null)
{
    print $username; //prints matt
    if ($username == null) { print 'null'; } //prints null

    return $query->where('username', $username); //returns null
}

回答1:

In a model gallery you need a field user:

class Gallery extends Model {
    /** these are just placeholder variables you should be recognising these from your own model.!**/
    protected $table = 'gallery';
    protected $guarded = ['*'];
    protected $fillable = ['username'];// Make sure this also is in the database!!
    public scopeWhereUser($query, $user = null) {
        if(!is_null($user)) { // Only do something if the username is provided!
           $query->where('username',$user);
        }
    }
}

Then, when you have the nullchecks you can just call it with

 $gallery = new Gallery();
 $query = $gallery->newQuery()->where('x','y')->whereUser('matt');

Changes I made:

  • renamed scope to whereuser instead of apply user because it's more logical to name it that way. Apply you do to something functional that changes a state permanently
  • added a not is_null() check to only limit the query when it's not null.

full working example that prints the results:

 $gallery = new Gallery();
 $query = $gallery->newQuery()->where('x','y')->whereUser('matt');
 $results = $query->get();
 foreach($results as $galleryItem) {
     echo $galleryItem->getKey() . ' is having:<BR/>';
     echo dump([
               'model'=>$galleryItem,
               'methods' => get_class_methods(get_class($galleryItem)),
               ]);
 }