Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.
Avatar
Martin Suchodol:7.7.2021 21:13

Ahoj, potřebuji vytvořit strom kategorií z XML souboru. Jenoduché zadání, ale nějak se nedaří.Po zpracování a ořezání dat o nežádoucí prvky z xml souboru dostanu zhruba takovýto výsledek.

Array
(
    [Id] => 37671
    [IdP] => -2147483647
    [Name] => G21
)
Array
(
    [Id] => 49663
    [IdP] => 37671
    [Name] => Archiv
)
Array
(
    [Id] => 64899
    [IdP] => 37671
    [Name] => Auto-moto
)
Array
(
    [Id] => 64868
    [IdP] => 64899
    [Name] => Autochladničky
)
Array
(
    [Id] => 64876
    [IdP] => 64868
    [Name] => Kompresorové autochladničky
)
//...

Do této chvíle je vše v pořádku, ale následně potřebuji. Data zpracovat tak aby se zobrazovala ve stromu. Kdy mi nic standartního nefunguje. Jen pro pořádek uvedu že takto zpracovávám XML prvně, a obecně s XML moc nepracuji.

XML zpracovávám takto:

foreach ($xml2->SPresentTree as $p) {
    $productCategoryTree = [];
    foreach ($p as $categoryItemKey => $categoryItemValue) {
        $productCategoryTree[$categoryItemKey] = (string)$categoryItemValue;
    }
    $array = array_except($productCategoryTree, ['StoItem', 'ImgSize', 'Sort']);
}

Pro zpracování dat do stromu jsem zkoušel různá řešení, včetně zdejšího na zpracování stromového menu, strom . Samozřejmě s patřičnými úpravami, aby funkce odpovídala datové struktuře pole s kategoriemi

 
Odpovědět
7.7.2021 21:13
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:11.7.2021 10:09

Vzdyt browser, kdyz mu posles xml, tak ho zobrazi stromove. Takze, jestli to jen chces prohlizet, tak klidne pouzij to xml.

Jinak, ten dotaz nelze zodpovedet. Proto na nej nikdo nereaguje.
Je tu jakysi vystup, ktery ovsem netusime, v jake je promenne. Je tu jakysi kod. A jaky je asi vstup?
Zkus sem dat jednoduchy uplny php kod, treba pro 5 takovych kategorii, ktery bude mit vse, vstup, php kod a zobrazi se mi nejaky vystup, treba pres

echo '<pre>'; var_dump($out);

Jestli je nejaky mezikrok to pole, co jsi nam ukazal, pak jako by mozna za zminku stalo, ze...

