Задать вопрос
@kolomat

Получения полного древа категорий из yml?

Добрый день, поскажите по такому вопросу. Есть стандартный yml файл, в нем древо категорий
<categories>
<category id="119604754" parentId="112971624">Блокноты</category>
<category id="112971624">Бумажные изделия</category>
<category id="112971626">Канцелярские товары</category>
<category id="112971625">Папки и файлы</category>
<category id="112971627">Товары для школы и творчества</category>
<category id="112971629">Детские книги и развитие</category>
<category id="112971630">Офисные товары</category>
<category id="112971631" parentId="112971624">Бумага для принтера</category>
<category id="112971632" parentId="112971624">Бумага для принтера цветная</category>
<category id="112971636" parentId="112971624">Бумага для заметок</category>
<category id="112971633" parentId="112971624">Специальная бумага</category>
<category id="112971634" parentId="112971624">Этикетки и ценники</category>
<category id="112971635" parentId="112971624">Ежедневники</category>
<category id="112971637" parentId="112971624">Конверты</category>
<category id="112971638" parentId="112971625">Папки на кнопке</category>
<category id="112971644" parentId="112971625">Папки-уголки</category>
<category id="112971645" parentId="112971625">Папки-регистраторы</category>
<category id="112971649" parentId="112971626">Клей</category>
<category id="112971647" parentId="112971625">Файлы</category>
<category id="112971646" parentId="112971625">Папки с зажимом</category>
<category id="112971648" parentId="112971626">Бейджи</category>
<category id="112971650" parentId="112971626">Скотч</category>
<category id="112971655" parentId="112971626">Стаканы и подставки для ручек</category>
<category id="112971654" parentId="112971626">Лотки для бумаг</category>


Хотел создать для google merchanta xml в котором бы у оффера был указан полный путь категорий
Например
<category id="119604754" parentId="112971624">Блокноты</category>
<category id="112971624">Бумажные изделия</category>


Что бы получилось так например
<item>
        <g:id>2023198597</g:id>
        <g:product_type>Бумажные изделия > Блокноты </g:product_type>
    </item>


Пробовал сделать вот так
foreach ($price->shop->categories->category as $category) {
    if (!$category->attributes()->parentId) {
        $categories[] = [
            'id' => (string)$category['id'],
            'name' => (string)$category
        ];
    } else {
        $pCategories[] = [
            'id' => (string)$category['parentId'],
            'name' => (string)$category
        ];
    }
}

$xml = new DomDocument('1.0', 'UTF-8');
$items = $xml->appendChild($xml->createElement('channel'));

foreach ($price->shop->offers->offer as $offer) {
    $categoryId = $offer->categoryId;
    $item = $items->appendChild($xml->createElement('item'));

    $id = $item->appendChild($xml->createElement('g:id'));
    $id->appendChild($xml->createTextNode($offer->attributes()->id));
    $category = $item->appendChild($xml->createElement('g:product_type'));

    array_filter($categories, function ($a) use ($pCategories, $categoryId, $category, $xml) {
        foreach ($pCategories as $pCategory) {
                if ($pCategory['id'] == $categoryId) {
                    return $category->appendChild($xml->createTextNode($a['name'] . '>' . $pCategory['name']));
                }
            }
    });
}


Внутри если распечатать $a['name'] . '>' . $pCategory['name'] там все верно, но в самом xml почему то сохраняеться для одного офера все древо категорий. Не подскажите что не верно или возможно есть более правильный способ реализовать это. Буду рад за любую помощь.
  • Вопрос задан
  • 122 просмотра
Подписаться 1 Простой 1 комментарий
Помогут разобраться в теме Все курсы
  • Skillfactory
    Профессия Fullstack веб-разработчик на JavaScript и PHP
    20 месяцев
    Далее
  • Хекслет
    PHP-разработчик
    10 месяцев
    Далее
  • Нетология
    Веб-разработчик с нуля: профессия с выбором специализации
    14 месяцев
    Далее
Решения вопроса 1
Набросал пару функций
/**
 * @param array<int, array> $categories
 */
function getCategoryPath(int $categoryId, array $categories): string|null
{
    $category = $categories[$categoryId] ?? null;

    if ($category === null) {
        return null;
    }

    $categoryName     = $category['name'];
    $categoryParentId = $category['parent_id'];

    if ($categoryParentId) {
        return getCategoryPath($categoryParentId, $categories) . ' > ' . $categoryName;
    } else {
        return $categoryName;
    }
}

/**
 * @param array<array> $array
 * @return array<mixed, array>
 */
function indexArrayByColumn(array $array, string $column): array
{
    return array_combine(array_column($array, $column), $array);
}


Пример использования:
$categories = [
    ['id' => 1,  'parent_id' => null, 'name' => 'Электроника'],
    ['id' => 2,  'parent_id' => 1,    'name' => 'Ноутюуки'],
    ['id' => 3,  'parent_id' => 2,    'name' => 'Apple'],
    ['id' => 4,  'parent_id' => 2,    'name' => 'Acer'],
    ['id' => 5,  'parent_id' => 2,    'name' => 'HP'],
    ['id' => 6,  'parent_id' => 2,    'name' => 'Dell'],
    ['id' => 7,  'parent_id' => 1,    'name' => 'Холодильники'],
    ['id' => 8,  'parent_id' => 1,    'name' => 'Телевизоры'],
    ['id' => 9,  'parent_id' => null, 'name' => 'Одежка'],
    ['id' => 10, 'parent_id' => 9,    'name' => 'Куртки'],
    ['id' => 11, 'parent_id' => 9,    'name' => 'Штаны'],
    ['id' => 12, 'parent_id' => null, 'name' => 'Игрушки'],
];

// Индексируем массив по полю 'id'
$categories = indexArrayByColumn($categories, 'id');

foreach ($categories as $categoryId => $_) {
    echo getCategoryPath($categoryId, $categories);
    echo PHP_EOL;
}


Результат:
php categories/script.php
Электроника
Электроника > Ноутюуки
Электроника > Ноутюуки > Apple
Электроника > Ноутюуки > Acer
Электроника > Ноутюуки > HP
Электроника > Ноутюуки > Dell
Электроника > Холодильники
Электроника > Телевизоры
Одежка
Одежка > Куртки
Одежка > Штаны
Игрушки


У этого кода преимущество в том, что путь будет корректно строиться при любой вложенности категорий
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы
FoodSoul Калининград
от 180 000 до 250 000 ₽
IT-Spirit Москва
от 230 000 до 320 000 ₽
от 200 000 до 290 000 ₽