Добавление потомков в многоуровневый ассоциативный массив по ссылке

У меня есть набор записей из MySQL, который возвращает идентификаторы категорий и их значения для заданных объектов. Например:

+-----------+-------------+----------------+
| object_id | category_id | category_value |
+-----------+-------------+----------------+
|         1 |           2 | VEGETARIAN     |
|         1 |           3 | MATARÓ         |
|         1 |           5 | MARCO POLO     |
|         1 |           5 | JOHN DOE       |
|         2 |           2 | VEGETARIAN     |
|         2 |           3 | MATARÓ         |
|         2 |           5 | JOHN DOE       |
+-----------+-------------+----------------+

Имея это, мне понадобится следующий результирующий ассоциативный массив в PHP:

// They are arrays, so more than one object_id can be in the same category tree (and the object_id can be repeated across categories)

$final_array['VEGETARIAN']['MATARÓ']['MARCO POLO'] = array(1);
$final_array['VEGETARIAN']['MATARÓ']['JOHN DOE'] = array(1, 2);

Запрос сначала упорядочивает результаты object_id а затем, по category_id с установленным пользователем порядком. Итак, это было бы как ORDER BY object_id ASC, FIELD(category_id, usercat1, usercat2, usercat3) (который в этом случае будет FIELD(category_id, 2, 3, 5),

У меня есть цикл, который проходит каждый набор, и я пытаюсь сохранить временную переменную для хранения уровней массива, потому что они могут изменяться (не всегда будет 3 уровня), так что-то вроде:

$temporary_array['VEGETARIAN'] = array();
$temporary_array = $temporary_array['VEGETARIAN'];

// And then, on the next iteration
$temporary_array['MATARÓ'] = array();
$temporary_array = $temporary_array['MATARÓ'];
// Now, $temporary_array would be equal to $temporary_array['VEGETARIAN']['MATARÓ'];

Таким образом, я могу создать главный ключ на основе новый значение категории, которое будет храниться как дочерний элемент родительского массива и получать все иерархическое дерево. Каждый уровень должен включать в себя все следующие.

Я пытался объявить это глобально и передать по ссылке, но, похоже, это не работает.

Есть ли способ добиться этого в PHP? Как бы вы сделали, чтобы получить желаемый результат?

РЕДАКТИРОВАТЬ:

Я был ближе к тому, чтобы изменить порядок категорий в обратном порядке, поэтому сначала я получаю последнюю категорию (ту, в которой нет других категорий) и иду вверх по массиву, что-то вроде этого:

// Long story very short, would be like
$final_array['new_category_value'] = $old_final_array;

И продолжай идти за каждым предметом. Когда я меняю object_idтогда я сделаю:

array_merge_recursive($final_array, $actual_object_array);

Однако я до сих пор не могу получить желаемый результат.

Спасибо за ваше время и комментарии!

0

Решение

Предполагая, что вы можете обращаться к своим данным SQL как к ассоциативному массиву, и что значение «1» — это object_id (вместо «true / false 0/1 и т. Д.»), Что-то вроде этого:

$sth = $dbh->prepare("SELECT ......"); //Your SQL Here
$sth->execute();
$rows = $sth->fetchAll(PDO::FETCH_ASSOC);

Строки $ должны содержать что-то вроде этого:

$rows = array(
array(
"object_id" => 1,
"category_id" => 2,
"category_value" => "VEGETARIAN"),
array(
"object_id" => 1,
"category_id" => 3,
"category_value" => "MATARÓ"),
array(
"object_id" => 1,
"category_id" => 5,
"category_value" => "MARCO POLO"),
array(
"object_id" => 1,
"category_id" => 5,
"category_value" => "JOHN DOE")
);

С этого момента вы можете перебирать строки. То, что происходит с отдельной строкой, зависит от строки перед ней, поэтому сохраните и обновите переменную, содержащую ее, чтобы к ней можно было получить доступ в этом цикле

//Define your final array
$final_array = array();

//Store a reference to the last row in order to get the last category checked
$lastRow=null;

//Store reference to the last potential parent
$lastParent=&$final_array;

//Store a reference to the last entry - either an array or the object id
$lastEntry = null;//Loop over all returned rows
foreach($rows as $row) {

//If first time around loop, $lastRow will be null
//If $lastRow is not null, but matches this row's category_id, we should add to the same parent
if($lastRow===null || $lastRow['category_id']===$row['category_id']){

$lastParent[$row['category_value']] = $row['object_id'];

$lastEntry = &$lastParent[$row['category_value']];

//Note - Do not change last parent here
}

//lastCategoryId does not match this row's category ID and is not null, we must change the
//  last entry to be an array and add this entry to it.
else {
$lastParent = &$lastEntry;

$lastParent = array($row['category_value'] => $row['object_id']);

$lastEntry = &$lastParent[$row['category_value']];
}//Loop complete, update the last row
$lastRow=$row;
}

Теперь вы можете проверить звонок print_r($final_array); который возвращает:

Array
(
[VEGETARIAN] => Array
(
[MATARÓ] => Array
(
[MARCO POLO] => 1
[JOHN DOE] => 1
)

)

)
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]