-  u cislovane array je key cislo 0, 1, 2, 3... nikoliv $value[id]
 foreach ($p as $categoryItemKey => $categoryItemValue) {
$productCategoryTree[$categoryItemKey] = (string)$categoryItemValue;

- ze nektera idp mas -2147483647
$productCategoryTree[$categoryItemKey] = (string)$categoryItemValue;

- array_except neni platna funkce, nikdo netusi, co asi dela
https://www.php.net/manual-lookup.php?pattern=array_except&scope=quickref

Jinymi slovy, vubec netusim, co ten tvuj kod vlastne dela nebo by mel delat.
Kdyz delas stromove menu, mel bys asi vyuzivat rekurzi.
A je tedy jeste otazkou, v jakem poradi dostanes data z db. Protoze, bys to mel mit serazene podle levelu zanoreni a serazene podle toho, jak chces v poradi seradit vice polozek.

id, idp, text
1,0 auta
2,0 nabytek
3,0 hracky
4,3 -kolotoc
A ted snadno vytvoris pole hlavnich kategorii, protoze level idp=0 mas prvni. Do hracek pak muzes dat kolotoc, protoze hracky budou existovat.

1,0 auta
2,0 nabytek
4,3 -kolotoc // v tomto pripade to selze, id=3 neexistuje
3,0 hracky // ta vznikne az v dalsim radku

.... a soucasne mas urcene, ze se zobrazi hlavni kategorie v poradi
auto, nabytek, hracky, pokud pri zobrazeni nepouzijes treba serazeni podle abecedy

Z toho pole, co jsi tam dal, budes muset proste prohledavat kazdou vetev a hledat, zda ma prislusne id.
A nebo, si generujes pomocne pole

array(
id => $pointer_array
)

$pointer_array je odkaz na strukturu v array

$list = Array(
Array(
    'Id' => 64899
    'IdP' => 37671,
    'Name' => Auto-moto,
),
Array
(
    'Id' => 64868
    'IdP' => 64899
    'Name' => Autochladničky
)
);
$out = array();
$pom = array();

// cyklus...
list( $ip, $idP ) = $value;
if (isExist($pom[ $idP ]))
    $pom[ $idP ][ $id ] = array();
    $pom[ $id ] = $pom[ $idP ][ $id ]; // to by melo pridat pointer na array
else
    $out[ $id ] = array();
    $pom[ $id ] = $out[ $id ]; // to by melo pridat pointer na array

Tady by mozna bylo dobre, kdybys vedel s jistotou, ktere z nich jsou kategorie a ktere uz konecne produkty, protoze tohle ti vytvori i pro kazde zbozi prazdnou array do pom. Ale to nevadi, protoze pom stejne nepouzijes. Jen, kdybys chtel usport pamet.
Ja bych to mozna cele poslal prohlizeci, javascriptu, at si to generuje. Tim preneses vykon ze serveru ven.
Na druhou stranu, ty si to muzes ulozit cele jako array do php souboru a tim padem to nemusis znova a znova generovat podle xml.

 
Nahoru Odpovědět
11.7.2021 10:09
Avatar
Martin Suchodol:12.7.2021 11:39

Takže jedná se o zdrojový feed, ze kterého se do eshopu načtou produkty, s kategorií se pak sestavuje řetězec něco jako:
Kategorie > podkategorie >podkategorie podkategorie > atd. Normálně jsou kategorie součástí hlavního feedu, ale tady je to jiné. Tady mají kategorie svůj vlastní feed. který musím zpracovat do požadované podoby.

Surový feed, zpracovaný čistě jen pomocí simplexml_load_fi­le vypadá takto .

Funcke array_except, jen ořezá pole o nepotřebné parametry:

function array_except($array, $keys) {
    foreach ($keys as $key) {
        unset($array[$key]);
    }
    return $array;
}

Cyklus který jsem již postoval v prvním příspěvku, jen zpracuje pole do podoby kterou jsem už také ukazoval. Tedy:
Z tohoto

Array
        (
            [0] => SimpleXMLElement Object
                (
                    [Id] => -2147483647
                    [Sort] => 001
                    [Name] => Dle výrobce
                    [StoItem] => SimpleXMLElement Object
                        (
                        )

                )

udělá toto

Array
(
    [Id] => -2147483647
    [Name] => Dle výrobce
)
Array
(
    [Id] => 37671
    [IdP] => -2147483647
    [Name] => G21
)
Array
(
    [Id] => 49663
    [IdP] => 37671
    [Name] => Archiv
)

To že je některé IdP záporné je v pořádku, to seskupuje kategorie které zastupuje určitého výrobce.

Rekurzi jsem samozrejme zkousel používat, včetně různých řešení nalezených na internetu. Do rekurze jsem pouštěl jak pole zpracované tím mým cyklem, tak neupravené načtené pomocí simplexml_load_fi­le. A vždy bez výsledku. Už mě opravdu nenapadá co dál zkusit, mimo uložení dat do databáze, ale to je v tomto případě zbytečné.

 
Nahoru Odpovědět
12.7.2021 11:39
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:12.7.2021 13:24

Co ti na to rici? Tenhle kod, zadny, proste nemuzu spoustet, testovat. A psat celej kod asi nechci :) Tak snad poradi nekdo jiny.
Nebo, jakym zpusobem bys postupoval ty, kdybys mel na svuj dotaz reagovat? Musel bys cely kod sestavit od zacatku, nejlepe i s parsovanim. To by mohlo zabrat i hodinu misto soustredeni se na opravu par radku.

No, ale, abys nerek, tak zprovoznim tu cast kodu, co sem psal...

<?php
$list = array(
array(
    'Id' => 64899,
    'IdP' => 37671,
    'Name' => "Auto-moto"
),
array
(
    'Id' => 64868,
    'IdP' => 64899,
    'Name' => "Autochladničky"
),
array
(
    'Id' => 64876,
    'IdP' => 64868,
    'Name' => "Kompresorové autochladničky"
)
);

$out = array();
$pom = array();

echo '<pre>';

foreach($list as $row)
{
//var_dump($row);
list( $id, $idP ) = array($row['Id'], $row['IdP']);
//var_dump( $id, $idP );
if (isset($pom[ $idP ]))
        {
        $pom[ $idP ][ $id ] = array();
        $pom[ $id ] = &$pom[ $idP ][ $id ];
        }
else    {
        $out[ $id ] = array();
        $pom[ $id ] = &$out[ $id ];
        }
}

var_dump($out);
?>

C:\xampp\htdocs\www\parse-category\parse-category-from-array.php:43:
array (size=1)
  64899 =>
    array (size=1)
      64868 =>
        array (size=1)
          64876 =>
            array (size=0)
              ...

Stejne si ale myslim, ze, co chces, by slo jednoduseji generovat primo z toho xml. Navic jsi nerek, ze ti jde o category_path, ale chtel jsi strom. Viz ten muj kod, vytvori strom.

Editováno 12.7.2021 13:26
 
Nahoru Odpovědět
12.7.2021 13:24
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:12.7.2021 15:20

Vlastne, muzes udelat jeste par uprav, kdyz teda chces z toho tu path...

<?php
$list = array(
array(
    'Id' => 64899,
    'IdP' => 37671,
    'Name' => "Auto-moto"
),
array
(
    'Id' => 64868,
    'IdP' => 64899,
    'Name' => "Autochladničky"
),
array
(
    'Id' => 64876,
    'IdP' => 64868,
    'Name' => "Kompresorové autochladničky"
)
);

$out = array();
$pom = array();

echo '<pre>';

foreach($list as $row)
{
//var_dump($row);
list( $id, $idP, $name ) = array($row['Id'], $row['IdP'], $row['Name']);//zde
//var_dump( $id, $idP );
if (isset($pom[ $idP ]))
        {
        $pom[ $idP ][ $id ] = array( 'IdP'=>$idP, 'Name'=>$name );//zde
        $pom[ $id ] = &$pom[ $idP ][ $id ];
        }
else    {
        $out[ $id ] = array( 'IdP'=>$idP, 'Name'=>$name );//zde
        $pom[ $id ] = &$out[ $id ];
        }
}

var_dump($out);
// $pom[ $idP ][ $id ] = array($idP, $name); slo by pouzit jen toto, ale nevim, zda 0 a 1 nemas jako kategorii
// $pom[ $idP ][ $id ] = $row; // nebo dat tam primo cely row
// $pom[ $idP ][ $id ] = &$row; // nebo dat tam primo cely row jako pointer
// totez u else

foreach($list as $row)
{
$path = array();
$id = $row['Id'];
for (;isset($pom[$id]);)
        {
        $path[] = $pom[$id]['Name'];
        $id = $pom[$id]['IdP'];
        }
echo implode(" > ", array_reverse($path))."\n";
}
?>


C:\xampp\htdocs\www\parse-category\parse-category-from-array.php:43:
array (size=1)
  64899 =>
    array (size=3)
      'IdP' => int 37671
      'Name' => string 'Auto-moto' (length=9)
      64868 =>
        array (size=3)
          'IdP' => int 64899
          'Name' => string 'Autochladničky' (length=15)
          64876 =>
            array (size=2)
              ...

Auto-moto
Auto-moto > Autochladničky
Auto-moto > Autochladničky > Kompresorové autochladničky
 
Nahoru Odpovědět
12.7.2021 15:20
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 5 zpráv z 5.