2016-08-09 1 views
3

В основном я кодировал ответ с помощью json и не мог понять, почему он продолжал возвращать правильное количество элементов массива, но они были пустыми.Slim framework не может кодировать 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 ($ серверы)

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

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

) 

Вот класс код ServerListing:

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

Здесь ServerEntity:

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

} 

Только так оно и есть орки с публикой.

Я понимаю общественность/частный/защищенный. Хотя это мой первый раз с фреймворком и объектно-ориентированным php.

Используя тот же вызов базы данных на другом маршруте, я могу передать список серверов в представление, и он отлично работает.

Так что, я думаю, два вопроса.

  1. Почему ошибка json не выполняется?
  2. Я делаю что-то принципиально неправильное/есть ли лучший способ сделать это?

ответ

5

Слима Response::withJson() ничего магического не делать. Для выполнения кодировки он использует функцию PHP json_encode(). json_encode() также не знает никаких специальных трюков. Если вы передаете ему объект для кодирования, он получает все данные, которые он может получить от него. И это означает только его публичные свойства, потому что, как хорошо работает ООП.

Однако, если вы реализуете интерфейс JsonSerializable в классе, тогда вы можете контролировать, какие данные доступны для 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"} 
+0

Хорошо, что имеет смысл. Я действительно не понимал, что происходит за кулисами. Спасибо за объяснение. – TheEditor

1

Короче говоря, объект может быть преобразован в массив.

Публичные свойства объекта будут использоваться как пары $key => $value в массиве.

Поскольку свойства защищены, значения не включены.

Хотя казалось бы логичным, что массив фактически пуст, процесс, в котором PHP преобразует объект в массив, на самом деле недостаточно документирован.

На практике я бы рекомендовал вам создать общедоступный метод, который преобразует объект в массив.

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;  
}); 
+0

Спасибо также. – TheEditor

 Смежные вопросы

  • Нет связанных вопросов^_^