Closed saada closed 4 years ago
+1
BTW some frontside REST libraries (like restangular) allow you to do it out the box. So, if this ability will be on the server side - it would be really cool.
+1
Any suggestions for PHP syntax for the feature? i.e. how you want it to look in Yii terms when using it.
This could be a special URL rule class, which accepts 2 config parameters: 'modelClass' and 'relations':
'rules' => [
[
'class' => 'yii\rest\NestedModelUrlRule',
'modelClass' => 'app\models\Magazine',
'relations' => ['ads'],
],
],
@klimov-paul :+1:
@klimov-paul, I like that! I would suggest doing it at the controller level. Something along the below lines...
MagazineController extends Controller {
public function resources() {
return [
AdController::className()
];
}
}
AdController extends Controller {
public function resources() {
return [
CommentController::className()
];
}
}
The above could mean that you expose these routes:
/magazine/:magazine_id:/ads
/magazine/:magazine_id:/ad/:ad_id:/comments
/ad/:ad_id:/comments
/ad/:ad_id:/comment/4
NOTICE: plural vs singular routes
@klimov-paul it looks very good. It would be great to use arrays instead of string if we nee. E.g.
'rules' => [
[
'class' => 'yii\rest\NestedModelUrlRule',
'modelClass' => 'app\models\Magazine',
'relations' => [
'ads' => [
'relations' => [
'comments'
]
]
],
],
],
@usualdesigner , would your example allow all these routes to be exposed?
/magazine/:magazine_id:/ads
/magazine/:magazine_id:/ad/:ad_id:/comments
/ad/:ad_id:/comments
/ad/:ad_id:/comment/4
or just these two?
/magazine/:magazine_id:/ads
/magazine/:magazine_id:/ad/:ad_id:/comments
Also, it's weird to mention some classes by namespace app\models\Magazine
and others by just alias ads
or comments
. Thoughts on this?
As I was reading the rails docs, I found another interesting, and related concept is Shallow Nesting and Routing Concerns. http://guides.rubyonrails.org/routing.html#routing-concerns
This matter concerns not only URL routes but controller actions as well. I am afraid we are outmatched against Ruby here.
any progress on this ?
A POST to /magazine/:magazine_id:/ads
should correctly assign $ads->magazine_id
before saving the new created data for example. Especial exception may be thrown if no magazine exist with magazine_id
value ...
By initialising a modelClass
instance in yii\rest\NestedModelUrlRule
is that also mean modifying the activeController class by serving its actions different dataProvider instances ? or it is about building a new class to handle CRUD's ?
@klimov-paul do you have a suggestion about how to properly relate models if using this special URL rule class ?
related/duplicate of #9474
Here's my API update leveraging existing relationships in the models.
Introducing the new Controller::resource($className, $relationship)
syntax
// controllers/MagazineController.php
MagazineController extends Controller {
public function actionAds() {
return $this->resource(Magazine::className(), 'ads');
}
}
// controllers/AdController.php
AdController extends Controller {
public function actionMagazine() {
return $this->resource(Ad::className(), 'magazine');
}
}
// models/Magazine.php
Magazine extends ActiveRecord {
public function getAds() {
return $this->hasMany(Ad::className(), ['id' => 'ad_id']);
}
}
// models/Ad.php
Ad extends ActiveRecord {
public function getMagazine() {
return $this->hasOne(Magazine::className(), ['ad_id' => 'id']);
}
}
HTTP Verb | Path | Controller#Action | Used for |
---|---|---|---|
GET | /magazines/:magazine_id/ads | AdsController::actionIndex | display a list of all ads for a specific magazine |
GET | /magazines/:magazine_id/ads/create | AdsController::actionCreate | return an HTML form for creating a new ad belonging to a specific magazine |
POST | /magazines/:magazine_id/ads | AdsController::actionCreate | create a new ad belonging to a specific magazine |
GET | /magazines/:magazine_id/ads/:id | AdsController::actionView | display a specific ad belonging to a specific magazine |
GET | /magazines/:magazine_id/ads/:id/update | AdsController::actionUpdate | return an HTML form for editing an ad belonging to a specific magazine |
PATCH/PUT | /magazines/:magazine_id/ads/:id | AdsController::actionUpdate | update a specific ad belonging to a specific magazine |
DELETE | /magazines/:magazine_id/ads/:id | AdsController::actionDelete | delete a specific ad belonging to a specific magazine |
I think this approach is a lot more familiar/flexible. @samdark , @klimov-paul, @mikehaertl ... what do you guys think?
+1
I also found this feature in Laravel: http://laravel.com/docs/5.1/controllers#restful-resource-controllers
here's my suggested interface for modifying the query or data https://github.com/yiisoft/yii2/issues/7184#issuecomment-73396628 however it is more generic and doesn't exactly do it as relations
the advantage of my approach is that for example
GET /magazines/1234
returns a 403 only for that specific 1234 ID for the magazine then
GET /magazines/1234/ads/456 or /magazines/1234/ads
will also return a 403
now i am not sure if this is a desired behavior or not
+1, also you can just write custom urlrule... http://stackoverflow.com/questions/27798088/yii2-nested-resources-best-practice
Here is an extension doing that: https://github.com/tunecino/yii2-nested-rest
+1
Should this be moved to https://github.com/yiisoft/yii-rest?
Yes.
Currently it seems to be out of our scope.
In the Rails world they use "Resources" to describe nested routes. Here's a reference for further reading. http://guides.rubyonrails.org/routing.html#nested-resources
It would be great to add this feature to Yii2.
The above code gives you these routes out of the box