Slim 框架无法使用受保护变量编码为 json

Slim framework unable to encode to json with protected variables

基本上我是用 json 对响应进行编码,但无法弄清楚为什么它一直返回正确数量的数组成员,但它们是空的。

 $app->get('/api/server_list', function ($request, $response, $args) {
 $serverlist = new ServerListing($this->db);
 $servers = $serverlist->getServers();
 $newResponse = $response->withJson($servers);
 return $newResponse;    
 });

这是上面添加的 print_r($servers)

的输出
[{},{}]Array
(
    [0] => ServerEntity Object
        (
            [id:protected] => 1
            [serverName:protected] => dc1.domain.com
        )

    [1] => ServerEntity Object
        (
            [id:protected] => 2
            [serverName:protected] => dc2.domain.com
        )

)

这是 ServerListing 的 class 代码:

 <?php

class ServerListing extends Listing
{
    public function getServers() {
        $sql = "SELECT * from servers";
        $stmt = $this->db->query($sql);

        $results = [];

        while($row = $stmt->fetch()) {
            $results[] = new ServerEntity($row);
        }
        return $results;
    }
}

这是服务器实体:

 <?php

 class ServerEntity
 {
     public $id;
     public $serverName;

     public function __construct(array $data) {

         if(isset($data['id'])) {
             $this->id = $data['id'];
          }

         $this->serverName = $data['name'];
     }

         public function getId() {
             return $this->id;
     }
         public function getServerName() {
             return $this->serverName;
     }

 }

唯一有效的方法是 public。

我明白了public/private/protected。虽然这是我第一次使用框架和面向对象 php。

在另一条路线中使用相同的数据库调用,然后我可以将服务器列表传递给视图并且它工作正常。

所以我猜两个问题。

  1. 为什么 json 编码失败?
  2. 我是不是做错了什么/有更好的方法吗?

简而言之,对象可以转化为数组。

对象的 public 属性将用作数组中的 $key => $value 对。

由于属性受到保护,因此不包括这些值。

虽然数组实际上为空似乎合乎逻辑,但 PHP 将对象转换为数组的过程并没有得到充分的记录。

实际上,我建议您创建一个 public 方法,将对象转换为数组。

class ServerEntity {
 //...
    public function toArray() {
         return array("id" => $this->id, "name" => $this->name);
    }
 //...
}

那么你可以简单地做...

$app->get('/api/server_list', function ($request, $response, $args) {
    $serverlist = new ServerListing($this->db);
    $servers = $serverlist->getServers();
    $objects = array();

    foreach ($servers as $server) {
        $objects[] = $server->toArray();
    }

    $newResponse = $response->withJson($objects);
    return $newResponse;    
});

Slim 的Response::withJson() doesn't do anything magic. It relies on the PHP function json_encode() 进行编码。 json_encode()也不知道有什么绝招。如果您将一个对象传递给它进行编码,它会获得它可以从中获得的所有数据。这仅意味着它的 public 属性,因为,这就是 OOP 的工作方式。

但是,如果您在 class 中实现 JsonSerializable 接口,那么在编码 class 的对象时,您可以控制 json_encode() 可用的数据=].

例如:

class ServerEntity implements JsonSerializable
{
    private $id;
    private $serverName;

    // ... your existing code here

    public function jsonSerialize()
    {
        return array(
            'id'   => $this->id,
            'name' => $this->serverName,
        );
    }
}

一些测试代码:

echo(json_encode(new ServerEntity(array('id' => 7, 'name' => 'foo'))));

输出为:

{"id":7,"name":"foo"}