Fórum Root.cz
Hlavní témata => Vývoj => Téma založeno: Honza 01. 01. 2018, 20:22:32
-
Ahoj, může někdo poradit jak vypsat z takového pole
$array = [] ;
$array["aaa"] = ["url"=>"aaa", "name"=>"AAA"];
$array["bbb"] = ["url"=>"bbb", "name"=>"BBB"];
$array["ccc"] = ["url"=>"ccc", "name"=>"CCC"];
$array["ccc"]["ddd"] = ["url"=>"ddd", "name"=>"DDD"];
$array["ccc"]["ddd"]["eee"] = ["url"=>"eee", "name"=>"EEE"];
$array["fff"] = ["url"=>"fff", "name"=>"FFF"];
$array["ggg"] = ["url"=>"ggg", "name"=>"GGG"];
takový html výsledek ?
<ul>
<li><a href="aaa">AAA</a></li>
<li><a href="bbb">BBB</a></li>
<li><a href="ccc">CCC</a>
<ul>
<li><a href="ccc/ddd">DDD</a>
<ul>
<li><a href="ccc/ddd/eee">EEE</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="fff">FFF</a></li>
<li><a href="ggg">GGG</a></li>
</ul>
Zatím mám takový kód ale ten nedokáže vypsat vnořené url.
private function makeList($array)
{
if(is_array($array))
{
$pridej_ul = false;
$output = '';
$url = '';
foreach($array as $key => $subArray)
{
if(isset($subArray ["url"]))
{
$pridej_ul = true;
$output .= '<li>';
$output .= '<a href="'.$subArray["url"].'">'.$subArray["name"].'</a>';
$output .= $this -> makeList ( $subArray );
$output .= '</li>';
}
else
{
$output .= $this -> makeList($subArray);
}
}
if ($pridej_ul)
{
$output = '<ul>'.$output.'</ul>';
}
}
else
{
$output = '';
}
return $output;
}
Díky za pomoc.
-
Možná nějak takkhle...
function render(array $array) {
$expected = ['url', 'name'];
echo '<ul>';
foreach ($array as $item) {
echo sprintf('<li><a href="%s">%s</a></li>', $item['url'], $item['name']);
if (count($item) > 2) {
$nested = array_filter(
$item,
function ($key) use ($expected) {
return !in_array($key, $expected) ? $key : false;
},
ARRAY_FILTER_USE_KEY
);
render($nested);
}
}
echo '</ul>';
}
render($array);
-
Díky, ale taky ti to nevypisuje správně ty url...
-
Nějak tak?
$render = function($element, $key, $path) {
if (isset($element['name'] && isset['url'])) {
sprintf("<li><a href='%s'>%s</a> ", explode("/", $path), $element['name']);
} else {
sprintf("<ul>");
array_walk($element, __function__, array_merge($path, array($key));
sprintf("</ul>");
}
};
array_walk($array, $render, array());
-
Zamysli se nad tím, co tohle udělá:
$array["ccc"] = ["url"=>"ccc", "name"=>"CCC"];
$array["ccc"]["ddd"] = ["url"=>"ddd", "name"=>"DDD"];
$array["ccc"]["ddd"]["eee"] = ["url"=>"eee", "name"=>"EEE"];
S tím se prostě blbě pracuje.
A zapomněl jsi uvést, že definice toho pole právě takhle není daná a můžeš si ho definovat jakkoliv jinak. Tak ho prostě definuj nějak "normálně".
-
A po odladění takto:
function render($element, $key, $path) {
$path = array_merge($path, array($key));
echo "<li>";
if (isset($element['name']) && isset($element['url'])) {
echo sprintf("<a href='%s'>%s</a>", implode("/", $path), $element['name']);
unset($element['name']);
unset($element['url']);
}
if ($element) {
echo "<ul>";
array_walk($element, 'render', $path);
echo "</ul>";
}
echo "</li>";
};
echo "<ul>";
array_walk($array, 'render', array());
echo "</ul>";
-
A po refaktorování takto:
function render_element($element, $key, $path) {
echo "<li>";
$path = array_merge($path, array($key));
if (isset($element['name']) && isset($element['url'])) {
echo sprintf("<a href='%s'>%s</a>", implode("/", $path), $element['name']);
unset($element['name']);
unset($element['url']);
}
render($element, $path);
echo "</li>";
};
function render($array, $path=array()) {
if ($array) {
echo "<ul>";
array_walk($array, 'render_element', $path);
echo "</ul>";
}
}
render($array);
-
Díky, ale taky ti to nevypisuje správně ty url...
Rád bych řekl, že sem ti nastřelil jen část, aby ses nad tím kódem zamyslel a zkusil to dořešit sám. Pravda je taková, že sem to prostě přehlédl a že ty data jsou uložený retardovaně tak se mi zase nechtělo tím pálit svůj čas. Ale řešení už tu od Ivana máš :-)
-
@Ivan Nový
Velmi děkuji za tvůj čas, jdu to zkusit nějak nastudovat. Musí tam prosím ty klíče být, nebo by to šlo i bez nich?
Myslím takto:
$array = [] ;
$array[] = ["url"=>"aaa", "name"=>"AAA"];
$array[] = ["url"=>"bbb", "name"=>"BBB"];
$array[] = ["url"=>"ccc", "name"=>"CCC"];
$array[][] = ["url"=>"ddd", "name"=>"DDD"];
$array[][][] = ["url"=>"eee", "name"=>"EEE"];
$array[] = ["url"=>"fff", "name"=>"FFF"];
$array[] = ["url"=>"ggg", "name"=>"GGG"];
-
Nemusí :D
-
Nemusí :D
musí, jinak se vám ztratí ty cesty. Naopak tam nemusí být ty koncové name a url.
-
List alá Python, nebo Lisp
array(
array('aaa', null),
array('bbb', null)
array('ccc',
array('ddd',
array('eee', null))),
array('fff', null),
array('ggg', null),
);
-
Pak z elementu se dá vyextrahovat, pouze naznačeno
$suburl = reset($element);
$name = strtoupper(reset($element));
if (end($element)) array_walk(end($element), 'render_element', $path);
-
@Ivan Nový
Moc děkuji, tak jsem to zkusil opravit ale nevypíše se vůbec nic :(
Takto to teď celé mám
$array = [] ;
$array[] = ["url"=>"aaa", "name"=>"AAA"];
$array[] = ["url"=>"bbb", "name"=>"BBB"];
$array[] = ["url"=>"ccc", "name"=>"CCC"];
$array[][] = ["url"=>"ddd", "name"=>"DDD"];
$array[][][] = ["url"=>"eee", "name"=>"EEE"];
$array[] = ["url"=>"fff", "name"=>"FFF"];
$array[] = ["url"=>"ggg", "name"=>"GGG"];
function render_element($element, $key, $path) {
echo "<li>";
$path = array_merge($path, array($key));
if (isset($element['name']) && isset($element['url'])) {
echo sprintf("<a href='%s'>%s</a>", implode("/", $path), $element['name']);
unset($element['name']);
unset($element['url']);
}
render($element, $path);
echo "</li>";
}
function render($array, $path=array()) {
if ($array) {
echo "<ul>";
//array_walk($array, 'render_element', $path);
$suburl = reset($element);
$name = strtoupper(reset($element));
if (end($element)) array_walk(end($element), 'render_element', $path);
echo "</ul>";
}
}
render($array);
-
@Ivan Nový
Moc děkuji, tak jsem to zkusil opravit ale nevypíše se vůbec nic :(
Takto to teď celé mám
$array = [] ;
$array[] = ["url"=>"aaa", "name"=>"AAA"];
$array[] = ["url"=>"bbb", "name"=>"BBB"];
$array[] = ["url"=>"ccc", "name"=>"CCC"];
$array[][] = ["url"=>"ddd", "name"=>"DDD"];
$array[][][] = ["url"=>"eee", "name"=>"EEE"];
$array[] = ["url"=>"fff", "name"=>"FFF"];
$array[] = ["url"=>"ggg", "name"=>"GGG"];
function render_element($element, $key, $path) {
echo "<li>";
$path = array_merge($path, array($key));
if (isset($element['name']) && isset($element['url'])) {
echo sprintf("<a href='%s'>%s</a>", implode("/", $path), $element['name']);
unset($element['name']);
unset($element['url']);
}
render($element, $path);
echo "</li>";
}
function render($array, $path=array()) {
if ($array) {
echo "<ul>";
//array_walk($array, 'render_element', $path);
$suburl = reset($element);
$name = strtoupper(reset($element));
if (end($element)) array_walk(end($element), 'render_element', $path);
echo "</ul>";
}
}
render($array);
No to byly jen příklady jak přistupovat k prvkům těch elementů, řádky logicky spolu nesouvisely. Nedá se to takto přímočaře použít. Zkuste více porozumět tomu co to dělá. Podívejte se do dokumentace, co použité funkce dělají. Jinak to vaše původní pole nakonec nebylo tak krkolomné, jak se zdálo, viz z toho vzniklý refaktorovaný algoritmus, který je relativně kompaktní. V algoritmu byla použita nepřímá rekurze.
-
@Ivan Nový
Aha, tak to já nedám ani omylem, jsem "jen" grafik, ne programátor :( v php znám jen pár primitivních funkcí které používám pro statický web. Tohle jsem chtěl abych nemusel při každé změně přepisovat tuny nepřehledného html kódu.
V každém případě moc děkuji a třeba se někdo slituje a doplní to ;)
-
to řešení funguje jen s tou původní reprezentací.
Ta vaše reprezentace
$array = [] ;
$array[] = ["url"=>"aaa", "name"=>"AAA"];
$array[] = ["url"=>"bbb", "name"=>"BBB"];
$array[] = ["url"=>"ccc", "name"=>"CCC"];
$array[][] = ["url"=>"ddd", "name"=>"DDD"];
$array[][][] = ["url"=>"eee", "name"=>"EEE"];
$array[] = ["url"=>"fff", "name"=>"FFF"];
$array[] = ["url"=>"ggg", "name"=>"GGG"];
není moc snadno použitelná. Když si ji vytisknete jako JSON dostanete
[
{
"url": "aaa",
"name": "AAA"
},
{
"url": "bbb",
"name": "BBB"
},
{
"url": "ccc",
"name": "CCC"
},
[
{
"url": "ddd",
"name": "DDD"
}
],
[
[
{
"url": "eee",
"name": "EEE"
}
]
],
{
"url": "fff",
"name": "FFF"
},
{
"url": "ggg",
"name": "GGG"
}
]
-
Tak použijte ten původní tvar vašeho pole s indexy. Struktura toho pole bude pro vás srozumitelnější a pravděpodobně jen to pole bude plnit hodnotami, které potřebujete. A tento kód, to by mělo fungovat.
$array = [] ;
$array["aaa"] = ["url"=>"aaa", "name"=>"AAA"];
$array["bbb"] = ["url"=>"bbb", "name"=>"BBB"];
$array["ccc"] = ["url"=>"ccc", "name"=>"CCC"];
$array["ccc"]["ddd"] = ["url"=>"ddd", "name"=>"DDD"];
$array["ccc"]["ddd"]["eee"] = ["url"=>"eee", "name"=>"EEE"];
$array["fff"] = ["url"=>"fff", "name"=>"FFF"];
$array["ggg"] = ["url"=>"ggg", "name"=>"GGG"];
function render_element($element, $key, $path) {
echo "<li>";
// Konstrukce aktuální cesty
$path = array_merge($path, array($key));
// Pokud element obsahuje name a url, vypíše se element <a>
if (isset($element['name']) && isset($element['url'])) {
echo sprintf("<a href='%s'>%s</a>", implode("/", $path), $element['name']);
unset($element['name']);
unset($element['url']);
}
// Vykreslení elementu <ul>
render($element, $path);
echo "</li>";
};
// Vykreslení pole ohraničeného elementem <ul>
function render($array, $path=array()) {
if ($array) {
echo "<ul>";
array_walk($array, 'render_element', $path);
echo "</ul>";
}
}
render($array);
-
Nemusí :D
musí, jinak se vám ztratí ty cesty. Naopak tam nemusí být ty koncové name a url.
oprava, nemsí, ale bude to zbytečně komplikované.
-
@Ivan Nový
OK, a proč mi to prosím nefunguje, nahradil jsem echo za $ret abych mohl vypsat data přesně tam kde potřebuji. Vypíše se ale pouze číslo 1 :)
$array = [] ;
$array["aaa"] = ["url"=>"aaa", "name"=>"AAA"];
$array["bbb"] = ["url"=>"bbb", "name"=>"BBB"];
$array["ccc"] = ["url"=>"ccc", "name"=>"CCC"];
$array["ccc"]["ddd"] = ["url"=>"ddd", "name"=>"DDD"];
$array["ccc"]["ddd"]["eee"] = ["url"=>"eee", "name"=>"EEE"];
$array["ccc"]["ddd"]["eee"]["eee2"] = ["url"=>"eee2", "name"=>"EEE2"];
$array["fff"] = ["url"=>"fff", "name"=>"FFF"];
$array["ggg"] = ["url"=>"ggg", "name"=>"GGG"];
function render_element($element, $key, $path) {
$ret = '';
$ret .= "<li>";
$path = array_merge($path, array($key));
if (isset($element['name']) && isset($element['url'])) {
$ret .= '<a href="'.implode("/", $path).'">'.$element['name'].'</a>';
unset($element['name']);
unset($element['url']);
}
$ret .= render($element, $path);
$ret .= "</li>";
return $ret ;
}
function render($array, $path=array()) {
$ret = '';
if ($array) {
$ret .= "<ul>";
$ret .= array_walk($array, 'render_element', $path);
$ret .= "</ul>";
}
return $ret ;
}
$con = render($array);
echo $con ;
-
@mmm
nevím co je to json ale co tedy takto? Bude to lepší?
$array = [] ;
$array["aaa"] = ["AAA"];
$array["bbb"] = ["BBB"];
$array["ccc"] = ["CCC"];
$array["ccc"]["ddd"] = ["DDD"];
$array["ccc"]["ddd"]["eee"] = ["EEE"];
$array["fff"] = ["FFF"];
$array["ggg"] = ["GGG"];
Nechci tady vysírat, jelikož jsem vážně rád, že se mi tady někdo snaží pomoci, ale jde o to, že tam budou stovky odkazů, tak ať je to pole co nejmenší..
-
Stovky odkazů jsou v pohodě.
-
Zde je upravený a funkční kód http://sandbox.onlinephpfunctions.com/code/954f2d8bdac768cfd2de82e72992abdaeba9cfbf
Je to sandbox, lze ho tam i spustit.
-
Nechci tady vysírat, jelikož jsem vážně rád, že se mi tady někdo snaží pomoci, ale jde o to, že tam budou stovky odkazů, tak ať je to pole co nejmenší..
napadla mě taková reprezentace
$array = ["aaa", "bbb", ["ccc", [["ddd", ["eee"]]]], "fff", "ggg"];
celé řešení s použitím vnořeného generátoru včetně odsazení
$array = ["aaa", "bbb", ["ccc", [["ddd", ["eee"]]]], "fff", "ggg"];
function a($path, $text) {
$spath = join('/', array_merge($path, [$text]));
return "<a href=\"$spath\">".strtoupper($text)."</a>";
}
function ul($array, $path=[]){
$indent = str_repeat(" ", count($path));
yield "$indent<ul>";
foreach($array as $content){
if(is_array($content)){
list($content, $ul) = $content;
yield "$indent <li>".a($path, $content);
yield from ul($ul, array_merge($path, [$content]));
yield "$indent </li>";
}else{
yield "$indent <li>".a($path, $content)."</li>";
}
}
yield "$indent</ul>";
}
function render($array){
foreach(ul($array) as $line) {
echo "$line\n";
}
}
render($array);
-
@mmm
To je pěkné, ale není-li tazatel programátor, bude se mu ručně lépe vyplňovat to pole, jak si ho sám navrhl a nebude záležet na pořadí v jakém tam ty linky bude sázet, může to pohodlněji rozšiřovat, nemusí dodržovat žádnou strukturu mezi řádky, jen strukturu v rámci řádku.
-
@mmm
To je pěkné, ale není-li tazatel programátor, bude se mu ručně lépe vyplňovat to pole, jak si ho sám navrhl a nebude záležet na pořadí v jakém tam ty linky bude sázet, může to pohodlněji rozšiřovat, nemusí dodržovat žádnou strukturu mezi řádky, jen strukturu v rámci řádku.
chtěl minimální velikost. Vaše reprezentace obsahuje redundantní informaci a překlep ji znevalidní.
-
@mmm
jj, vaše řešení je vážně pěkné.
-
...
Php (mimo jiny) umi nativne XML a interne je to reprezentovany jako pole. A defakto cely (a libovolne strukturovany) pole vysypes do X/Html jednim radkem.
Tuhle mas nejakej sampl https://stackoverflow.com/questions/1397036/how-to-convert-array-to-simplexml. Samosebou to umi i mnohem slozitejsi konstrukty a muzes (pokud bys chtel) pouzivat XSL.
Jen bacha na to, ze phpko ma dva ruzny enginy, ten simple je fakt simple a moc toho neumi => musis prizpusobit strukturu tomu co umi.
-
Zde je upravený a funkční kód http://sandbox.onlinephpfunctions.com/code/954f2d8bdac768cfd2de82e72992abdaeba9cfbf
Je to sandbox, lze ho tam i spustit.
Funguje to parádně, velmi moc děkuji. Ten výpis je opravdu možný pouze pomocí ob_start()... ? Prozradíš mi prosím proč to nefunguje, tak jak jsem to dosadil do těch proměnných?
-
@ Honza
Bylo to jednodušší řešení v daném případě, navíc možná i efektivnější co do zdrojů, protože zpracování řetězců probíhá na nižší úrovni jazyka v C. Prostě se jen výstup přesměruje do bufferu a nic není třeba měnit, obejde se práce s řetezci v PHP, jejich skládání a alokace paměti.
-
@ Honza
Nefunguje to proto, že funkce array_walk nevrací výsledek, ale pravdivostní hodnotu, která určuje zda zpracování proběhlo bez chyby, pokud funkce aplikovaná na pole pomocí array_walk vrátí false po detekci chyby, vrátí false i funkce array_walk. Ta funkce, která se vkládá do array_walk se volá pro každý prvek pole znovu.
-
Díky za objasnění..
Zkusil jsem napsat vlastní funkci z mých velmi omezených znalostí z PHP až na jediný špatný odkaz (u FFF) všechno funguje správně :) Možná je to blbost, ale nemůžu zjistit proč tomu tak je.
$array = [] ;
$array["aaa"] = ["AAA"];
$array["bbb"] = ["BBB"];
$array["ccc"] = ["CCC"];
$array["ccc"]["ddd"] = ["DDD"];
$array["ccc"]["ddd"]["eee"] = ["EEE"];
$array["ccc"]["ddd"]["eee"]["eee2"] = ["EEE2"];
$array["fff"] = ["FFF"];
$array["ggg"] = ["GGG"];
$array["hhh"] = ["HHH"];
$array["hhh"]["iii"] = ["III"];
function render2($data , $path=''){
$return = "<ul>";
foreach ($data as $key => $element){
if(is_array($data[$key])){
$return .= "<li>";
$path = $path . '/' . $key ;
$return .= '<a href="'.$path.'">'.$element[0].'</a>';
$return .= "</li>";
if(count(array_keys($data[$key]))==2){
$return .= render2($data[$key], $path);
}
else{
$path = '' ;
}
}
}
$return .= "</ul>";
return $return ;
}
echo render2($array) ;
-
To je proto, že cesta není upravena po vynoření se z úrovně zanoření. Upravený algoritmus zde http://sandbox.onlinephpfunctions.com/code/95e82581e6945576feaf342c8da788fd211962af
-
Vaše funkce ale nebude fungovat, když se do dat přidá:
$array["ccc"]["xxx"]["eee"]["eee2"] = ["EEE2"];
-
Upravený a zjednodušený algoritmus, můj http://sandbox.onlinephpfunctions.com/code/1865f13bcde5dc834d0fdeaea82e3dd12f136bc2
-
Upravený a zjednodušený algoritmus, můj http://sandbox.onlinephpfunctions.com/code/1865f13bcde5dc834d0fdeaea82e3dd12f136bc2
Ještě se chybka vloudila, nakonec správně takto http://sandbox.onlinephpfunctions.com/code/6d58192b208d0f6dda5024af0c0bfa60631ee5ba
-
Vaše funkce ale nebude fungovat, když se do dat přidá:$array["ccc"]["xxx"]["eee"]["eee2"] = ["EEE2"];
A víte proč? Je to tím, že je ta funkce celá špatně?
-
Ještě se chybka vloudila, nakonec správně takto http://sandbox.onlinephpfunctions.com/code/6d58192b208d0f6dda5024af0c0bfa60631ee5ba
Se dívám, že to taky nefunguje správně.
-
Díky za objasnění..
Zkusil jsem napsat vlastní funkci z mých velmi omezených znalostí z PHP až na jediný špatný odkaz (u FFF) všechno funguje správně :) Možná je to blbost, ale nemůžu zjistit proč tomu tak je.
$array = [] ;
$array["aaa"] = ["AAA"];
$array["bbb"] = ["BBB"];
$array["ccc"] = ["CCC"];
$array["ccc"]["ddd"] = ["DDD"];
$array["ccc"]["ddd"]["eee"] = ["EEE"];
$array["ccc"]["ddd"]["eee"]["eee2"] = ["EEE2"];
$array["fff"] = ["FFF"];
$array["ggg"] = ["GGG"];
$array["hhh"] = ["HHH"];
$array["hhh"]["iii"] = ["III"];
function render2($data , $path=''){
$return = "<ul>";
foreach ($data as $key => $element){
if(is_array($data[$key])){
$return .= "<li>";
$path = $path . '/' . $key ;
$return .= '<a href="'.$path.'">'.$element[0].'</a>';
$return .= "</li>";
if(count(array_keys($data[$key]))==2){
$return .= render2($data[$key], $path);
}
else{
$path = '' ;
}
}
}
$return .= "</ul>";
return $return ;
}
echo render2($array) ;
v tom řešení je víc věcí špatně. Uzavíráte li před začítkem ul, ale ve vzorovém html je ul uvnitř li. $path nulujete až po výpisu odkazu, proto vám to u FFF nefunguje. Nebude to fungovat v případě, kdy má jeden prvek více než jednoho potomka, ale to možná nepotřebujete.
-
Ještě se chybka vloudila, nakonec správně takto http://sandbox.onlinephpfunctions.com/code/6d58192b208d0f6dda5024af0c0bfa60631ee5ba
Se dívám, že to taky nefunguje správně.
je tam malá chybka. V odkazech chybí poslední část cesty. Zkuste tohle.
function render_element($element, $key, $path) {
echo "<li>";
$path = array_merge($path, [$key]);
if (isset($element[0])) {
echo '<a href="'.implode("/", $path).'">'.$element[0].'</a>';
unset($element[0]);
}
render($element, $path);
echo "</li>";
}