Многострочная функция toJSON с использованием Propel и Backbone

Я пытаюсь сделать то, что должно быть очень простой функцией «список всех», используя Propel ORM - для чтения Backbone.js. Это то, что я хочу сделать и, на мой взгляд, должно работать:

$users = UsersQuery::create()
->find();

echo $users->toJSON();

Однако, когда я запускаю это, я получаю следующие результаты:

{"Users_0":{"Id":1,"EmailAddress":"sdf","Password":"sdf","CreatedAt":null,"ModifiedAt":null},
"Users_1":{"Id":2,"EmailAddress":"dsf","Password":"sdf","CreatedAt":null,"ModifiedAt":null}}

Хотя это действительный JSON, тот факт, что когда-либо строка является массивом в основном массиве, отбрасывает мой JSON. Мне нужно, чтобы он возвращал JSON следующим образом:

[{"Id":1,"EmailAddress":"sdf","Password":"sdf","CreatedAt":null,"ModifiedAt":null},{"Id":2,"EmailAddress":"dsf","Password":"sdf","CreatedAt":null,"ModifiedAt":null}]

Я создал приведенную ниже функцию (в качестве теста), и она отлично работает, но, конечно же, Propel (или Slim, используемая мной структура) может остановить все, что находится внутри массива? Вот хак;

$users = UsersQuery::create()
->find();

$json = '[';
foreach($users as $user){
    $json = $json.$user->exportTo('JSON').',';
}
$json = $json.']';
echo str_replace("},]", "}]", $json);

Любая помощь будет принята с благодарностью! Спасибо всем.


person Daniel Sharp    schedule 08.04.2013    source источник


Ответы (3)


Ненавижу это говорить, но я думаю, что это всего лишь одна из тех ситуаций, когда «Propel работает именно так». Тем не менее, вы можете немного улучшить свою вспомогательную функцию, чтобы она была более надежной.

Я бы поместил этот код в ваш класс UserQuery:

class UsersQuery extends BaseUsersQuery {
  ...

  public function toJSONArray() {
    $users = $this->find();
    $userArray = array();
    foreach($users as $user){
      array_push($userArray, $user->toArray());
    }
    return json_encode($userArray);
  }
}

А потом использовать так...

$userJSON = UsersQuery::create()->toJSONArray();

Или если у вас есть другие критерии...

$userJSON = UsersQuery::create()
              ->filterBySomeField("someValue")
              // other Criteria ...
              ->toJSONArray();
person Jordan Kasper    schedule 08.04.2013
comment
Да, это работает, кроме: array_push($userArray, $user-›toArray()); в противном случае вы получите каждый массив в виде строки... - person Daniel Sharp; 09.04.2013
comment
ак! Спасибо, что поймали это, я исправлю это в ответе. Рад, что это помогло. - person Jordan Kasper; 09.04.2013

есть ли возможное решение для использования этого и фильтра выбора в одном выражении. Что-то вроде этого:

   $ojson = TblproductQuery::create()
        ->select(array('ProdtID', 'DivnID'))
        ->toJsonArray();
person J-H    schedule 26.06.2013

Одна вещь, которую не касается принятый ответ, - это когда у вас есть объект с вложенной коллекцией. Например, может быть, у вас есть куча тестов с такими ответами:

[
  {
    id:test1,
    answers : [
      { id: 1, answer: pig},
      { id: 2, answer: dog}
    ]
  },
  {
    id:test2,
    answers : [
      { id: 5, answer: duck},
      { id: 6, answer: swan}
    ]
  }
]

Вышеприведенное не будет хорошо работать с магистральными коллекциями, когда вы попытаетесь использовать принятый ответ. Это связано с тем, что каждая модель Propel будет вызывать метод PropelCollection::toArray() для любых коллекций Propel внутри себя.

Метод PopelCollection::toArray() будет возвращать себя только как ассоциативный массив в php, который преобразуется в несортированный набор в JSON, а не в массив. Магистральные коллекции сортируются только (массивы).

Чтобы исправить это, я просто изменил метод toArray() в исходном файле propel PropelCollection.php на следующий:

public function toArray(
    $keyColumn = null, 
    $usePrefix = false, 
    $keyType = BasePeer::TYPE_PHPNAME, 
    $includeLazyLoadColumns = true, 
    $alreadyDumpedObjects = array()){

  $ret = array();
  foreach ($this as $key => $obj) {
    array_push($ret, $obj->toArray($keyType, $includeLazyLoadColumns, 
      $alreadyDumpedObjects, true);
  }

  return $ret;
}

Я не видел, как это влияет на методы toXML или toYAML, но позволяет методу toJSON работать так, как я хочу, с вложенными коллекциями, как в моем примере выше.

person MechaMarinara    schedule 19.02.2014