, (*1)
ScopeApplicator brings an elegant way of sorting and filtering data to your Yii2 projects., (*2)
Overview
ScopeApplicator is an easy and logical way to achieve something like this:, (*3)
/posts
โ returns a list of all posts, (*4)
/posts?recent
โ returns only recent posts, (*5)
/posts?author_id=5
โ returns posts belonging to an author with an id=5
, (*6)
/posts?author_id=5&order_by_title=desc&status=active
โ returns only active posts belonging to an author with an id=5
and sorts them by a title in a descending order, (*7)
Requirements
โ PHP 5.4 or newer, (*8)
โ Yii 2.0.x, (*9)
Installation
composer require mobileka/scope-applicator-yii2 1.0.*
, (*10)
Usage
Let's learn by example. First of all, we'll implement an author_id
filter for post
table., (*11)
These are steps required to achieve this:, (*12)
- Create a
PostQuery
class which extends Mobileka\ScopeApplicator\Yii2\ActiveQuery
and define a userId
method
- Create a
Post
model which extends Mobileka\ScopeApplicator\Yii2\Model
and make it use the PostQuery
instead of a regular ActiveQuery
- Create a basic
PostController
which outputs a list of posts when /posts
route is hit
- Tell ScopeApplicator that
userId
scope is available and give it an alias
- Visit
/posts?author_id=1
and enjoy the result
Ok, let's cover these step by step., (*13)
โ Create a PostQuery
class in app/models/queries
directory with the following content:, (*14)
<?php
namespace app\models\queries;
use Mobileka\ScopeApplicator\Yii2\ActiveQuery;
class PostQuery extends ActiveQuery
{
public function userId($id = 0)
{
if ($id) {
return $this->andWhere(['user_id' => $id]);
}
return $this;
}
}
I'll refer the userId()
method as a userId
scope in the future., (*15)
Make sure that this class extends Mobileka\ScopeApplicator\Yii2\ActiveQuery
., (*16)
โ Create a Post
model and override the find
method like follows:, (*17)
<?php
namespace app\models;
use app\models\queries\PostQuery;
use Mobileka\ScopeApplicator\Yii2\Model;
use Yii;
class Post extends Model
{
public static function find()
{
return Yii::createObject(PostQuery::className(), [get_called_class()]);
}
}
This makes sure that our userId
scope will be available to the Post
model., (*18)
โ Next, create a PostController
:, (*19)
<?php
namespace app\controllers;
use Yii;
use yii\web\Response;
use yii\rest\Controller;
use app\models\Post;
class PostController extends Controller
{
public function actionIndex()
{
return Post::find()->all();
}
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['contentNegotiator']['formats'] = [
'application/json' => Response::FORMAT_JSON
];
return $behaviors;
}
}
In this case I extend the yii\rest\Controller
and make sure that its output format is set to JSON., (*20)
โ Now let's modify this controller to make it use ScopeApplicator:, (*21)
<?php
namespace app\controllers;
use Yii;
use yii\web\Response;
use yii\rest\Controller;
use app\models\Post;
class PostController extends Controller
{
/**
* Scope configuration array
*/
protected $scopes = ['userId'];
public function actionIndex()
{
return Post::applyScopes($this->scopes)->all();
}
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['contentNegotiator']['formats'] = [
'application/json' => Response::FORMAT_JSON
];
return $behaviors;
}
}
Note that I added a new protected property which describes available scopes. Right now we have only userId
., (*22)
Also note that I have replaced Post::find()
with Post::applyScopes($this->scopes)
., (*23)
If you have done all the above steps, you should be able to populate your post
table and try to filter data like follows:
/posts?userId=x
., (*24)
But we wanted it to be author_id
instead of userId
, so we have to configure our scope and add an alias:, (*25)
<?php
namespace app\controllers;
use Yii;
use yii\web\Response;
use yii\rest\Controller;
use app\models\Post;
class PostController extends Controller
{
/**
* Scope configuration array
*/
protected $scopes = [
'userId' => [
// here it is!
'alias' => 'author_id'
]
];
public function actionIndex()
{
return Post::applyScopes($this->scopes)->all();
}
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['contentNegotiator']['formats'] = [
'application/json' => Response::FORMAT_JSON
];
return $behaviors;
}
}
โ That's it! Now you can visit /posts?author_id=x
and check the result., (*26)
alias
is only one of the many available scope configuration options. These are described in ScopeApplicator's documentation., (*27)
Contributing
If you have noticed a bug or have suggestions, you can always create an issue or a pull request (use PSR-2). We will discuss the problem or a suggestion and plan the implementation together., (*28)
License
ScopeApplicator is an open-source software and licensed under the MIT License., (*29)