Php 将Yii模型对象转换为JSON时获取垃圾值

Php 将Yii模型对象转换为JSON时获取垃圾值,php,yii,Php,Yii,我有一个扩展CComponent的模型类 class CompanyModel extends CComponent{ private $company_pk; public function getCompany_pk() { return $this->company_pk; } public function setCompany_pk($value) { $this->company_pk =


我有一个扩展CComponent的模型类

    class CompanyModel extends CComponent{ 
    private $company_pk;
    public function getCompany_pk()
   {
        return $this->company_pk;
   }
   public function setCompany_pk($value)    {
        $this->company_pk = $value;
    }
}
我有一个函数来填充这个模态

    public function getCompanyList() {
    $companyList=array();
    $company_obj = new CompanyModel();
    $sql = "SELECT company_pk,name FROM tbl_company WHERE status = ".Constants::ACTIVE_COMPANY;
    $command=$this->connection->createCommand($sql);
    $command->setFetchMode(PDO::FETCH_ASSOC);
    $rows=$command->queryAll();

    foreach ($rows as $row){
        $company_obj->company_pk = $row['company_pk'];
        array_push($companyList,$company_obj);

    }

    return $companyList;
}
还有我的控制器

    Class UserController extends CController {
public  function actionGetCompanyList() {
    $model = new UserAction();
    $ret_val = $model->getCompanyList();
    echo CJSON::encode((array)$ret_val[0]);
         }
     }
我得到的JSON是

{"\u0000CompanyModel\u0000company_pk":"2"}

我怎样才能删除那些垃圾值呢?

我知道你以后无法解码它们,如果你想将
$company\u pk
更改为public,它应该正确编码。问题在于您的对象强制转换到数组,该数组将空字节添加到您的私有成员
$company\u pk
。在
echo CJSON::encode((数组)$ret_val[0])中作为对象数组

你可以做坏事

$json = '{"\u0000CompanyModel\u0000company_pk":"2"}';

$json = str_replace('\u0000', '', $json);

var_dump(json_decode($json));
或者您将对象传递给
CJSON::encode
我不太了解YII,但它应该按照手册处理对象

以下是重现问题的示例:

class test {
 private $private = 1;
 public $publiv = 2;
}

$obj = new test();
$array = (array) $obj;

$json = json_encode($array);

var_dump($json);

var_dump(json_decode($json));
编辑

从手册中:

如果将对象转换为数组,则结果是一个数组,其元素是对象的属性。键是成员变量名,但有几个显著的例外:整数属性不可访问;私有变量的类名在变量名前面;受保护变量的变量名前面有一个“*”。这些带前缀的值两边都有空字节

我从YII快速查看了
CJSON::encode
,您可以直接使用对象,但您的对象必须是可遍历的,所以您必须实现迭代器接口

编辑:2

实现接口可能很棘手,有另一个选项可以从对象内部调用
get\u object\u vars
,在这种情况下,您将获得可以工作的数组

class CompanyModel extends CComponent
{
    private $company_pk;

    public function getCompany_pk()
    {
        return $this->company_pk;
    }
    public function setCompany_pk($value)
    {
        $this->company_pk = $value;
    }

    public function export()
    {
        return get_object_vars($this);
    }
}

然后:

$ret_val = $model->getCompanyList();
echo CJSON::encode($ret_val->export());

问题:为什么它不适用于普通对象,因为YII在内部使用
get\u object\u vars
,并且当它位于不同的作用域时,它无法访问私有属性

我想你以后无法解码它们,如果你想将
$company\u pk
更改为public,它应该正确编码。问题在于您的对象强制转换到数组,该数组将空字节添加到您的私有成员
$company\u pk
。在
echo CJSON::encode((数组)$ret_val[0])中作为对象数组

你可以做坏事

$json = '{"\u0000CompanyModel\u0000company_pk":"2"}';

$json = str_replace('\u0000', '', $json);

var_dump(json_decode($json));
或者您将对象传递给
CJSON::encode
我不太了解YII,但它应该按照手册处理对象

以下是重现问题的示例:

class test {
 private $private = 1;
 public $publiv = 2;
}

$obj = new test();
$array = (array) $obj;

$json = json_encode($array);

var_dump($json);

var_dump(json_decode($json));
编辑

从手册中:

如果将对象转换为数组,则结果是一个数组,其元素是对象的属性。键是成员变量名,但有几个显著的例外:整数属性不可访问;私有变量的类名在变量名前面;受保护变量的变量名前面有一个“*”。这些带前缀的值两边都有空字节

我从YII快速查看了
CJSON::encode
,您可以直接使用对象,但您的对象必须是可遍历的,所以您必须实现迭代器接口

编辑:2

实现接口可能很棘手,有另一个选项可以从对象内部调用
get\u object\u vars
,在这种情况下,您将获得可以工作的数组

class CompanyModel extends CComponent
{
    private $company_pk;

    public function getCompany_pk()
    {
        return $this->company_pk;
    }
    public function setCompany_pk($value)
    {
        $this->company_pk = $value;
    }

    public function export()
    {
        return get_object_vars($this);
    }
}

然后:

$ret_val = $model->getCompanyList();
echo CJSON::encode($ret_val->export());

问题:为什么它不适用于普通对象,因为YII在内部使用
get\u object\u vars
,并且当它位于不同的作用域时,它无法访问私有属性

我发现,如果我在模型类中扩展CModel而不是CComponent,我可以实现我想要的。在扩展此类时,必须重写一个抽象方法。否则它将抛出错误。我的新模型课看起来像这样

   class CompanyModel extends CModel{ 
private $company_pk;
public function attributeNames()
{
    return array( 'company_pk' );
}

public function attributeLabels()
{
    return array( 'company_pk' => 'company_pk Label' );
}
public function getCompany_pk()
   {
    return $this->company_pk;
   }
public function setCompany_pk($value)    {
    $this->company_pk = $value;
}
}

我发现如果我在模型类中扩展CModel而不是CComponent,我就可以实现我想要的。在扩展此类时,必须重写一个抽象方法。否则它将抛出错误。我的新模型课看起来像这样

   class CompanyModel extends CModel{ 
private $company_pk;
public function attributeNames()
{
    return array( 'company_pk' );
}

public function attributeLabels()
{
    return array( 'company_pk' => 'company_pk Label' );
}
public function getCompany_pk()
   {
    return $this->company_pk;
   }
public function setCompany_pk($value)    {
    $this->company_pk = $value;
}
}

这些是unicode字符代码点,而不是垃圾值。这些是unicode字符代码点,而不是垃圾值。如果我不将其输入到数组中,我将无法在JSON输出中获取任何内容。像
CJSON::encode($ret_val[0])
那样,您可以删除private和make in public,或者使用
str_replace
进行清理。当您将包含私有成员的对象强制转换为数组时,将添加空字节。您的意思是模型中的更改吗?你能告诉我它应该是什么样子吗?通过改变
private$company\u pk至<代码>公开$company\u pk。但这不是创建属性的方法,对吗?你知道用Yii创建一个带有属性的模型类的方法吗?如果我不把它输入到数组中,我就不会在JSON输出中得到任何东西。像
CJSON::encode($ret_val[0])
那样,您可以删除private和make in public,或者使用
str_replace
进行清理。当您将包含私有成员的对象强制转换为数组时,将添加空字节。您的意思是模型中的更改吗?你能告诉我它应该是什么样子吗?通过改变
private$company\u pk至<代码>公开$company\u pk。但这不是创建属性的方法,对吗?您知道用Yii创建具有属性的模型类的方法吗?因为CModel实现了IteratorAggregate;)所以基本上我的答案仍然有效。有趣的是,您正在使用
公共函数attributeLabel(){return array('company_pk'=>'company_pk Label');}
与我建议的完全相同,它们只是在内部映射数组中提供的所有属性;)不管怎样,你找到了Yii的方法很好。是的,我已经检查了CModel中的代码,我知道你的答案仍然有效。我试图接受这两个答案,但在这里不起作用;)。我对Yii和PHP还很陌生。因此出现了麻烦:)。我认为属性标签并不重要,重要的是属性名称,因为CModel实现了IteratorAggregate;)所以基本上我的答案仍然有效。你做的事很有趣