active-record icon indicating copy to clipboard operation
active-record copied to clipboard

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

Open alexweb-zz opened this issue 11 years ago • 50 comments
trafficstars

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?

alexweb-zz avatar Apr 30 '14 12:04 alexweb-zz

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

qiangxue avatar Apr 30 '14 12:04 qiangxue

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

cebe avatar Apr 30 '14 12:04 cebe

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

qiangxue avatar Apr 30 '14 14:04 qiangxue

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 avatar May 30 '14 14:05 creocoder

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"
        }
    }
}

creocoder avatar May 30 '14 14:05 creocoder

+1

xterr avatar Mar 11 '15 19:03 xterr

+1

bogdaniy avatar Apr 27 '15 18:04 bogdaniy

+1

jcvalerio avatar Apr 27 '15 19:04 jcvalerio

+1

eberon avatar May 23 '15 03:05 eberon

+1

akaNightmare avatar May 27 '15 12:05 akaNightmare

+1

kadanin avatar Jun 04 '15 08:06 kadanin

+1

juanagu avatar Jun 24 '15 17:06 juanagu

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

kadanin avatar Jun 25 '15 06:06 kadanin

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

cebe avatar Jun 25 '15 21:06 cebe

+1

riyaskp avatar Aug 03 '15 16:08 riyaskp

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 avatar Aug 24 '15 16:08 One-art

+1

jasonhancock avatar Aug 26 '15 00:08 jasonhancock

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.

ebuzzz avatar Aug 31 '15 14:08 ebuzzz

+1

mushahidh avatar Aug 31 '15 16:08 mushahidh

+1

supr-d avatar Sep 19 '15 21:09 supr-d

+1

tendallas avatar Oct 01 '15 12:10 tendallas

+1

jacksumit avatar Oct 25 '15 22:10 jacksumit

+1

pgarriga avatar Nov 25 '15 09:11 pgarriga

+1

manquer avatar Nov 27 '15 16:11 manquer

+1

Tr9 avatar Dec 01 '15 09:12 Tr9

+1

Forin avatar Dec 01 '15 12:12 Forin

+1

archlemon avatar Dec 01 '15 12:12 archlemon

+1

Faryshta avatar Dec 01 '15 14:12 Faryshta

+1

pedromalta avatar Dec 18 '15 20:12 pedromalta

+1

nancoder avatar Dec 22 '15 06:12 nancoder