Suggestion to add multi-level relations to ActiveRecord::extraFields() #3303

Open
alexweb opened this Issue Apr 30, 2014 · 50 comments

Comments

Projects
None yet
@alexweb

alexweb commented Apr 30, 2014

Currrently there is no possibility to dynamically manage relations that should be included to respond in case when relation level is bigger than one.
For example we have model Business and you can define Locations relation like this:

    public function extraFields()
    {
        $fields = parent::fields();
        $fields[]='locations';
        return $fields;
    }

And then you can include it to respond using ?expand="locations"

But if we want to include Locations together with related location Schedules, then that doesn't work.

I suggest to implement multi-level relations (using dot notation):

    public function extraFields()
    {
        $fields = parent::fields();
        $fields[]='locations';
        $fields[]='locations.schedule';
        return $fields;
    }

And then it will be possible to use it this way: ?expand="locations, locations.schedule"

I think it would be nice, because it's very often needed to manage relation records that should be included to respond.
Is it possible?

@cebe cebe added this to the 2.1 milestone Apr 30, 2014

@qiangxue

This comment has been minimized.

Show comment
Hide comment
@qiangxue

qiangxue Apr 30, 2014

Member

I thought about this. It's not trivial, especially if you also want to support selectively pick up certain fields from relations.

Member

qiangxue commented Apr 30, 2014

I thought about this. It's not trivial, especially if you also want to support selectively pick up certain fields from relations.

@cebe

This comment has been minimized.

Show comment
Hide comment
@cebe

cebe Apr 30, 2014

Member

can't we delegate this to the extraFields method of the related model and use definitions from there?

Member

cebe commented Apr 30, 2014

can't we delegate this to the extraFields method of the related model and use definitions from there?

@qiangxue

This comment has been minimized.

Show comment
Hide comment
@qiangxue

qiangxue Apr 30, 2014

Member

How will the GET query parameter looks like? How to go from there to the method parameters?

Member

qiangxue commented Apr 30, 2014

How will the GET query parameter looks like? How to go from there to the method parameters?

@creocoder

This comment has been minimized.

Show comment
Hide comment
@creocoder

creocoder May 30, 2014

Contributor

can't we delegate this to the extraFields method of the related model and use definitions from there?

We do not need do that!

Please read this: http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api#autoloading

All we need is support expand or embed parameter.

I thought about this. It's not trivial, especially if you also want to support selectively pick up certain fields from relations.

From client side there is no feature to selectively pick up certain fields from relations in expand/embed. It will be overcoding.

From model side it can be easily handled like:

class Product extends ActiveRecord
{
    public function extraFields()
    {
        return [
            'price',
            'quantity',
            'categories' => ['id', 'title'], <- LOOK HERE
        ];
    }
}
Contributor

creocoder commented May 30, 2014

can't we delegate this to the extraFields method of the related model and use definitions from there?

We do not need do that!

Please read this: http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api#autoloading

All we need is support expand or embed parameter.

I thought about this. It's not trivial, especially if you also want to support selectively pick up certain fields from relations.

From client side there is no feature to selectively pick up certain fields from relations in expand/embed. It will be overcoding.

From model side it can be easily handled like:

class Product extends ActiveRecord
{
    public function extraFields()
    {
        return [
            'price',
            'quantity',
            'categories' => ['id', 'title'], <- LOOK HERE
        ];
    }
}
@creocoder

This comment has been minimized.

Show comment
Hide comment
@creocoder

creocoder May 30, 2014

Contributor

So query like GET /products?expand=price,categories will give you result:

{
    "id": 1,
    "title": "Foo",
    "price": "$10",
    "categories": [
        {
            "id": 1,
            "title": "Bar"
        },
        {
            "id": 2,
            "title": "Baz"
        }
    }
}
Contributor

creocoder commented May 30, 2014

So query like GET /products?expand=price,categories will give you result:

{
    "id": 1,
    "title": "Foo",
    "price": "$10",
    "categories": [
        {
            "id": 1,
            "title": "Bar"
        },
        {
            "id": 2,
            "title": "Baz"
        }
    }
}
@xterr

This comment has been minimized.

Show comment
Hide comment
@xterr

xterr Mar 11, 2015

Contributor

+1

Contributor

xterr commented Mar 11, 2015

+1

@bogdaniy

This comment has been minimized.

Show comment
Hide comment

+1

@jcvalerio

This comment has been minimized.

Show comment
Hide comment
@jcvalerio

jcvalerio Apr 27, 2015

Contributor

+1

Contributor

jcvalerio commented Apr 27, 2015

+1

@eberon

This comment has been minimized.

Show comment
Hide comment

eberon commented May 23, 2015

+1

@akaNightmare

This comment has been minimized.

Show comment
Hide comment

