Diskuze: Vytvoření stromu kategorií z XML
V předchozím kvízu, Online test znalostí PHP, jsme si ověřili nabyté zkušenosti z kurzu.


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.
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_file 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_file. 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é.
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.
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
Zobrazeno 5 zpráv z 5.