Na nabídku

Postřehy z CakePHP


Věci, na které jsem narazil při práci nad CakePHP


Paginator

Narazil jsem na další věc, ke které mám v CakePHP výhrady. Paginator má pomoci se stránkováním produktů. Fajn. Ale jen na jednoduché struktury, při vyhledávání a řazení složitějších věcí začne být koulí na noze. Typické zpracování při stránkování nad kategorií by totiž mělo mít více kroků, než nyní má.

  1. nacucat všechny k dispozici podle nějakého omezení (obecně povolení) - find.
  2. vyházet ty, které mají jiné omezení (v mém případě lokální naskladněnost, avšak měly by tu být všechny parametry, které zasahují do dalších tabulek a zároveň neomezují další volitelné parametry); pozor, join je nad větší hromadou VELMI pomalý, proto odebírání na vyšší vrstvě.
  3. vyzískat parametry, podle kterých lze výběr dále omezit.
  4. vyházet ty, které mají omezení parametry (podle výběru uživatele)
  5. seřadit
  6. vystránkovat stávající výběr (fakticky manipulujeme jenom nad polem produktů, takže se i šetří paměť - ještě se netahají závislosti).
  7. plné vyhledání produktů podle ID včetně doplnění údajů ze závislých tabulek pro vykreslení.

V CakePHP to jede jinak. Do jediné struktury je třeba nacpat všechny vztahy a parametry a tu pak poslat oklikou do Paginatoru a on vyplivne produkty. A vnitřní chod je také lehce jiný.

  1. nechá find() zpracovat předvyhledávací úlohy - předá databázi kompletní dotaz s parametry (ať se zblázní databázový server).
  2. find ještě provede připojení parametrů a návazností podle afterFind (táhne celou strukturu).
  3. paginator pak už jenom vyháže ty výsledky, které neodpovídají stránce a počtu na ní.

To zrovna není šetrný přístup. V případě jednoduchého projíždění kategorií produktů s parametry to ještě vcelku přežitelné. Průšvih začíná, když se do toho začne motat software třetích stran, typicky vyhledávací motor. Tady už je potřeba získat pouze podle vnějšího zadání povolená ID, tedy mnou popsaný krok 1. Co se s nimi vyvede dál, hlavně v omezovacím kroku 2 a 4, má už být motoru jedno. Ve chvíli, kdy tohle jede paginatorem, tak find musí nějak celou eskapádu obejít - a tak vyrábí těžko debugovatelné chyby.

Slušný paginator se chová jinak. Nejdřív zjistí z databáze množství všech použitelných položek a z toho pak podle aktuální stránky vrátí omezení pro dotaz. Netřeba lovit všechna data. A dotaz pak pracuje s touto informací od paginatoru. Sice jsou to 2 dotazy, ten první ale vrací 1 číslo a bude díky relacím lehčí, ten druhý, náročný, vrací už jen část dat se závislostmi. Vyhledávací motor pak vrací pouze primární klíče odpovídajících položek, paginator tak dostane množství položek a výsledek se vybere z položek v rozsahu podle paginatoru, na které ty primární klíče odkazují. Je to daleko elegantnější.

porovnání s KWCMS...

KWCMS1-2 něco takového jako paginator úplně neznalo, ale docela vede k prvnímu přístupu, jelikož neumí používat vztahy mezi tabulkami; stejně to nad soubory moc jinak nejde. Malinko o něm uvažuju, ale zásadní vada je, že to musí jít jako knihovna do zobrazovací i administrační části. KWCMS3+ má mapper, kde je paginator součástí a pager vedle. Tabulky už to potřebovaly.


CakePHP - problematika vztahů ve velkých tabulkách

Došlo na to. Měl jsem zábavu jménem export dat do xml souboru. Zpočátku všechno vypadalo snadně, pro málo položek stačí věci, které nabízí přímo Cake. Ovšem dump všech položek už je jiné kafe. Obzvlášť pokud jsou v návrhu správně v tabulkách rozdělené. Jako největší problém vypluly vztahy mezi tabulkami. Prostě tenhle přístup generuje dotazy, co se provádí velmi líně. Paradoxně daleko rychlejší je vycucat potřebné tabulky zvlášť a spojovat je až v aplikační vrstvě. První, co každého napadne, je použít předdefinované struktury, které framework vrací. To si ale dotyčný moc nepomůže, pořád tu visí potřeba najít vztah mezi položkami tabulek. Daleko lepší je prohnat každou tabulku funkcí, která vyrobí pole-záznam, co obsahuje potřebné součásti a jehož indexem je klíč a zbytek může zahodit. PHP je nejrychlejší právě při práci s indexy pole, navíc lze použít trochu "ostrou" taktiku s funkcemi isset() a empty(). Takovýmito změnami jsem daný skript zrychlil z 3 hodin na 5 minut. A to už lze debugovat. Na druhou stranu samozřejmě roste složitost samotného kódu, protože pro každou další tabulku je potřeba extra část, co z ní vyloví indexované pole pro navázání a pak samotné vázání.

CakePHP

Ano, i já, nepřítel frameworků pro malé projekty, začal v jednom dělat. On vůbec rozsah toho projektu nějaký větší gun vyžadoval. Frameworky nemám rád, protože vedou k určitým způsobům práce a jiné nemají rády. Většinou framework dostanete od edice "do-do" (dodělej doma) až po "včetně deštníčku, jen nasadit". Navíc zhusta využívají databáze, v případě PHP jednu konkrétní. A jak už jsem kdesi zmínil, ne vždy je databáze v této formě k mání. Proto jsem dělal KWCMS, kterému stačí systém souborů, kam se skripty kopírují.

Trávil jsem (2013) většinu času v pohledech a tedy šablonách. To je sice jen trapné kódění, ale bugy napříč prohlížeči už tak dávají občas zabrat (že, malý-měkký výbuch 8). Semtam jsem už začal pošilhávat po věcech volaných z řádky, v modelech a ovladačích.

Petr Plšek, 182 00 Praha, me@kalanys.com