+1

@kadanin

This comment has been minimized.

Show comment
Hide comment

kadanin commented Jun 4, 2015

+1

@juanagu

This comment has been minimized.

Show comment
Hide comment

juanagu commented Jun 24, 2015

+1

@kadanin

This comment has been minimized.

Show comment
Hide comment
@kadanin

kadanin Jun 25, 2015

Where in code YII2 looks for "expand" parameter to choose which extra fields must be shown?

kadanin commented Jun 25, 2015

Where in code YII2 looks for "expand" parameter to choose which extra fields must be shown?

@cebe

This comment has been minimized.

Show comment
Hide comment
@cebe

cebe Jun 25, 2015

Member

Where in code YII2 looks for "expand" parameter to choose which extra fields must be shown?

https://github.com/yiisoft/yii2/blob/master/framework/rest/Serializer.php#L159

Member

cebe commented Jun 25, 2015

Where in code YII2 looks for "expand" parameter to choose which extra fields must be shown?

https://github.com/yiisoft/yii2/blob/master/framework/rest/Serializer.php#L159

@riyaskp

This comment has been minimized.

Show comment
Hide comment

riyaskp commented Aug 3, 2015

+1

@One-art

This comment has been minimized.

Show comment
Hide comment
@One-art

One-art Aug 24, 2015

This problem make me cry, really!
I want to get list of "items" with author.
And in author I want to get Full name extra field.
But it's not working at all. Expand not using custom fields.

One-art commented Aug 24, 2015

This problem make me cry, really!
I want to get list of "items" with author.
And in author I want to get Full name extra field.
But it's not working at all. Expand not using custom fields.

@jasonhancock

This comment has been minimized.

Show comment
Hide comment

+1

@eborned

This comment has been minimized.

Show comment
Hide comment
@eborned

eborned Aug 31, 2015

For the moment, I've worked around this problem by overruling the fields() call in my ActiveRecord model.

class MultiLevelActiveRecord extends \yii\db\ActiveRecord
{
    public function fields()
    {
        $fields = parent::fields();

        // Add multi-level expanded fields
        $expandFields = explode(',', Yii::$app->request->getQueryParam('expand'));
        foreach ($expandFields as $field)
        {
            if (strpos($field, strtolower($this->formName()).'.') === 0)
            {
                $fields[] = substr($field, strlen($this->formName()) + 1);
            }
        }

        return $fields;
    }
}

That enabled me to use:

?expand=category,author.name

But only based on exact modal names, and not based on relations. It's dirty, but does the job for me.

eborned commented Aug 31, 2015

For the moment, I've worked around this problem by overruling the fields() call in my ActiveRecord model.

class MultiLevelActiveRecord extends \yii\db\ActiveRecord
{
    public function fields()
    {
        $fields = parent::fields();

        // Add multi-level expanded fields
        $expandFields = explode(',', Yii::$app->request->getQueryParam('expand'));
        foreach ($expandFields as $field)
        {
            if (strpos($field, strtolower($this->formName()).'.') === 0)
            {
                $fields[] = substr($field, strlen($this->formName()) + 1);
            }
        }

        return $fields;
    }
}

That enabled me to use:

?expand=category,author.name

But only based on exact modal names, and not based on relations. It's dirty, but does the job for me.

@mushahidh

This comment has been minimized.

Show comment
Hide comment

+1

@supr-d

This comment has been minimized.

Show comment
Hide comment

supr-d commented Sep 19, 2015

+1

@tendallas

This comment has been minimized.

Show comment
Hide comment

+1

@jacksumit

This comment has been minimized.

Show comment
Hide comment

+1

@pgarriga

This comment has been minimized.

Show comment
Hide comment

+1

@manquer

This comment has been minimized.

Show comment
Hide comment

manquer commented Nov 27, 2015

+1

@Tr9

This comment has been minimized.

Show comment
Hide comment

Tr9 commented Dec 1, 2015

+1

@Forin

This comment has been minimized.

Show comment
Hide comment

Forin commented Dec 1, 2015

+1

@mattether

This comment has been minimized.

Show comment
Hide comment
@mattether

mattether Dec 1, 2015

Contributor

+1

Contributor

mattether commented Dec 1, 2015

+1

@Faryshta

This comment has been minimized.

Show comment
Hide comment
@Faryshta

Faryshta Dec 1, 2015

Contributor

+1

Contributor

Faryshta commented Dec 1, 2015

+1

@pedromalta

This comment has been minimized.

Show comment
Hide comment

+1

@nancoder

This comment has been minimized.

Show comment
Hide comment

+1

@dawei101

This comment has been minimized.

Show comment
Hide comment
@dawei101

dawei101 Dec 25, 2015

Contributor

+1

Contributor

