Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

\yii\db\BaseActiveRecord::getDirtyAttributes causes Fatal Error in 2.0.46 #19544

Closed
r-simlinger opened this issue Sep 6, 2022 · 9 comments
Closed
Labels
Milestone

Comments

@r-simlinger
Copy link

r-simlinger commented Sep 6, 2022

Since the version 2.0.46 we are getting a fatal error, if we want to update data in a complex mongo collection and where we are using Yii models for the ActiveRecord class attributes to validate some additional stuff.

What steps will reproduce the problem?

<?php

use core\FunctionalTester;
use yii\base\Behavior;
use yii\base\Model;
use yii\mongodb\ActiveRecord;

/**
 * Test for bug in Yii version 2.0.46:
 *  yii\base\ErrorException: Nesting level too deep - recursive dependency? in /vendor/yiisoft/yii2/helpers/BaseArrayHelper.php
 */
class UpdateBugCest
{
    /**
     * @param FunctionalTester $I
     * @return void
     */
    public function testGetDirtyAttributes(FunctionalTester $I)
    {
        $data = [
            'basket' => [
                0 => [
                    'name' => 'Item 1',
                    'group' => [
                        0 => new GroupModel([
                            'id' => '3',
                        ])
                    ],
                ],
                1 => [
                    'name' => 'Item 2',
                    'group' => [
                        0 => new GroupModel([
                            'id' => '3',
                        ])
                    ],
                ],
            ],
        ];

        // simulate the loading of some existing data from db
        $db_model = new BasketModel();
        $db_model->setOldAttribute('basket', []);

        // update model with new data
        $db_model->setAttributes($data);

        // start the test -> will result in an ErrorException in version 2.0.46, but worked before
        $db_model->getDirtyAttributes();

        // test passed
        $I->assertTrue(true);
    }
}

/**
 * @property array $basket
 */
class BasketModel extends ActiveRecord
{
    public function rules(): array
    {
        return [
            ['basket', 'save'],
        ];
    }

    /**
     * {@inheritdoc}
     */
    public function attributes()
    {
        return ['basket'];
    }
}

class GroupModel extends Model
{
    public int $id = 0;

    public function rules(): array
    {
        return [
            [['id'], 'integer'],
        ];
    }


    /**
     * @param array $config
     */
    public function __construct($config = [])
    {
        // call default constructor
        parent::__construct($config);

        // attach behavior
        $this->attachBehaviors([
            'logger_or_similar' => [
                'class' => Behavior::class,   // !!! this is important to reproduce the error !!!
            ],
        ]);
    }
}

What is the expected result?

A working test.

What do you get instead?

FATAL ERROR. TESTS NOT FINISHED.
Nesting level too deep - recursive dependency?
in .../vendor/yiisoft/yii2/helpers/BaseArrayHelper.php:1031
yii\base\ErrorException 'yii\base\ErrorException' with message 'Nesting level too deep - recursive dependency?'

Additional info

Q A
Yii version 2.0.46
PHP version 7.4
Operating system Linux
@samdark
Copy link
Member

samdark commented Sep 7, 2022

Could it be reproduced with non-mongo AR?

@samdark
Copy link
Member

samdark commented Sep 7, 2022

Does it work with 2.0.45?

@r-simlinger
Copy link
Author

yeah with 2.0.45 it's working.

It's also not directly related to mongo (because it's also called in the updateAttributes of the BaseActiveRecord class, in this case a \yii\base\Model class).
It's more when you have an object which behaves like an array (using the interfaces and so on). Somehow this call_user_func_array is then going into a loop.

@samdark samdark added the type:bug Bug label Sep 8, 2022
@samdark samdark added this to the 2.0.47 milestone Sep 8, 2022
@samdark
Copy link
Member

samdark commented Sep 8, 2022

Do you have some time to help with a reproducible test-case we can use to debug/fix it?

@r-simlinger
Copy link
Author

r-simlinger commented Sep 8, 2022

Maybe it's more clear if you add this to the test from above:

        $model = new GroupModel();
        $I->assertEquals(['id'], $model->attributes());
        $I->assertEquals(['id' => 0], $model->toArray()); // works
        $I->assertEquals(['id' => 0], (array)$model); // fails, more fields then needed to pass it then to the call_user_func_array().

will output:

 Fail  Failed asserting that two arrays are equal.
- Expected | + Actual
@@ @@
Array (
+    'id' => 0
+    Binary String: 0x007969695c626173655c4d6f64656c005f6572726f7273 => null
+    Binary String: 0x007969695c626173655c4d6f64656c005f76616c696461746f7273 => null
+    Binary String: 0x007969695c626173655c4d6f64656c005f7363656e6172696f => 'default'
+    Binary String: 0x007969695c626173655c436f6d706f6e656e74005f6576656e7473 => Array ()
+    Binary String: 0x007969695c626173655c436f6d706f6e656e74005f6576656e7457696c646361726473 => Array ()
+    Binary String: 0x007969695c626173655c436f6d706f6e656e74005f6265686176696f7273 => Array (...)
)

Scenario Steps:
 3. $I->assertEquals([],{"id":0,"\u0000yii\\base\\Model\u0000_errors":null,"\u0000yii\\base\\Model\u0000_validators":null,"\u0000yii\\base\\Model\u0000_scenario":"default","\u0000yii\\base\\Component\u0000_events":[],"\u0000yii\\base\\Component\u0000_eventWildcards":[],"\u0000yii\\base\\Component\u0000_behavior...})

@r-simlinger
Copy link
Author

Maybe it's only needed to modify the getDirtyAttributes() in the \yii\mongodb\ActiveRecord class so that it will use the toArray() method, like for the insert into the mongodb.
But I will test it (later) also with some other BaseActiveRecord class...

@lubosdz
Copy link
Contributor

lubosdz commented Sep 11, 2022

Perhaps related to #19546 ?

@schmunk42
Copy link
Contributor

also related #19531

@samdark
Copy link
Member

samdark commented Nov 15, 2022

Should be already fixed in master.

@samdark samdark closed this as completed Nov 15, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants