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

AR refresh() with relations

Open yurii-github opened this issue 7 years ago • 4 comments

What steps will reproduce the problem?

$video = Video::find()->andWhere(['id' => $videoId])
->with(['videoType',  'videoThumbnails'])
->one();

// DATA IS GOOD
$videoArray = $video->toArray([], ['videoType', 'videoThumbnails']);

// do some video manipulations

// now refresh video object
$video->refresh();

// NO RELATIONS!
$videoArray = $video->toArray([], ['videoType', 'videoThumbnails']);

//WORKAROUND
$video->videoType;
$video->vdeoThumbnails;

// DATA IS GOOD NOW
$videoArray = $video->toArray([], ['videoType', 'videoThumbnails']);

What is the expected result?

repopulate existing/fetched relations

What do you get instead?

nothing

Additional info

| ---------------- | --- | Yii version | 2.0.13

yurii-github avatar Jan 16 '18 10:01 yurii-github

I think the issue is in #15522

vladis84 avatar Feb 03 '18 07:02 vladis84

Yes. Looks like so.

samdark avatar Feb 03 '18 13:02 samdark

@samdark Shouldn't we have tests for this? I don't see how this is related to #15522.

rob006 avatar Feb 03 '18 22:02 rob006

it is not related

my point is currently all relations get unset on refresh at BaseActiveRecord.php

    protected function refreshInternal($record)
    {
        if ($record === null) {
            return false;
        }
        foreach ($this->attributes() as $name) {
            $this->_attributes[$name] = isset($record->_attributes[$name]) ? $record->_attributes[$name] : null;
        }
        $this->_oldAttributes = $record->_oldAttributes;
        $this->_related = [];  // <--- RESET HERE
        $this->afterRefresh(); 

        return true;
    }

Currently I don't see any easy solution for this usecase because information about relations (from active query) is not passed to active record, so repopulate relations with proper conditions looks impossible. I mean, basic relations potentially can be repopulated, but custom not, like

$video = Video::find()->andWhere(['id' => $videoId])
->with(['videoType' => function($q) { .... }])
->one();

Maybe you should ignore my issue and just make some kind of warning. Currently , in whole project I have only 2 places with such workaround.

regards

yurii-github avatar Feb 04 '18 10:02 yurii-github