Yii2 Active record JSON response, type casting problem

I ran into a strange problem in Yii2. I have a query in which there is one connection to the table of operators and the relation (from one to many) of tasks with the task, it works fine, but the problem is that it returns everything in the string. The following is the request:

$query = self::find() ->select("job.*, agent.first_name,agent.last_name") ->leftJoin('agent', 'job.agent_id = agent.id') ->with('tasks') ->asArray() ->all(); 

and JSON encoded result:

 { "success": true, "data": [ { "id": "10", "customer_id": "1", "job_type": "normal", "created": "2016-06-22 10:19:25", "first_name": "Shayan", "last_name": "", "tasks": [ { "id": "10", "job_id": "10", "title": "bring food", "instruction": null, "created": "2016-06-22 10:19:25", }, { "id": "10", "job_id": "10", "title": "bring pizza", "instruction": null, "created": "2016-06-22 10:19:25", }, ] } 

if you notice fields like id, customer_id and job_id, they are all integers, but they are returned as a string. But if I delete β†’ asArray () from the above query, it returns a valid casting type, but the problem is that it skips the relational and leftJoin fields of the agent table, it returns only the fields of the task table, here is the answer after deleting β†’ asArray () from request above.

 { "success": true, "data": [ { "id": 10, "customer_id": 1, "name": null, "job_type": "normal", "created": "2016-06-22 10:19:25", }, 

If you notice in the answer above, it has no tables of first_name, last_name statements and relational data tasks that are completely skipped, and id and customer_id are integers.

Has anyone encountered the same problem? Your help would be greatly appreciated. Thanks in advance.

+6
source share
2 answers

I wanted to make sure that this is true. I myself tested this with a very similar query, and my results are very similar:

 array(2) { [0]=> array(5) { ["id"]=> string(1) "1" ["name"]=> string(5) "Admin" // ... } // ... } 

In my case, I also get all types as strings. So, if you want to check the input and type with if ($data[0]['id'] === 1) , you will get the result false , since it is string .

But you need to add (int) before the variable in order to convert it to another type. It will be: (int) $data[0]['id'] .

Then var_dump((int) $data[0]['id']); (in my case) will give int(1) instead of string(1) "1" .

You can also check the legend:

 ((int) $data[0]['id'] === 1) ? exit('Integer') : exit('Not integer'); 

Without a record (int) prefix will give the result Not integer , and with the prefix, Integer .

If you do not want to write these prefixes in each function, you can write something like:

 $data[0]['id'] = (int) $data[0]['id']; 

And now $data[0]['id'] will be an Integer for future purposes.


New solution:

This new solution will return an object with arrays instead of arrays.

 // Method that gives data back. In this case, user with ID == 10. public static function getData() { $dataProvider = new ActiveDataProvider([ 'query' => self::findOne(['id' => 10])->attributes ]); return $dataProvider; } 

In the controller, you (as always) pass this object:

 $data = User::getData(); return $this->render('user', [ //... 'data' => $data ]); 

And then in Viewer you can access the values ​​(in the correct type) as follows:

 $data->query['columnName']; 

So, to verify the identifier:

 ($data->query['id'] === 10 ? exit('ok') : exit('nok')); 

You will get the answer ok (typecast: integer, value: 10).

+12
source

This is the expected behavior, and is also documented :

Note. . Although this method saves memory and improves performance, it is closer to the lower level of database abstraction, and you will lose most of the functions of Active Record. A very important difference is the data type of the column values. When you return data in Active Record instances, the column values ​​will automatically typecast according to the actual column types; on the other hand, when you return data to arrays, the column values ​​will be strings (since they are the result of a PDO without any processing), regardless of their actual column types.

For the second problem, in order to get additional fields in the active record class, you need to create additional properties for them in the class:

 class MyRecord extends \yii\db\ActiveRecord { public $first_name; public $last_name; // ... } 
+7
source

All Articles