evan108108 / RESTFullYii

RESTFull API for your Yii application
http://evan108108.github.com/RESTFullYii/
320 stars 114 forks source link

Filter based on relations #51

Closed blitzjs closed 10 years ago

blitzjs commented 11 years ago

Is there a way to filter based on relations?

evan108108 commented 11 years ago

No that is not currently supported. I will consider it for future versions. It will require lazy loading to be turned off and a few changes to the filter behavior.

You could implement this without changing RESTFullYii core. You will need to hook at least these two events:

  1. pre.filter.model.filter (You will have to strip out your relation filter as this will cause errors)
  2. model.find.all (You will have to apply your custom filter logic here)

Hope that helps. Please let me know if you have any ideas on future implementation of this feature.

-evan

blitzjs commented 11 years ago

I've been doing some prototyping to see if I'll be able to use this extension for an upcoming project.

From what I've seen so far, in the model.find.all event, instead of model()->findAll(), you would need to add something like:

with( array ( 'myRelation' => array('condition' => ..., 'params'=> ...), 'myRelation2' => array('condition' => ..., 'params'=> ...), ) )->findAll();

where each relation is pulled from either the filter attribute (or a new property that represents an attribute, i.e. filterRelation) using a . as the separator..

Given this request: /api/photo?filterRelation = [ {"property": "baseEntity.user_id", "value" : "18", "operator": "="} ]

the property baseEntity.user_id would be split into the two parts baseEntity and user_id. A map would have to be maintained of the different relations and each of their condition and param lists.

evan108108 commented 11 years ago

Yes I agree that something like the approach above would be the way to go. This would be a nice feature to build into core. I should have some time next week to work on this feature, but I would be very pleased if you would like to take a stab at it and submit a pull request.

That said you should be able to implement exactly that using the method I suggested above. To review you could strip the filter objects that have a DOT from the _GET var (pre.filter.model.filter) and set them in some other global. Now in your model.find.all you could apply the above method. A bit hacky but should get the job done until the feature has been added to core.

Thank you for your input! :cake:

blitzjs commented 11 years ago

https://github.com/blitzjs/RESTFullYii/compare/evan108108:master...master

I did a really rough prototype, I basically took a subset of your filter method and worked it in.

Again to keep things simple, I used filterRelation instead of just filter but I think you get the idea. This allows me to at least get past this issue and continue with my prototype.

Note that $model->count() no longer is accurate... so the response's totalCount is off but the data is correct.

evan108108 commented 11 years ago

This looks promising! I will take a look tomorrow and see if I can't get this in.

Thank you so much!