dawei101 commented Dec 25, 2015

+1

@nkostadinov

This comment has been minimized.

Show comment
Hide comment
@nkostadinov

nkostadinov Dec 25, 2015

I'm currently implementing something to handle this issue. I use scopes, so I define each scope in the model and the client requests the scopes to be returned. The request is

?scope=profile,orders,locations 

and in the model I define them as arrays like in fields(). I personally don't think that the client should be able to define exactly what to be returned it should be limited to scopes defined on the server. It can be easily used with oauth server(in my case) which limits the visible scopes for each client.

I'm currently implementing something to handle this issue. I use scopes, so I define each scope in the model and the client requests the scopes to be returned. The request is

?scope=profile,orders,locations 

and in the model I define them as arrays like in fields(). I personally don't think that the client should be able to define exactly what to be returned it should be limited to scopes defined on the server. It can be easily used with oauth server(in my case) which limits the visible scopes for each client.

@nerburish

This comment has been minimized.

Show comment
Hide comment

+1

@xfg

This comment has been minimized.

Show comment
Hide comment

xfg commented Jan 14, 2016

+1

@vadim-bulochnik

This comment has been minimized.

Show comment
Hide comment
@ilves

This comment has been minimized.

Show comment
Hide comment

ilves commented Feb 18, 2016

+1

@panrus

This comment has been minimized.

Show comment
Hide comment

panrus commented Mar 29, 2016

+1

@vertamedia-teamcity-github

This comment has been minimized.

Show comment
Hide comment
@sazo

This comment has been minimized.

Show comment
Hide comment

sazo commented Apr 4, 2016

+1

@vnddr

This comment has been minimized.

Show comment
Hide comment

vnddr commented Apr 12, 2016

+1

@tdimdimich

This comment has been minimized.

Show comment
Hide comment

+1

@dcb9

This comment has been minimized.

Show comment
Hide comment
@dcb9

dcb9 May 2, 2016

Contributor

+1

Contributor

dcb9 commented May 2, 2016

+1

@SilverFire

This comment has been minimized.

Show comment
Hide comment
@SilverFire

SilverFire May 3, 2016

Member

Please, use 👍 emoticon to the first message in this issue instead of adding more "+1" comments. Thank you!

Member

SilverFire commented May 3, 2016

Please, use 👍 emoticon to the first message in this issue instead of adding more "+1" comments. Thank you!

@Faryshta

This comment has been minimized.

Show comment
Hide comment
@Faryshta

Faryshta May 3, 2016

Contributor

@SilverFire i think the reason is because reactions emojis doesn't get attention.

Contributor

Faryshta commented May 3, 2016

@SilverFire i think the reason is because reactions emojis doesn't get attention.

@SilverFire

This comment has been minimized.

Show comment
Hide comment
@SilverFire

SilverFire May 3, 2016

Member

We have enough members asking for this feature, so we already know that we should take care about this issue. Clicking "+1" is OK to let us know, that you want this kind of enhancement too. We appreciate all kinds of help. We are thankful for showing, what is important for you and will take care of it. GitHub added emotions to help managing daily flow of changes in repo. Thank you

Member

SilverFire commented May 3, 2016

We have enough members asking for this feature, so we already know that we should take care about this issue. Clicking "+1" is OK to let us know, that you want this kind of enhancement too. We appreciate all kinds of help. We are thankful for showing, what is important for you and will take care of it. GitHub added emotions to help managing daily flow of changes in repo. Thank you

@yiisoft yiisoft locked and limited conversation to collaborators May 3, 2016

@yiisoft yiisoft unlocked this conversation May 3, 2016

@SilverFire

This comment has been minimized.

Show comment
Hide comment
@SilverFire

SilverFire May 3, 2016

Member

I'm not locking the conversation. We will be happy to hear more feedback from you

Member

SilverFire commented May 3, 2016

I'm not locking the conversation. We will be happy to hear more feedback from you

@Faryshta

This comment has been minimized.

Show comment
Hide comment
@Faryshta

Faryshta May 3, 2016

Contributor

There are currently two PR's from @mdmunir with two different approaches on how to solve this feature request #11493 and #11476 I think the people here should check them and see which oneis easier to implement and use.

Contributor

Faryshta commented May 3, 2016

There are currently two PR's from @mdmunir with two different approaches on how to solve this feature request #11493 and #11476 I think the people here should check them and see which oneis easier to implement and use.

@gonimar

This comment has been minimized.

Show comment
Hide comment
@gonimar

gonimar May 31, 2017

Contributor

+1

Contributor

gonimar commented May 31, 2017

+1

@lubobill1990

This comment has been minimized.

Show comment
Hide comment

+1

@samdark samdark modified the milestones: 2.1.x, 2.1.0 Dec 18, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment