[PHP] Gnezdenje
 
thai 20. jun 2015 10:01:01 Pridružen od:
14. dec 2014
81 objav
32 31 2
#11

theuros:




thai:

Ni nujno, da ima nek meni 100 nivojev, vsaj pri moji skripti ne, če imaš 50 kategorij in ima vsak podkategorijo, se recursive kliče že 50x, ker mora za vsak podmeni pač kreirat nov meni. Sem pa omenil, da bodo rešitev uporabljali uporabniki in pri njih nikoli ne veš. Evo ti primer ene naključne strani... http://cult-trgovina.si/si/. Če imajo to rešeno z recursive, se ta kliče več kot 100x in php bi v tem primeru izpisal error (če bi ostala "default Maximum function nesting level of 100"). Tko da tale "halo?" lahko postane realnost :P




Očitno ti gradiš nek menu iz kategorij ki jih imaš .. ko se kreira prvi nivo greš za vsako kategorijo pogledat če ima podkategorijo in prikažeš še te .. in tako v nedogled v globino kolikor jih obstaja.



Kategorij ne sme biti toliko da bi se ti funkcija obesla .... pa če tudi .. še vedno lahko postopoma zlagaš meni in ne vsega naenkrat, ... pa tudi vse skupaj vržeš v cache tako da se ne izvede ob vsakem requestu ..



Vseh kategorij nima smisla imet na enkrat odprtih, tako da prikažeš samo aktivne in na klik izdeveš kak ajax da ti pokaže še podkategorije.




Si si pogleda meni na tej strani ? http://cult-trgovina.si/si/ Ne pride tu v poštev ajax, keširanje pa lahko uredim šele potem, ko je meni že zgeneriran.


všeč(0) ni všeč(0) spam(0)
*Uporabniku je bila prepovedana uporaba foruma zaradi večih uporabniških računov, ki so po [pravilih obnašanja](/pravila.html) prepovedani.*
 
theuros 20. jun 2015 10:13:49 Pridružen od:
22. jun 2009
197 objav
120 22 1
#12

ah... ja če povečaš xdebug.maxnestinglevel bi ti pomagalo, vendar ti priporočam da spremeniš logiko da ne bo potrebne toliko rekurzije, saj ne vidim razloga zakaj bi moral imeti vso strukturo na voljo. Strukturo zlagaj postopoma, da ne presežeš limita oz. še bolje naloži samo vidne kategorije, vse ostale pa naložiš šele ko uporabnik klikne na njih.


všeč(1) ni všeč(0) spam(0)
Če je nekdo profesionalec še ne pomeni da obvlada tisto kar ponuja ampak samo, da služi z svojim delom.
 
pavarti 20. jun 2015 11:18:50 Pridružen od:
26. okt 2011
445 objav
587 92 14
#13

Obremenjuješ se nepotrebnimi stvarmi.

V kolikor te skrbi preveč poizvedb na bazo, dodaj strukturo v cache. Iz baze jo pa beri samo če se kaj spremeni.



Tako boš imel podatke v memoriju, branje in rekurzija bo hitra in malo potratna.



V kolikor ti je to še vedno potratno lahko keširaš tudi html izpis menija za naprimer prvi in drugi nivo.



Obstaja še mnogo načinov za optimizacijo, ampak načelo mora biti, da se optimizira takrat ko je to potrebno.


všeč(0) ni všeč(0) spam(0)
 
bostjan 20. jun 2015 11:21:19 Pridružen od:
31. jul 2008
643 objav
689 30 9
#14

poglej si še nested tree set (https://en.wikipedia.org/wiki/Nestedsetmodel), zna olajšat select querye




  • na faksu te naučijo, da se vsaka rekurzija da predelat v iteracijo (celo na izpitu imaš to :) )


všeč(1) ni všeč(0) spam(0)
 
carli 20. jun 2015 11:40:17 Pridružen od:
5. avg 2008
1258 objav
583 54 17
#15

Preberi vse zapise in poženi skozi zanko sortiranje v array, je tudi kar nekaj primerov po netu. Vse skupaj lažje za keširat in v bistvu imaš samo en klic na bazo :D


všeč(1) ni všeč(0) spam(0)
 
thai 24. jun 2015 14:32:21 Pridružen od:
14. dec 2014
81 objav
32 31 2
#16

bostjan:

poglej si še nested tree set (https://en.wikipedia.org/wiki/Nestedsetmodel), zna olajšat select querye




  • na faksu te naučijo, da se vsaka rekurzija da predelat v iteracijo (celo na izpitu imaš to :) )




