Miért nem használok PHP frameworköt?

Felhívom a PHP Pro-k figyelmét, hogy a következő tartalom a nyugalom megzavarására alkalmas!

 

Az előzmények

Már nem is emlékszem évre pontosan pontosan, hogy mikor kezdtem először PHP-val foglalkozni, talán 2004-ben. Az első kecskeméti munkahelyemen, a felvétel egyik követelménye volt. Két napom volt megtanulni alap szinten, úgy, hogy minimális HTML ismerettel rendelkeztem (még a <form> -okat sem használtam előtte soha). Hol voltak még az online oktatók ingyen, a letölthető könyvek, miegymás? Hétvégén a semmiből tanulni, kb. lehetetlen küldetésnek tűnt. Szerencsémre Noxy kimentett és elmagyarázta nekem a lényeget. Akkor már sejthettem, hogy később a „hülyék nyelvének” fogom hívni: ha nekem sikerül megtanulni, akkor bárkinek sikerül.

Akkoriban még senki sem foglalkozott a biztonsággal, a mezők szűrésével. Senkit sem érdekelt az XSS vagy az SQL injection. Jó sok adatot el is loptak, könnyedén, nagyon nagy cégektől. Sok ember volt, aki saját boldogítására PHP-zett. Voltak az önbizalommal teli emberek, akik egyenesen addig merészkedtek, hogy hírportálokat indítsanak egymaguk. Ez utóbbiakba szívesen trollkodtunk bele jelképes JavaScript és PHP tudásunkkal, ráébresztve a készítőt, hogy van még mit tanulnia.

Már majdnem…

Kis szünet után, a következő munkahelyemen foglalkoztam újra PHP-val. Eleinte csak a saját munkám könnyítésére, intranetes oldalacskákat írtam, majd egyre több olyan probléma jött, amit csak PHP-val tudtam megoldani – ugyanis más nyelvet nem ismertem. Eddig nagyobb projektem nem volt, így fel sem merült a framework használata. Ha kellett egy új elem, csak pár perc alatt hozzáírtam és kész. A natív PHP-t később visszanézve is egyből tudtam, hogy mi, mit csinál.

Az első nagyobb projekt

Egy motoros hírportált kellett módosítani/kibővíteni/átírni. Akkor felmerült, hogy valamilyen tartalomkezelő alkalmasabb lenne a feladatra. De valahogy minden újabb igény olyan volt, amire nem volt kész modul és mindig újat kellett volna fejleszteni. Tudom, felelőtlenség a WordPresst frameworknek hívni, de tulajdonképpen az. Mivel nem valami sok WordPress mintapélda volt a neten – amik voltak pedig szörnyen voltak dokumentálva – ezért úgy  döntöttünk, hogy a képességeimnek megfelelően lesz megoldva: sima, natív PHP-val. Ez volt az első eset, hogy a pro fejlesztők szemével nézve, minimum 2 keretrendszert kellett volna használni 🙂

Ekkor még nem volt annyira felkapva az MVC. Az oldalak dugig voltak szöveggel, kicsik voltak a képek, nem volt divat a CSS cserélgetése sem. Megvolt a PSD dizájn, szétszabdaltuk, statikus HTML lett belőle, majd a dinamikus részekbe sok-sok <?php echo ''; ?> -t tettünk. Igen, már akkor sem voltam rajongója a <?= ''; ?> rövidítésnek, mert szeretem, ha valamiről ránézésre látszik, mire való. (Érdekes módon a PHP7-ben végre kinyírták a short_open_tag -et, de a <?= megmaradt);

A kezdő szint

Egyre több olyan projektem lett, ahol már kissé modernebb dolgokra lett szükség: reszponzív dizájn, több oldalas/kategóriás/alkatagóriás/funkcionalitású részekkel. Így felmerült az igény egy framework megismerésére. Viszont az idő szűkössége miatt nem volt idő tanulni és oldalt gyártani, ezért maradt a natív PHP, mindenféle trükközés nélkül. A PHP „router” nem is magában a PHP scriptben volt, hanem az Apache2 webszerverhez kapcsolódó .htaccess fájlban, minden kategóriára/funkcióra egy-egy külön sorral. Ebben az esetben még mindig könnyen követhető, hogy mit is csinál az oldal, hogyan is talál oda a megfelelő részekhez. Valami ilyesmit kell elképzelni:

