yii2: Bug in ActiveQuery (select, joinWith, asArray combination fails)

Hi there,

I found problem with ActiveQuery. I tired query like this:

Order::find()->select(['price', 'firstname', 'lastname'])->joinWith('user')->asArray()->all();

Exception:

exception 'yii\base\ErrorException' with message 'Undefined index: id' in E:\Web\root-users\proj1\vendor\yiisoft\yii2\db\ActiveQuery.php:263
Stack trace:
#0 E:\Web\root-users\proj1\vendor\yiisoft\yii2\db\ActiveQuery.php(263): yii\base\ErrorHandler->handleError(8, 'Undefined index...', 'E:\\Web\\root-use...', 263, Array)
#1 E:\Web\root-users\proj1\vendor\yiisoft\yii2\db\ActiveQuery.php(220): yii\db\ActiveQuery->removeDuplicatedModels(Array)
#2 E:\Web\root-users\proj1\vendor\yiisoft\yii2\db\Query.php(207): yii\db\ActiveQuery->populate(Array)
#3 E:\Web\root-users\proj1\vendor\yiisoft\yii2\db\ActiveQuery.php(130): yii\db\Query->all(NULL)
#4 E:\Web\root-users\proj1\backend\controllers\order\ExportCsvAction.php(38): yii\db\ActiveQuery->all()
#5 [internal function]: backend\controllers\order\ExportCsvAction->run()
#6 E:\Web\root-users\proj1\vendor\yiisoft\yii2\base\Action.php(92): call_user_func_array(Array, Array)
#7 E:\Web\root-users\proj1\vendor\yiisoft\yii2\base\Controller.php(151): yii\base\Action->runWithParams(Array)
#8 E:\Web\root-users\proj1\vendor\yiisoft\yii2\base\Module.php(455): yii\base\Controller->runAction('export-csv', Array)
#9 E:\Web\root-users\proj1\vendor\yiisoft\yii2\web\Application.php(84): yii\base\Module->runAction('order/ex...', Array)
#10 E:\Web\root-users\proj1\vendor\yiisoft\yii2\base\Application.php(375): yii\web\Application->handleRequest(Object(yii\web\Request))
#11 E:\Web\root-users\proj1\backend\web\index.php(18): yii\base\Application->run()
#12 {main}

Version: 2.0.4

About this issue

  • Original URL
  • State: open
  • Created 9 years ago
  • Reactions: 5
  • Comments: 15 (7 by maintainers)

Most upvoted comments

The same thing. There is a workaround:

$result = Order::find()->select(['price', 'firstname', 'lastname'])->joinWith('user')
   ->createCommand()->queryAll();

@Alex-Code it should be done automatically. In select you specify only data what should be outputted not selected from DB. It should be done by ORM.

your gist was enough indeed. It took quite a dive into core code to understand the problem and it does seem a bug. When linking parameters are not loaded into a model at first hand, it would never be possible to access this model attribute at this line: https://github.com/yiisoft/yii2/blob/master/framework/db/ActiveRelationTrait.php#L458

Same thing.

I think the desired behavior is to return only the list of attributes we specified in $query->select(), but automatically additionally select needed attributes for relations specified in joinWith(), which won’t be in the result until they were specified in $query->select()).

@RdeWilde, its undoable to help you debugging. To sum up:

  • an example with ‘rentalType.rentalTypeConnection.objects.objectType’
  • an example about ‘byAmountOfNights’
  • an example about ‘byObjectType’
  • a reference to ‘inverseOf’

You really have to split your issue in the smallest contained environment for us to understand it properly without wasting too much time. Perhabs its better for you to open your own issue.

@mikehaertl code is fine, but code form Yii still have some problems. In every place of application user relation work. But when I added select closure to my query everything stop work as is expected. I know that it can be a black swan for you and no one test it.

If I remove select or joinWith from this query, than it works fine.

Expectations of this functionality are:

  • In output is a two dimensional array (no less no more)
  • First dimension is a list of arrays.
  • Second dimension is a dictionary with keys as column names (prefixed if belong to foreign model), and values only matching to select closure.

Current result:

array(1) {
  array(4) {
    ["price"]=>
    string(9) "23456.78"
    ["firstname"]=>
    string(6) "Test10"
    ["lastname"]=>
    string(6) "Test"
    ["user_id"]=>
    string(1) "4"
    ["user"]=>
    array(12) {
      ["id"]=>
      string(1) "4"
      ["username"]=>
      string(6) "test10"
      ["auth_key"]=>
      string(32) "nWJ_gUFQ4n09X17iXO22dIKh9i9zUqAd"
      ["password_hash"]=>
      string(60) "$2y$13$7LxKbo/MFIHxIetKTnpQYOhjb1z2LkBWc4rOAkGgKSKUhfY4ZlL.S"
      ["password_reset_token"]=>
      NULL
      ["email"]=>
      string(14) "test10@test.pl"
      ["email_confirm_token"]=>
      NULL
      ["firstname"]=>
      string(6) "Test10"
      ["lastname"]=>
      string(4) "Test"
      ["status"]=>
      string(2) "10"
      ["created_at"]=>
      string(10) "1439591224"
      ["updated_at"]=>
      string(10) "1439591257"
    }
  }
}

This pretty clearly indicates an issue in your code. You seem to use user_id somewhere, where it doesn’t belong. Probably in the relation definition of user.