Yii2 Active Record JSON响应,类型转换问题

cvxl0en2  于 2022-11-09  发布在  其他
关注(0)|答案(3)|浏览(135)

我在Yii 2中遇到了一个奇怪的问题,我有一个查询,它与代理表有一个连接,并且作业与任务有一个(一对多)关系,它工作正常,但问题是它返回的所有内容都是字符串。

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

和JSON编码的结果:

{
  "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",

    },
  ]
}

如果你注意到像id,customer_id和job_id这样的字段,它们都是整数,但是它返回的是字符串。但是如果我从上面的查询中删除-〉asArray(),它返回的是有效的类型转换,但是问题是它跳过了关系和leftJoin代理表字段,它只返回job表字段。这里是从上面的查询中删除-〉asArray()后的响应。

{
"success": true,
"data": [

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

如果您注意到上面的响应中没有完全跳过代理表first_name、last_name和关系数据任务,但id和customer_id为整数。
有没有人遇到过同样的问题?你的帮助将是非常感谢。提前感谢。

s71maibg

s71maibg1#

我想确认一下这是不是真的。我自己也用类似的查询进行了测试,结果也很相似:

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

在我的例子中,所有类型都是字符串,所以,如果你要用if ($data[0]['id'] === 1)来检查输入和它的类型,你会得到false的结果,因为它是string .
但是你需要做的是在variable前面加上(int),把它转换成不同的类型转换。(int) $data[0]['id'] .
那么var_dump((int) $data[0]['id']);(在我的例子中)将给予int(1)而不是string(1) "1"
您也可以签入条件式:

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

如果不将(int)作为前缀写入,则将得到Not integer结果,而将其作为前缀写入将得到Integer结果。
如果您不想在每个函数中一直写入这些前缀,则可以写入如下内容:

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

现在,$data[0]['id']在将来的使用中将变为integer

新解决方案:

这个新的解决方案将返回一个包含数组的对象,而不仅仅是数组。

// 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;
}

在Controller中,您(和往常一样)传递此对象:

$data = User::getData();

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

然后,在Viewer中,您可以访问如下所示的值(类型转换正确):

$data->query['columnName'];

因此,对于ID检查:

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

您将收到响应ok(类型转换:整数,值:10页)。

0pizxfdo

0pizxfdo2#

这是预期的行为,也记录在文件中:

**注意:**虽然此方法可以节省内存并提高性能,但它更接近较低的DB抽象层,因此您将丢失大多数活动记录功能。列值的数据类型有一个非常重要的区别。当您在活动记录示例中返回数据时,列值将根据实际的列类型自动转换类型;另一方面,当您返回数组中的数据时,列值将是字符串(因为它们是PDO的结果,没有经过任何处理),而不管它们的实际列类型。

对于第二个问题,要检索活动记录类中的附加字段,必须在类中为它们创建附加属性:

class MyRecord extends \yii\db\ActiveRecord
{
    public $first_name;
    public $last_name;

    // ...
}
bwleehnv

bwleehnv3#

方法“asArray”会将所有变量的类型转换为字符串。因此,不应使用此方法。
您可以在文档中找到正确的解决方案:https://www.yiiframework.com/doc/guide/2.0/en/rest-resources#overriding-extra-fields
对于API请求,您需要在URI中使用“fields”和“expand”参数。
例如:http://localhost/posts?fields=id,title&expand=author
首先将关系添加到模型中:

/**
     * @return \yii\db\ActiveQuery
     */
    public function getAuthor()
    {
        return $this->hasOne(Profile::class, ['id' => 'author_id']);
    }

您还需要向模型添加字段和extraFields方法:

public function fields()
    {
        return ['id', 'title'];
    }

    public function extraFields()
    {
        return ['author'];
    }

并更改响应:

public function actionIndex()
{
    return new ActiveDataProvider([
        'query' => Post::find(),
    ]);
}

P.S.很抱歉necroposting,但我最近也有同样的问题

相关问题