http://domain.hu/modul/azonosito – ahol a „modul” jelentette azt, hogy melyik view-t kell meghívnia, pontosabban melyik PHP fájlt, ami a megjelenítésért felelős, az „azonosito” pedig a modulhoz tartozó azonsoító. Valahogy így: http://hirportal.hu/hir/10345 vagy http://hirportal.hu/hir/ez-egy-szupi-jo-hir. A PHP-s logikában ez így volt megoldva:

<?php
   //...
switch( $_GET['modul'] ) {
   case 'hir': include_once 'modul/hir/hir.php'; break;
   case 'kapcsolat': include_once 'modul/kapcsolat/kapcsolat.php'; break;
   // ...
   default: include_once 'modul/default/default.php';
}
// ...

Tulajdonképpen ez már egy primitív router, de tulajdonképpen a teljes további logika a modul.php -ben van, a grafikai (view) és a logikai (controller) elemekkel együtt. Ami azt jelenti, hogy maga a modul.php kódja elég csúnya. Komoly hátránya a dolognak,hogy ha a grafikában valami változás áll be, akkor minden egyes modul.php-ben át kell írni a grafikát. Előnye pedig az, hogy nagyon könnyen meg lehet találni a hibákat és azt javítani. Olyan fejlesztőknek is, akik csak kezdő PHP-sok.

A használói-fejlesztői szint:

Most pedig elérkeztünk a valódi válaszhoz, hogy miért is kerülöm a PHP-s frameworkök használatát.

