Я использую LARAVEL 4
с MySQL
back-end.
У меня есть таблица с self-referencing
со столбцами id, name, type
и parent
. Здесь parent
является foreign-key
Id
столбца. Данные в таблице приведены ниже:
id name type parent 1 General group NULL 2 What is..? question 1 3 aa answer 2 4 bb answer 2 5 cc answer 2 6 How is..? question 1 7 ba answer 6 8 bb answer 6 9 Where is..? question 4 10 ca answer 9 11 cb answer 9 12 Who is..? question 6 13 da answer 12 14 db answer 12 15 Specific group NULL 16 When is..? question 15 17 ea answer 16 18 eb answer 16 19 Whome is..? question 2 20 fa answer 19 21 fb answer 19 22 fc answer 19
Я хочу функцию, которая возвращает nested JSON
используя эти реляционные данные. Например :
[{ "id" : 1, "name" : "Geneal", "type" : "group", "children" : [{ "id" : 2, "name" : "What is..?", "type" : "question", "children" : [{ "id" : 3, "name" : "aa", "type" : "answer" }, { "id" : 4, "name" : "bb", "type" : "answer" }, { "id" : 5, "name" : "cc", "type" : "answer" }]}, { "id" : 6, "name" : "How is..?", "type" : "question", "children" : [{ "id" : 7, "name" : "ba", "type" : "answer" }, { "id" : 8, "name" : "bb", "type" : "answer" }] }] ... and so on }]
Я создал model
именем Survey
как Survey
ниже:
class Survey extends BaseModel{ protected $table = 'questions'; protected $softDelete = false; public function parent() { return $this->belongsTo('Survey', 'parent'); } public function children() { return $this->hasMany('Survey', 'parent'); } }
и назвал его controller
:
$user = Survey::all(); $parent = $user->parent()->first(); $children = $user->children()->get();
Но я не получаю должного результата, как я уже упоминал в JSON
выше.
print_r($parent->toJson());
дает записи только с одной иерархией уровней (т.е. группа и вопросы, а не ответы).
в то время как
print_r($children ->toJson());
Дает только вопросы (не группы и ответы).
Я хочу, чтобы все данные саморегуляции в вложенном формате JSON с N уровнем иерархии .
Я также попробовал
$user = Survey::with('parent', 'children')->get();
Но нашел то же самое, что и $ parent выше.
В любом случае, я могу получить желаемый результат?
Заранее спасибо..
Вот как вы вручную извлекаете вложенные отношения:
$collection = Model::with('relation1.relation2.relation3')->get();
Поэтому в вашем случае это будет:
$surveys = Survey::with('children.children.children')->get();
Очевидно, что это выполнит эту работу, когда отношения будут фиксированными, но это не путь для рекурсивного отношения к той же таблице.
К счастью, вы можете сделать такое отношение рекурсивным , тогда все, что вам нужно, чтобы получить цельное дерево:
$surveys = Survey::with('childrenRecursive');
Тем не менее, я бы не загружал родителя для каждой строки таким образом.
Вот и все, что вам нужно:
// Survey model // loads only direct children - 1 level public function children() { return $this->hasMany('Survey', 'parent'); } // recursive, loads all descendants public function childrenRecursive() { return $this->children()->with('childrenRecursive'); // which is equivalent to: // return $this->hasMany('Survey', 'parent')->with('childrenRecursive); } // parent public function parent() { return $this->belongsTo('Survey','parent'); } // all ascendants public function parentRecursive() { return $this->parent()->with('parentRecursive'); }
EDIT: для получения реальной древовидной структуры первый запрос должен быть ограничен только корневыми узлами:
$surveys = Survey::with('childrenRecursive')->whereNull('parent')->get();
так просто!!!
вам просто нужно добавить функцию clouser к вашим отношениям следующим образом:
$surveys = Survey::with(['children' => function($q) { $q->with('children'); }, 'parent' => function($q) { $q->with('parent'); });
то вы можете получить доступ к своим вложенным детям в свой результат следующим образом:
$surveys->children
и неограниченное гнездование:
$surveys->children->first()->children
и так далее.