New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix for #4479 REST filter #12641
Fix for #4479 REST filter #12641
Conversation
Added support for request via body content at
|
Is there a reason to use |
This is a practice borrowed from ElasticSearch and MongoDB. In particular I can provide following reasons:
|
Also note that all operators are configurable: you can change thier keywords to whatever you like. |
Yes, I've noticed that. I'm concerned about defaults. |
A good format. It seems to abandon the Here's what I don't like: applications, simultaneously, using forms and REST API for the same model, will have to make several implementations of the filters (searchModel and dataFilter models). In fact, we want to implement the same behavior, but we still need to write it twice. |
You can reuse a search model created for the regular 'frontend' listing in REST even without this fix via class SearchModel extends \yii\base\Model
{
// ...
public function search($params, $formName = null)
{
$query = Item::find();
// add conditions that should always apply here
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$this->load($params, $formName); // remember that you can pass `formName` directly to the `load()` method
if (!$this->validate()) {
$query->where('0=1');
return $formName === '' ? $this : $dataProvider;
}
}
class ItemController extends \yii\rest\ActiveController
{
// ...
public function actions()
{
return [
'index' => [
'class' => 'yii\rest\IndexAction',
'modelClass' => $this->modelClass,
'prepareDataProvider' => function () {
$searchModel = new SearchModel();
return $searchModel->search(Yii::$app->request->queryParams, '');
},
],
];
} With such code: search at the regular 'frontend' will be performed via following URL:
while for the REST - URL will be following:
There is no need to change something to implement simpliest search in the REST. I have alreay told this here: This PR introduces sophisticated search condition builder, which can be used for creating 'database-like' search interface. |
@klimov-paul shouldn't that SearchModel replace the old one here ? also what do you think about adding an interface for it ? (see related discussion in #11470) |
Unlikely, because it more complex and thus will confuse newcomers.
I am unsure if search interface can be made generic enough. It still may need extra options. |
Refactored:
|
framework/rest/DataFilter.php
Outdated
public function setSearchModel($model) | ||
{ | ||
if (is_object($model)) { | ||
if (!$model instanceof Model && !$model instanceof \Closure) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could be moved to the condition above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, it could not: $model
may be an array or string class name, which is a valid value and should not throw an exception.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
$model may be an array
Then it will not be object and no exception will be thrown
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
|
||
foreach ($model->getValidators() as $validator) { | ||
$type = null; | ||
if ($validator instanceof BooleanValidator) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd move this part to a separate protected method to make it easier to adjust for custom validators.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Disagreed.
It is meant to override a whole detectSearchAttributeTypes()
ot provide some sophosticated type detecttion mechanism. Particular implementation may not process validators at all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding custom validator does not lead to any sophisticated type detection logic. It is still a map: class to type. I don't think that overriding the whole method (including logic) is a right way for filter configuration.
Moreover, current approach increases formal cyclomatic complexity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Repeat once more: method detectSearchAttributeTypes()
as a whole determines the search attribute types. The actual algorithm of its detection may be different.
For example: you may want to get types from DB table schema, or may want to parse PHPDoc searching for type-hints.
It is only a single particular implementation, which relies on model validators.
If I add extra method for validators processing, it will become useless and never will be invoked in case detectSearchAttributeTypes()
rewritten to use DB table schema.
I don't think that overriding the whole method (including logic) is a right way for filter configuration.
How is method override related to filter configuration? You can set $searchAttributeTypes
via setSearchAttributeTypes()
to whatever you like. Method detectSearchAttributeTypes()
invoked only in case there are $searchAttributeTypes
explicitly configured.
framework/rest/DataFilter.php
Outdated
public $attributeMap = []; | ||
|
||
/** | ||
* @var array list of error messages responding to invalid filter structure, in format: `[errorKey => message]`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
array|\Closure
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
Code and user API looks good to me. @klimov-paul should it be described in the guide? |
Extra docs will not hurt. But I can not afford to waste any more time on this. |
OK. |
@yiisoft/reviewers need your help to:
Thanks. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good otherwise
framework/rest/IndexAction.php
Outdated
* | ||
* @see DataFilter | ||
* | ||
* @since 2.0.10 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2.0.13
Merged. Thanks for solving it. |
Docs will be handled separately but for 2.0.13 as well. |
Implemented REST filter.
Format inspired from the ones used by ElasticSearch and MongoDB.