Amit nem szeretek a keretrendszerekben:

  • Nem „frissítésálló”.
    Az akár 12 éves PHP-s kódjaim nulla változtatással futnak PHP 7.0-án is, bátran frissíthetek operációs rendszert biztonsági okok miatt, nem kell aggódnom, hogy a projektek megállnak miatta és lehet szőrözni a changelogot. Amit persze ingyen kell megtenni, ellenben sok időt tud elvenni. Ellentétben a keretrendszerek esetében ritkán szabad naprakésznek lenni a PHP csomagok és modulok tekintetében, nagyon jól ismerni kell a changelogot és simán megteszik azt, hogy átneveznek egy olyan függvényt/osztályt amit amúgy gyakran használsz, vagy megváltoztatják annak paramétert sorrendjét. Biztonságilag ráadásul a keretrendszer készítőire kell támaszkodni, vagy az összes ügyfelet fel kell keresni, hogy bibi van, mert van egy PHP sebezhetőség és nem elég támaszkodni a hosting cégre.
  • Nem lehet polihisztornak lenni.
    Rengeteg framework van és csak egyre több és több lesz. Van, aki lefarag a másikhoz képest 2ms-ot, van aki megharagszik a régi csapatra, kivál belőle és megcsinálja a sajátját, stb-stb. A lényeg, hogy sok van és mindegyiket nem lehet ismerni. Mivel akkor lehet a keretrendszerekkel sok időt spórolni és szépen dolgozni, ha az ember minden problémára tudja a specifikus megoldást, azt professzionálisan ismerni kell, stackowerflow és Google több órás bogarászása nélkül. Szal’ egy átlag, normál ember gyanítom 2-3 ilyenből tudja magát profi szinten kiművelni. Ilyenkor jön a képbe Muprhy, mert mire kiműveli magát profi szintre az ember, addig tutira megszűnik a framework támogatása, beolvad egy másikba, A maradék 50-re van jól fizető állás, mert az ismertet már mindenki tudja és alád ajánlanak.
  • A hibakeresés.
    A fenti megoldáshoz képest rémálom a hibát megtalálni. Annyi belső kacifánton megy át az adat – aminek lehető legtöbb része persze indokolatlanul protected elérhetőségű, mer’ úgy szép és kész – , hogy a legkisebb paraméter átadás hiba is lehet rémálom. Igen-igen, a nagyok csodaszép statisztikázó és debuggoló megoldásokat adnak. Ezzel tisztában vagyok. De ha nem vagy jó az említett rendszerből, akkor egy rémálom (ha jó vagy, akkor is tud az lenni). Ráadásul a legtöbben amint átadják a projektet, minden hidat behintek atombombával, tehát a javításhoz olyan embert kell keresni (pénz++; idő++;) aki jól ért a rendszerhez.
  • A biztonság.
    Na, ha eddig nem köveztél meg, akkor most már biztos ököllel ütöd a monitort, hogy állíthatok ilyen hülyeséget. Nos, ha picit is jártas vagy a PHP sebezhetőségek témában, akkor tudod, hogy a legtöbb hacket – ami PHP specifikus, tehát nem SQL injection – a serialize függvények és az eval() segítségével hajtják végre. A keretrendszerek mindkettőt előszeretettel használják, hisz’ 1 paraméter átadásához is egy óriási objektumhalmazt adnak át, mert ha már OOP, akkor egy $i=1; integert is komplett namespace-interface-class-method -on keresztül lehet csak használni, természetesen protectedként, hogy még setter és getter is kelljen hozzá. Az elmúlt 2 hétben megjelent PHP súlyos sebeszhetőségek 80%-a serialize alapú hack, amiben a nagy frameworkök is érintettek.
    Mivel a frameworkök jellemző HTML kódot hagynak maguk után, egy célzott Google kereséssel adatbázisba gyűjtik a helyeket, ahol ilyenek futnak. Így ha megjelenik egy sebezhetőség hozzá, perceken belül van adatbázis dump és vagy teljes hozzáférés. Igen, tudom, néhány tíz óra, esetleg néhány hónap után jön hozzá a fix. De a frissítés természetesen csak remegő kézzel történhet, mert lehet közben a fenti viccek egyikét is meglépték. Persze a felelős fejlesztőcég azonnal szól az ügyfélnek, hogy: „10 perce olvastunk egy sebezhetőségről, ami a te oldaladat is érinti, kijavítjuk most” 🙂 Hát persze, hogy szinte sohasem történik ilyen. Kifizették a pénzt, átadtuk a projektet, takarodjatok, a következő 2-3 évben hozzá sem lesz nyúlva, vagy még tovább, egészen addig, amíg egy frissítés miatt le nem hal az oldal (lásd fent).
  • A telepítés.
    A natív PHP-s kódokat felmásoljuk F5-tel bárhova, bármire amin egy alap PHP elfut (amit akármelyik doboz alján találunk WRT-s ARM-tól, androidos telefonig vagy milliárdos vasig) és már működik is a paraméretek beállítása után. A keretrendszerek ellenben durván nagy függőségekkel tudnak rendelkezni (frissítési szívások ugye), jellemzően jól behatárolt elvárásoknak kell megfelelni. Sok esetben nem hivatalos vagy félhivatalos csomagokra hivatkoznak, mert olyan nincs, hogy mi magunk készítünk el egy parsert, hisz’ láttuk egyet múltkor, nem támogatott, 3 éve halott PEAR csomagban, használjuk azt. A következő főverzióra majd lesz saját, becsszó, vagy áttérünk egy másikra, de hogy ne legyen ütközés ezért átnevezünk pár függvényt (hmm, olyan ismerős rész).
  • A fröccsöntés.
    A fröccsöntött weblapok az egyetlenek amik anyagilag megérik. Ezért is szárnyalnak annyira a CMS-ek és frameworkök. Pár perc alatt összedobni az oldalt, a zöldet kicseréljük pirosra, 500.000Ft + 60.000/hó fejlesztői támogatás + 15.000Ft/óra módosítási díj. Persze még jobb, ha saját hosting cégnél csináljuk, mert akkor a kódot sem kell odaadni, örökre odaláncoljuk az ügyfelet. Persze hülyék lennénk követni a biztonsági és képesség beli frissítéseit a keretrendszernek, mert ha behal valami, akkor „én nem fogok 50 ügyfél projektjében, ingyen szívni”. A fröccsöntés velejárója, hogy univerzális elemek állnak mögötte. Brutális nagy overhead (nem tudom mi a szép magyar fordítása a szónak) az egész. Egy 5 statikus elemből álló weblap rendszerigénye 100-10.000x annyi erőforrást igényel frameworközve. Ezzel persze nincs baj, mert vetetünk az ügyféllel nagyobb csomagot oszt’ jónapot (lásd korábban a saját hostingot). Egészen addig, amíg nem nő jelentősen a látogatottság, mert az 5 oldalas PHP-vel generált lapunk már sok procis Xeonokat kajál meg. Jó-jó, RAM és CPU van kilóra.
    Az egységesség legnagyobb hátulütője mégis inkább a biztonság. A teljesítmény igény senkit sem érdekel (na jó, engem azért igen, de én nem vagyok pro fejlesztő).
  • A szakember.
    „A PHP a hülyék nyelve” – szoktam mondani. Mert ha nekem sikerül benne produkálni, akkor bárkinek sikerül, aki írni-olvasni tud. Egy keretrendszer nélküli kódot, bármilyen szinten levő (értsd: pénz) képes lehet karbantartani, módosítani, bugfixelni. Minél összetettebb egy framework, annál tapasztaltabb fejlesztő kell annak karbantartásához is. Márpedig – mint ahogy korábban is írtam – a weboldal nem egy olyan termék, ami átadás után nem igényel törődést. Ezzel nem azt mondom, hogy ne húzzunk meg egy minimális határt a szaktudást és tapasztalatot illetőleg. Azt mondom,  hogy 1/10 költséggel is számolhatunk, ha nem erőltetünk mindent csodarendszerekbe.
  • Az adatok tárolása.
    Jellemzően még mindig SQL-ben tároljuk az adatokat, bár erősen jön fel a NoSQL szemlélet. Az elterjedten használt keretrendszerek a jobb működés érdekében előre definiált adatbázis sémákkal dolgoznak és saját „adatbázis telepítőjükkel” kell azt létrehozni. Ez nyilván azért van, hogy a megfelelő osztályokat és objektumokat össze tudja rendelni az adatbázis tábláinak tartalmával. A NoSQL mozgalomnak nem vagyok híve. Bizonyos esetekben valóban sokkal gyorsabb lehet, de a komplex SQL kérések nagyon-nagyon kacifántosan oldhatók csak velük. Az SQL pedig igenis gyors. Ha nem az, akkor az adatbázisos szakembernek egy másik állást kell ajánlani a takarító részlegen.
    Én jobban hiszek az előre megtervezett adatbázisban, a megfelelő táblakapcsolatokban, SQL tárolt eljárásokban, view-kban, (stb.) és ezek dinamikus módosíthatóságában. Úgy vélem, hogy az adattárolás megvalósítása a leglényegesebb része a webes megoldásoknak. Az adattárolás kioptimalizálása jobban határok közé van szorítva a keretrendszerekben.
  • Az overhead.
    Magyarul valahogy úgy lehetne fordítani, hogy szükségtelen erőforrás pazarlás: ágyúval verébre. Iszonyatos mennyiségű szemét kísér minden kis paramétert vagy adatot. Ez ügye sebességben, de főleg erőforrás igényben durván meglátszik. Rengeteg felesleges adatlekérést okoz, hatalmas mennyiségű értelmetlen cache és SQL kapcsolatot, óriási RAM használatot…

Ha még mindig olvasol, akkor nyilván úgy érzed, hogy én vagyok a szakma szégyene, a rendes fejlesztés ellensége és az ilyen embernek nem lenne szabad gép elé ülnie. Részben igazad is van. Részben.

Ami viszont jó dolog a PHP keretrendszerekben:

  • A fejlesztési idő.
    Drasztikusan képes lecsökkenteni a fejlesztési időt. Főleg akkor, ha a sok űrlap miatt nagyon sok a mező-adatbázis összerendelés és vizsgálat.
  • A sablon HTML kódjának viszonylagos tisztasága
    Amennyiben később grafikai dizájn átszabásra van szükség, jól áttekinthető a HTML kód.
  • A router
    Nem kell saját routert gyártani, hisz’ már van a frameworkben.
  • Az adatbázis-objektum összekapcsolás
    A beviteli mezők generálására, vizsgálatára és ezek adatbázissal való összerendelésére már előre gyártott megoldások vannak. Bizonyos keretrendszereknél ezek „automatikusan” létre is jönnek.
  • A beépített PHP-s védelmek (pl. prepared statements)
    Nem kell a fejlesztőnek felesleges sorokat írnia, hogy védje az adatbázist és hogy kivédhesse az egyéb string alapú támadásokat (pl. XSS).
  • Űrlap generátorok
    Az űrlap generátor megoldja a kötelező mezők kérdését és a bevitt adatok típusának és értékének vizsgálatát is.
  • A forráskód rendezettsége
    Mivel az adatbázis műveletek, a ciklusok, a paraméterek kezelése a frameworkben történik, ezért a lényegi rész jobban áttekinthető, a fájlok rendezettek.
  • … ?

Természetesen használok keretrendszereket máshol és a PHP-ban is van egy-kettő ami tetszik (pl. RedbeanPHP). A JavaScriptben pl. nagyon megkönnyíti a munkát a jQuery, ami a Microsoft és a Google által is kb. szabvánnyá vált. A kényelem ára viszont a sebesség. De hát JS-ben általában ügye a klienstől vesszük el az erőforrást, szal’ vegyen a látogató erős gépet 😀 ).