#json #yii #yii-relations
#json #yii #yii-отношения
Вопрос:
Как я могу вернуть объект со всеми отношениями (отношения между вложенными объектами ans?). Теперь я использую EJsonBehavior, но он возвращает только отношения первого уровня, а не вложенные связанные объекты. Мой исходный код:
$order = Order::model()->findByPk($_GET['id']);
echo $order->toJSON();
Yii::app()->end();
Ответ №1:
Подход с быстрой загрузкой извлекает связанные экземпляры AR вместе с основными экземплярами AR. Это достигается с помощью метода with() вместе с одним из методов find или findAll в AR. Например,
$posts=Post::model()->with('author')->findAll();
Приведенный выше код вернет массив экземпляров Post. В отличие от ленивого подхода, свойство author в каждом экземпляре Post уже заполнено соответствующим экземпляром User, прежде чем мы получим доступ к свойству. Вместо выполнения запроса объединения для каждой записи, подход с быстрой загрузкой возвращает все записи вместе с их авторами в одном запросе объединения!
Мы можем указать несколько имен отношений в методе with (), и подход с быстрой загрузкой вернет их все одним выстрелом. Например, следующий код вернет сообщения вместе с их авторами и категориями:
$posts=Post::model()->with('author','categories')->findAll();
Мы также можем выполнять вложенную быструю загрузку. Вместо списка имен отношений мы передаем иерархическое представление имен отношений методу with(), например, следующему,
$posts=Post::model()->with(
'author.profile',
'author.posts',
'categories')->findAll();
Приведенный выше пример вернет все сообщения вместе с их автором и категориями. Это также вернет профиль каждого автора и публикации.
Быстрая загрузка также может быть выполнена путем указания свойства CDbCriteria::with, например, следующим образом:
$criteria=new CDbCriteria;
$criteria->with=array(
'author.profile',
'author.posts',
'categories',
);
$posts=Post::model()->findAll($criteria);
или
$posts=Post::model()->findAll(array(
'with'=>array(
'author.profile',
'author.posts',
'categories',
)
);
Комментарии:
1. Код этого ответа не возвращает правильный ответ, как только вы печатаете результаты в формате json, отношения не отображаются.
Ответ №2:
Я нашел решение для этого. вы можете использовать $row-> attributes для создания данных
$magazines = Magazines::model()->with('articles')->findAll();
$arr = array();
$i = 0;
foreach($magazines as $mag)
{
$arr[$i] = $mag->attributes;
$arr[$i]['articles']=array();
$j=0;
foreach($mag->articles as $article){
$arr[$i]['articles'][$j]=$article->attributes;
$j ;
}
$i ;
}
print CJSON::encode(array(
'code' => 1001,
'magazines' => $arr,
));
Ответ №3:
Это лучший фрагмент кода, который я нашел после долгих поисков, отвечающий этому требованию. Это будет работать как шарм.
protected function renderJson($o) {
//header('Content-type: application/json');
// if it's an array, call getAttributesDeep for each record
if (is_array($o)) {
$data = array();
foreach ($o as $record) {
array_push($data, $this->getAttributes($record));
}
echo CJSON::encode($data);
} else {
// otherwise just do it on the passed-in object
echo CJSON::encode($this->getAttributes($o));
}
// this just prevents any other Yii code from being output
foreach (Yii::app()->log->routes as $route) {
if ($route instanceof CWebLogRoute) {
$route->enabled = false; // disable any weblogroutes
}
}
Yii::app()->end();
}
protected function getAttributes($o) {
// get the attributes and relations
$data = $o->attributes;
$relations = $o->relations();
foreach (array_keys($relations) as $r) {
// for each relation, if it has the data and it isn't nul/
if ($o->hasRelated($r) amp;amp; $o->getRelated($r) != null) {
// add this to the attributes structure, recursively calling
// this function to get any of the child's relations
$data[$r] = $this->getAttributes($o->getRelated($r));
}
}
return $data;
}