Zanimivo.



carli: saj točno tako imam sedaj


všeč(0) ni všeč(0) spam(0)
*Uporabniku je bila prepovedana uporaba foruma zaradi večih uporabniških računov, ki so po [pravilih obnašanja](/pravila.html) prepovedani.*
 
carli 24. jun 2015 18:25:53 Pridružen od:
5. avg 2008
1258 objav
583 54 17
#17

Kako? Ne rabiš delat rekurzivnih klicev, za to da sortiraš!


všeč(0) ni všeč(0) spam(0)
 
thai 25. jun 2015 09:39:11 Pridružen od:
14. dec 2014
81 objav
32 31 2
#18

carli:

Kako? Ne rabiš delat rekurzivnih klicev, za to da sortiraš!




Ne vem, če se midva razumeva. Lahko potem pokažeš, kako bi rešil spodnji primer brez uporabe recursive?



V bazi ima vsaka kategorija id ter parent_id, gnezdi se lahko, jasno, neomejeno globoko.




všeč(0) ni všeč(0) spam(0)
*Uporabniku je bila prepovedana uporaba foruma zaradi večih uporabniških računov, ki so po [pravilih obnašanja](/pravila.html) prepovedani.*
 
carli 25. jun 2015 12:06:34 Pridružen od:
5. avg 2008
1258 objav
583 54 17
#19

Išči iterating over trees ali pa RecursiveIteratorIterator ... za display, ko imaš že enkrat sortiran array iz baze, pa seveda potem skeširaj output, ker zna biti počasnejši pri večjih arrayih.



Večkrat je zadeva uporabna pri prikazu folderjev, itd...


všeč(1) ni všeč(0) spam(0)
 
DSmidge 26. jun 2015 07:59:00 Pridružen od:
29. maj 2015
8 objav
8 0 0
#20

En način je, da celoten meni sestaviš že na bazi. To bi bilo v primeru, da bi imel v tabeli en kup zapisov, aktualni bi pa bili samo nekateri:

http://guilhembichot.blogspot.com/2013/11/with-recursive-and-mysql.html

V MS-SQL se za te namene uporablja rekurzivni klic s pomočjo WITH ukaza, pri MySQL je pa potrebno malo več telovadbe.



Drugi način, ki je verjetno bolj primeren zate, je pa da uporabiš kakšen bolj ali manj učinkovit (= enostavnejši) algoritem za sestavljanje drevesa - kot so ti že predlagali.



Čisto enostavni način, ki je hkrati zelo neučinkovit, ko imaš veliko podatkov, je da uporabiš dve FOR zanki. Z vsako od njih se sprehodiš skozi svoj seznam in na PARENT_ID dodajaš ID zapise.


// Primer, ko imaš polje $kateg, kjer imaš pod vsakim zapisom spet polje vrednosti (lahko pa to predelaš z uporabo FOREACH)
// Tole pišem na pamet ni pretestirano
// Dele, ki se začnejo s TODO je potrebno še doprogramirati
$result = [];
// Spodnje zanke ponavljaj toliko časa, dokler ne bo nič več za dodati
$repeat = true;
while ($repeat) {
$repeat = false;
for ($a = 0, $ac = count($kateg); $a < $ac; $a++) {
$a_id = $kateg[$a]['id'];
$a_pid = $kateg[$a]['parent_id'];
// TODO: Dodaj preverjanje, če je element že v seznamu $result[], casting
if ($a_pid === null) $result[$a_id]['id_path'] = $a_id; // Sestavljaj pot povezanih ID-jev
for ($b = 0, $bc = count($kateg); $b < $bc; $b++) {
$b_id = $kateg[$b]['id'];
$b_pid = $kateg[$b]['parent_id'];
// TODO: Ni optimalno, ker se mora parent že nahajati v končnem seznamu
if ($a_id === $b_pid && in_array($a_id, $result)) {
// Dodaj v končni seznam
// TODO: Dodaj preverjanje, če je element že v seznamu $result[], casting
$result[$b_id]['id_path'] = $result[$a_id]['id_path'] . '#' . $b_id; // Sestavljaj pot povezanih ID-jev
$repeat = true;
}
}
}
}

Na koncu še posortiraš polje po 'id_path' ter urediš zamike.



Optimizacije so možne: npr. beležiš zapise, ki so že bili dodani in se po njih ne sprehajaš več v naslednjih korakih, idr.


všeč(1) ni všeč(0) spam(0)
 
 

🔒 Za odgovor na to temo se moraš prijaviti.

Prijavi se