Reputation: 59
I am working on Restful APIs of Yii.
My controller name is ProductsController
and the Model is Product
.
When I call API like this GET /products
, I got the listing of all the products.
But, now I want to filter the records inside the listing API.
For Example, I only want those records Which are having a product name as chairs
.
How to implement this?
How to apply proper filtering on my Rest API. I am new to this. So, I have no idea how to implement this. I also followed their documentation but unable to understand.
May someone please suggest me a good example or a way to achieve this?
Upvotes: 2
Views: 2689
Reputation: 18021
First of all you need to have validation rules in your model as usual.
Then it's the controllers job and depending on the chosen implementation I can give you some hints:
ProductsController
extends yii\rest\ActiveController
Basically the easiest way because almost everything is already prepared for you. You just need to provide the $modelClass
there and tweak actions()
method a bit.
public function actions()
{
$actions = parent::actions();
$actions['index']['dataFilter'] = [
'class' => \yii\data\ActiveDataFilter::class,
'searchModel' => $this->modelClass,
];
return $actions;
}
Here we are modifying the configuration for IndexAction which is by default responsible for GET /products
request handling. The configuration is defined here and we want to just add dataFilter
key configured to use ActiveDataFilter which processes filter query on the searched model which is our Product
. The other actions are remaining the same.
Now you can use DataProvider filters like this (assuming that property storing the product's name is name
):
GET /products?filter[name]=chairs
will return list of all Products where name is chairs
,GET /products?filter[name][like]=chairs
will return list of all Products where name contains word chairs
.ProductsController
doesn't extend yii\rest\ActiveController
but you are still using DataProvider to get collectionHopefully your ProductsController
extends yii\rest\Controller
because it will already benefit from serializer and other utilities but it's not required.
The solution is the same as above but now you have to add it by yourself so make sure your controller's action contains something like this:
$requestParams = \Yii::$app->getRequest()->getBodyParams(); // [1]
if (empty($requestParams)) {
$requestParams = \Yii::$app->getRequest()->getQueryParams(); // [2]
}
$dataFilter = new \yii\data\ActiveDataFilter([
'searchModel' => Product::class // [3]
]);
if ($dataFilter->load($requestParams)) {
$filter = $dataFilter->build(); // [4]
if ($filter === false) { // [5]
return $dataFilter;
}
}
$query = Product::find();
if (!empty($filter)) {
$query->andWhere($filter); // [6]
}
return new \yii\data\ActiveDataProvider([
'query' => $query,
'pagination' => [
'params' => $requestParams,
],
'sort' => [
'params' => $requestParams,
],
]); // [7]
What is going on here (numbers matching the code comments):
Product
,false
it means there is an error (usually unsuccessful validation) so we return the object to user to see list of errors,Product
,Now you can use DataProvider filters just as mentioned above.
ProductsController
doesn't use DataProvider to get collectionYou need to create your custom solution.
Upvotes: 7