-
Folosind Magento de ceva timp, pot spune ca platforma s-a schimbat mult de-a lungul timpului și vreau sa impartasesc câteva păreri personale legate de ea.
Cum a invatat Magento 2 din trecut cum sa facă greșeli noi noute
M-am intalnit prima oară cu platforma Magento în 2011, iar, in acel moment, știam despre ea doar că era bazată pe Zend Framework 1 și (în mod evident) ca se ocupă cu e-commerce.
Eu veneam din universul framework-ului Symfony, unde exista documentație din belșug, o comunitate foarte mare, și care avea o implementare solidă. Acestea se intamplau de-abia pe vremea Symfony 1, Symfony 2 de abia aparuse.
Prin comparatie, Magento nu avea aproape deloc documentație, comunitatea era într-un stadiu incipient, și implementarea nu ducea lipsa de bug-uri. Încă din primele zile la noul job am văzut mulți colegi care făceau debugging adanc in Core, eram perplex, eu aproape că nu avusesem niciodată nevoie sa fac debugging în Core-ul de Symfony, darămite să mai găsesc și bug-uri.
Unii pot argumenta ca Symfony este un framework, pe cand Magento este o platforma, iar eu sunt de acord ca acesta este un argument cel puțin la fel de solid ca un porcusor de guinea.
Motivul pentru care s-a ajuns la aceasta situatie e simplu: nu se așteptau ca platforma sa aiba atat de mult success; dar a avut, și motivul a fost simplu – a fost cam singura platforma din universul PHP care fusese construită sa fie modulară, punct! Mai erau și alte platforme, dar în mod sigur nu la fel de versatile, pline de functionalitati și modulare precum Magento.
În perioada următoare au investit mult timp și efort pentru a construi o documentație ampla pentru Magento1, s-au concentrat pe calitate, pe stabilitate imbatabilă, și toate acestea au fost completate cu un suport de excepție oferit partenerilor de tip enterprise!
Te-am prins! Nu, nu au făcut asta! Documentatia pentru M1 a fost mereu sărăcăcioasă și de foarte slabă calitate. Cea mai buna resursa a fost cursul “Fundamentals of Magento Development” de Ben Marks, o carte (despre care nu-mi pot exprima o opinie pentru ca nu am citit-o), niște postări pe bloguri personale și ale companiilor care lucrau cu platforma și, nu în ultimul rand, multe întrebări și răspunsuri pe StackOverflow. Toate acestea au fost combinate cu un suport deosebit de prost pentru clienții enterprise, răspunsuri lente și de o calitate îndoielnică și, peste toate astea, o varietate de bug-uri în Core. Nu era ceva ieșit din comun sa gasesti implementări atipice sau făcute doar pe jumate alături de bug-uri în Core. Dar Core-ul era suficient de simplu, așa ca, folosind doar Xdebug și multă răbdare, totul era mai mult sau mai puțin rezolvabil.
Fix-urile de la suport erau intamplari aproape mitice. Dacă nu aveai chef sa repari un bug, sau pur și simplu nu aveai chef de munca, puteai deschide un ticket și de cele mai multe ori dura cateva zile sau chiar saptamani pana cand primeai un răspuns corespunzător. Până în acel moment, de multe ori problema era deja rezolva și (în unele cazuri) soluția chiar trimisă celor de la suport ca sa poată repara problema si în Core..
Și așa apare Magento 2
Cu povara popularității care a incurajat dezvoltarea Magento 1, Magento 2 a venit sa salveze situatia.
A durat mult timp pana cand Magento 2 a fost gata, și cred ca asta ar putea sa fie în sine o poveste, dar de data aceasta au fost luate unele măsuri pentru a evita problemele pe care le-a avut prima versiune.
Sa vedem unele din probleme platformei:
- functionalitatea claselor nu puteau fi extinsă decât prin suprascriere;
- partea de frontend era bazată exclusiv pe framework-ul Prototype.
Existau multe alte probleme, dar cred ca acestea erau printre cele mai relevante.
Și sa vedem cum Magento 2 a reușit sa rezolve toate aceste probleme
Este de bun augur sa începi cu ceva pozitiv, așa ca voi începe cu documentatia, Magento2 avea documentație încă de la început și era atat utilă, cat și bine făcută!
Legat de suprascrierea claselor, au fost implementate două abordări:
- implementarea a dependency injection (din Symfony);
- implementarea pluginurilor folosind Interceptor pattern.
Dependency injection ajuta foarte mult la înlocuirea de clase și functionalitati, iar plug-in-urile ajuta la extinderea sau modificarea functionalitatilor printr-o metoda neinvaziva. Înainte de plug-in-uri, doar observerele ofereau posibilitatea de a modifica date într-o maniera neinvaziva, marea problema fiind ca (în multe cazuri) pur și simplu nu erau observere peste tot unde aveai nevoie de ele.
Din pacate, aceasta abordare a crescut cu mult complexitatea. Dacă în M1 puteai pune un breakpoint și apoi urmareai stacktrace-ul ca sa vezi ce metode modifică ce anume, acum… era pur și simplu mult mai complex, pentru ca fiecare metoda clasa interceptor declanșează mecanismul de plug-in. Fiecare plug-in poate sa declanșeze o acțiune înainte, după, sau în jurul metodei și poate chiar sa prevină metoda din a fi apelată. Atunci cand functioneaza, abordarea este mult mai elegantă, dar atunci cand nu funcționează este mult mai dificil de făcut debugging.
Într-o intorsatura dramatica de situație, nu toate clasele au fost implementate corespunzător în Core. Vezi tu, atunci cand Magento 2 a fost lansat, au fost necesare multe compromisuri, iar multe module din Core a trebuit sa fie “făcute sa mearga” în noul framework. Mai tarziu, cand toata lumea aștepta sa se facă curățenie… momentul nu a mai venit, iar motivul a fost simplu: de ce sa repari Core-ul cand riști să strici compatibilitatea cu modulele deja existente?
Acest lucru i-a făcut pe dezvoltatorii de Core sa sugereze sa folosesti direcția sugerată de ei in ghid, sa nu iei implementarea din Core drept exemplu: fa cum spunem noi, nu cum facem noi.
Frontend-ul a fost reparat și mai bine! Poate unii se întreabă ce este “prototype” și de ce cineva întreg la cap ar alege așa ceva? În vremurile in care Magento 1 a fost creat avea mai mult sens, pentru ca exista o serie intreaga de librării populare, în principal: jQuery, Prototype și MooTools. Erau mult mai multe pe langa acestea trei, dar acestea erau printre cele mai populare. Era un război între jQuery și Prototype, așa cum este in prezent cel dintre React, Angular și Vue. jQuery avea o abordare nouă care părea să semene chiar cu un limbaj nou, în timp ce Prototype a mers pe extinderea capabilitatilor browserului într-o maniera mai discreta. Acum știm cine a castigat, dar pe atunci nu era la fel de evident. Ca o mica nota, și eu eram fan Prototype la vremea respectivă.
Echipa Magento 2 a realizat în timp ca a făcut o gresala si, ca sa o repare, au promis ca vor avea o abordare mai flexibilă. Noua abordare mai flexibilă nu a mai folosit libraria Prototype, iar în locul ei au fost incluse: jQuery, Knockout.js și Require.js, asta doar la nivelul superior, fără sa luăm toate celelalte dependinte in considerare.
Ideea era o mai buna separare între frontend și backend, pentru a putea face o aplicație de frontend complet nouă. Dar, la fel ca mai înainte, acest plan nu a fost finalizat, iar acum este doar un sistem foarte complicat, parțial separat, parțial aplicație “single page” și parțial… “multi page”, implementat folosind o varietate de stiluri. Iar aceasta este doar pe store front, pe store backend este puțin diferit, un sistem mai complex format din fișiere xml, phtml, html și js. Ca backend developer, pot spune sincer ca este mult mai dificil decât înainte sa faci debug (sau doar sa înțeleg cum funcționează părți din frontend).
Poate cea mai dificila parte este cea de generare de griduri folosind XML, debugging-ul poate fi facut doar cu mari dificultati, iar daca gresesti ceva nu primești niciun warning, trebuie sa gasesti clasa care construiește efectiv gridul și sa vezi daca apare acolo vreo excepție, ceea ce nu este deloc o soluție evidenta…
Și, evident, totul este mult mai lent, din pricina noilor “abordări inginerești”. Cand tot codul intermediar este generat, legăturile facute către resursele statice și totul este setat în modul producție, nu este foarte rapid, dar nu este nici groaznic de încet. Dar atunci cand nu ai cache, nu ai făcut deploy la resurse statice, și mai ești și în modul developer, este groaznic de încet, poate dura minute bune pentru a incarca o simpla pagina de produs! Este pur și simplu ridicol! Dacă mă întrebați pe mine, nu este un sistem de operare, sau un joc video, este un magazin virtual, nu exista niciun motiv pentru care sa dureze 5 minute pentru a afișa o pagina, lucru care se intampla chiar si in cazul in care nu ai multe module adiționale instalate.
Trebuie avut în vedere ca Magento 2 nu a venit cu o multitudine de noi functionalitati, majoritatea funcționalitatilor principale erau și în M1, doar ca au fost mai “inginerizate”, asa ca acele 5 minute de generare de cod, generare de legături și alte magii pe care le mai face, nu vin de la adaugarea de functionalitati noi, doar refactorizari ale sistemului vechi.
Magento Cloud
Magento a oferit și o soluție de Cloud, nu știu dacă-l mai oferă, nu-mi pasa prea tare, nimănui nu pare să-i mai pese, în speță pentru ca nu era ce își dorea lumea.
Oamenii vor lucruri simple: ai o aplicație, o urci în nori și începe sa ploua cu bani. Cam asta este tot ce ar trebuie sa fie – mai puține griji.
Demandware, care nu are un core open source, face ceva de acest tip. Nu ai la fel de mult control, dar nu tu te ocupi de website-ul tău, zeii din nori se ocupă (suna mai bine în engleza)! Dezvoltatorul doar dezvolta, lui nu ar trebui să-i pese ce magii fac cei de la operations, pentru ca el nu e ops, el e dev!
Magento Cloud încerca sa facă asta, speranta era ca tu doar trimiti caracatita în norișor și niște ops foarte inteligenți o sa scaleze pentru tine! Dar nu era deloc așa, nu era deloc ușor, si nici rapid. Si, peste toate acestea, au inceput sa apara hosting providers cu soluții specializate pe Magento care făceau o treaba mai buna la scalare decât hostingul oficial, lucru care mi se pare de necrezut.
Dar sa incheiem intr-o nota pozitiva
Sub toate aceste neajunsuri, exista totuși un Core interesant. Sunt o mulțime de functionalitati foarte inteligente care au făcut platforma atat de populara. Acum exista și teste, deci poți face chiar și TDD.
Chiar și cu atatea provocări (supra)inginerești, exista totuși destui programatori pasionați care sunt gata sa le depaseasca.
Sunt și multe unelte dezvoltate de comunitate pentru a acoperi din lipsuri, cum ar fi problema cu numarul foarte mare de fișiere care trebuie generate pentru un model, sau MSP_DevTools care ajuta la debugging pe frontend, sau n98-magerun2 care te ajuta sa lucrezi cu cronuri și multe, multe altele.
Și, nu în ultimul rand, încă sunt mulți programatori straluciti și pasionați care sunt gata să găsească un mod de a dezvolta și scala aplicatii e-Commerce bazate pe Magento pentru a face vanzari încă o zi!
-
Ah, atmosfera de sarbatori…
Inspirat de o postare in Perl Advent, m-am gandit ca ar fi interesant sa vedem un exemplu cu PHP si Go. Vreau sa mentionez ca acest blog este inspirat intr-o buna masura din postarea mentionata anterior.
Sa presupunem ca vrei sa-i urezi cuiva sarbatori fericite folosind viteza limbajului Go, dar aplicatia ta este scrisa in PHP, ce poti face?
In lumea PHP ar fi momentul ideal, deoarece noua versiune PHP 7.4 vine cu “Foreign Function Interface” (FFI pe scurt).
Echipat cu aceasta noua arma, am instalat PHP 7.4 si am trecut la treaba.
Sa incepem cu super incredibila urare din Go, sa creem fisierul “greeting.go”:
1package main 2 3import ( 4 "fmt" 5) 6 7func main() { 8 WishMerryChristmas(); 9} 10 11func WishMerryChristmas() { 12 fmt.Println("We wish you a Merry Christmas!"); 13}
Si acum sa-l rulam:
1$ go run greeting.go
Ar trebui sa afiseze:
1We wish you a Merry Christmas!
Pana aici e super! Este foarte rapid, frumos si tot ce mai trebuie, dar noua ne-ar trebui sa fie un serviciu, deci sa vedem cum o sa arate in acest caz:
1package main 2 3import ( 4 "C" 5 "fmt" 6) 7 8func main() {} 9 10//export WishMerryChristmas 11func WishMerryChristmas() { 12 fmt.Println("We wish you a Merry Christmas!") 13}
Dupa cum se poate vedea, exista cateva diferente:
- am importat si libraria “C”,
- am scos apelul functiei din main()
- am adaugat un comentariu pentru exportul functiei.
Pentru compilare se ruleaza astfel:
1$ go build -o greeting.so -buildmode=c-shared
De mentionat este faptul ca aceasta comanda trebuie rulata de fiecare data cand fisierul Go este modificat.
Rezultatul ar trebuie sa fie compus din doua fisiere:
“greeting.so” si “greeting.h”.Fisierul de header “greeting.h” contine tipurile de date si definitile functiilor. Daca ai mai lucrat cu C, esti probabil familiarizat cu acest fel de fisiere. In mod normal, tot ce trebuie sa mai facem acum este sa importam fisierul header folosind FFI si sa apelam functia!
Pentru asta am creat un fisier cu numele “greeting.php”:
1<?php 2$ffi = FFI::load("greeting.h"); 3$ffi->WishMerryChristmas();
Pare suficient de simplu, tot ce trebuie sa mai facem acum este sa-l rulam folosind comanda:
1$ php greeting.php 2PHP Fatal error: Uncaught FFI\ParserException: undefined C type '__SIZE_TYPE__' at line 43 in /home/claudiu/php-go/greeting.php:3 3Stack trace: 4#0 /home/claudiu/php-go/greeting.php(3): FFI::load() 5#1 {main} 6 7Next FFI\Exception: Failed loading 'greeting.h' in /home/claudiu/php-go/greeting.php:3 8Stack trace: 9#0 /home/claudiu/php-go/greeting.php(3): FFI::load() 10#1 {main} 11 thrown in /home/claudiu/php-go/greeting.php on line 3
Nu e tocmai urarea la care ma asteptam…
Dupa ce am sapat destul de intens, am gasit asta intr-o pagina de manual:
C preprocessor directives are not supported, i.e. #include, #define and CPP macros do not work.Din acest motiv, se pare ca nu vom putea folosi fisierul de header, sau cel putin eu nu am gasit o metoda clara.
Partea buna este ca putem folosi FFI::cdef() care permite sa specificam definitia functiilor. Daca te-am pierdut pe drum, ce incerc de fapt sa fac este sa-i spun PHP-ului care sunt definitile funcțiilor pe care vreau sa folosesc din fisierul “greeting.so”.
Noul cod va fi:
1<?php 2$ffi = FFI::cdef(" 3void WishMerryChristmas(); 4", __DIR__ . "/greeting.so"); 5 6$ffi->WishMerryChristmas();
Iar daca rulam acum:
1$ php greeting.php 2We wish you a Merry Christmas!
Am progresat mult, iar serviciul isi face treaba foarte bine!
Adaugarea unui parametru int
Urarea arata foarte bine si e super rapida, dar ar fi si mai frumos sa putem specifica de cate ori sa o afisam.
Pentru a face asta, trebuie modificata functia din fisierul “greeting.go”, adaugandu-i un parametru cu numarul afisarilor dorite:1//export WishMerryChristmas 2func WishMerryChristmas(number int) { 3 for i := 0; i < number; i++ { 4 fmt.Println("We wish you a Merry Christmas!"); 5 } 6}
Trebuie rulata din nou comanda de compilare ca mai devreme.
In PHP trebuie sa modificam definitia functiei. Pentru a vedea ce trebuie modificat putem sa ne inspiram din fisierul “greeting.h”. Noua definitie a functiei in fisier este:
1extern void WishMerryChristmas(GoInt p0);
“GoInt”? Ce magie mai e si asta? Daca ne uitam in fisier gasim urmatoarele definitii:
1... 2typedef long long GoInt64; 3... 4typedef GoInt64 GoInt; 5...
De unde concluzionam ca GoInt este de fapt un long.
Cu aceste noi descoperiri putem modifica fisierul PHP in:
1<?php 2 3$ffi = FFI::cdef(" 4void WishMerryChristmas(long); 5", __DIR__ . "/greeting.so"); 6 7$ffi->WishMerryChristmas(3);
Il rulam din nou si vedem:
1$ php greeting.php 2We wish you a Merry Christmas! 3We wish you a Merry Christmas! 4We wish you a Merry Christmas!
Ah, incepe sa se simta spiritul sarbatorilor!
Adaugarea unui parametru string
Sa afisam o urare de mai multe ori este destul de dragut, dar ar fi mai dragut sa adaugam si un nume.
Noua functie devine:
1//export WishMerryChristmas 2func WishMerryChristmas(name string, number int) { 3 for i := 0; i < number; i++ { 4 fmt.Printf("We wish you a Merry Christmas, %s!\n", name); 5 } 6}
Nu uita sa compilezi, iar apoi vom trece la partea interesanta.
Daca ne uitam in fisierul “greeting.h”, noua definitie a functiei este:
1extern void WishMerryChristmas(GoString p0, GoInt p1);
Stim deja ce este GoInt, dar GoString este un pic mai complicat. Dupa mai multe substituiri am ajuns la structura:
1typedef struct { char* p; long n } GoString;
Este practic un pointer catre o lista de caractere si o dimensiune.
Asta inseamna ca, in fisierul PHP, noua definitie o sa fie:
1$ffi = FFI::cdef(" 2typedef struct { char* p; long n } GoString; 3typedef long GoInt; 4void WishMerryChristmas(GoString p0, GoInt p1); 5", __DIR__ . "/greeting.so");
p0 si p1 sunt optionali, dar i-am lasat ca sa semene mai mult cu definitia din fisierul de header.
Similar, GoInt este practic un long, dar l-am lasat acolo din acelasi motiv.Construirea unui GoString din PHP a fost un pic mai complicata. Principala cauza a fost ca nu am gasit un mod sa fac un “char *” si sa-l initializez in acelasi timp. Alternativa mea a fost sa fac un array de “char” si apoi sa-i fac cast, dupa cum urmeaza:
1$name = "reader"; 2$strChar = str_split($name); 3 4$c = FFI::new('char[' . count($strChar) . ']'); 5foreach ($strChar as $i => $char) { 6 $c[$i] = $char; 7} 8 9$goStr = $ffi->new("GoString"); 10$goStr->p = FFI::cast(FFI::type('char *'), $c); 11$goStr->n = count($strChar); 12 13$ffi->WishMerryChristmas($goStr, 2);
Sa-l incercam:
1$ php greeting.php 2We wish you a Merry Christmas, reader! 3We wish you a Merry Christmas, reader!
Succes!
In aceasta faza, mi-ar placea sa mut crearea de GoString intr-o functie separata, de dragul lizibilitatii codului.
Noul cod rezultat este:
1$name = "reader"; 2 3$goStr = stringToGoString($ffi->new("GoString"), $name); 4 5$ffi->WishMerryChristmas($goStr, 2); 6 7function stringToGoString($goStr, $name) { 8 $strChar = str_split($name); 9 10 $c = FFI::new('char[' . count($strChar) . ']'); 11 foreach ($strChar as $i => $char) { 12 $c[$i] = $char; 13 } 14 15 $goStr->p = FFI::cast(FFI::type('char *'), $c); 16 $goStr->n = count($strChar); 17 18 return $goStr; 19}
Si acum sa-l incercam:
1$ php greeting.php 2We wish you a Merry Christmas, ��! 3We wish you a Merry Christmas, ��!
Hopa, nu e tocmai bine… pare ca afisam niste memorie reziduala. Dar de ce?
Cautand in documentatia FFI::new am gasit un al doilea parametru, “bool $owned = TRUE”.
Whether to create owned (i.e. managed) or unmanaged data. Managed data lives together with the returned FFI\CData object, and is released when the last reference to that object is released by regular PHP reference counting or GC. Unmanaged data should be released by calling FFI::free(), when no longer needed.
Asta inseamna ca atunci cand intoarcem rezultatul functiei, GC-ul din PHP dezaloca memoria pentru variabila cu string-ul. Este destul de probabil ca acesta sa fie un bug, dar exista o solutie foarte simpla, trebuie doar sa adaugam “false” la crearea de array:
1$c = FFI::new('char[' . count($strChar) . ']', false);
Sa incercam din nou:
1$ php greeting.php 2We wish you a Merry Christmas, reader! 3We wish you a Merry Christmas, reader!
Si functioneaza!
Concluzie
Poate ca rulatul din PHP a unei librarii scrisa in Go nu este atat de simplu precum importul unui fisier de header, dar cu putina rabdare nu este nici foarte dificil! Marele avantaj este ca librariile scrise in Go, sau in orice alt limbaj de programare care permite acest lucru, pot fi folosite din PHP fara sa mai trebuiasca reimplementarea lor!
Si, încheind pe aceasta nota pozitiva, va urez sarbatori fericite!
-
Nota
Trebuie mentionat ca aceasta solutie este adaptata nevoilor mele, deci exista posibilitatea ca ele sa nu se suprapuna perfect cu nevoile tale. Totusi nu-ti face griji, totul este pe GitHub, asa ca poti lua doar ce ai nevoie.
Vreau sa mai adaug si ca acesta nu este blog de genul “ai folosit total gresit Magento2 cu Docker pana acum, uite cum se face de fapt”, eu doar vreau sa-mi impartasesc experienta. Probabil ca nu este cea mai buna solutie pentru toata lumea, dar cred ca orice persoana interesata de subiect poate gasi ceva util aici.
Intro
De aproape 2 ani folosesc Magento2 in containere Docker. Am facut asta si inainte, dar trebuie sa recunosc ca a fost pentru ca a trebuit, nu pentru ca am vazut calea cea buna, adica avantajele Docker.
Dupa cum probabil ai aflat deja, Magento2 nu este tocmai o aplicatie micuta si usoara, este chiar foarte greoi, lucru vizibil in special in timpul dezvoltarii.
Daca l-am compara cu un VM clasic, cu Docker ai avea in plus:
- Viteza: cred ca acesta este unul dintre cele mai mari avantaje, poti opri si porni containerele foarte rapid, doar primul build dureaza mai mult, dupa asta totul va fi foarte rapid;
- Mai putine resurse utilizate: Comparat cu un VM, un container nu trebuie sa includa tot sistemul de operare, in consecinta nu va ocupa mult spatiu pe disc si nu va folosi foarte multa putere de procesare, iar pentru ca nu este un OS intreg nu face toate lucrurile… de OS, in general face doar actiuni legate de serverul relevant.
Dar ce nu primesti in schimb:
- Curba de invatare: daca nu ai cunostinte de Docker si Docker Compose, o sa fie mai putin intuitiv la inceput;
- Prima instalare: este mai greu de setat la inceput, iar daca ai folosit VM-uri mult timp o sa ai impresia ca mergi impotriva curentului, dar cu siguranta o sa devina mult mai usor pe termen lung.
Luand cele de mai sus in considerare, vreau sa mentionez ca atunci cand am facut acest setup foloseam un Linux cu 8Gb de RAM. Un coleg chiar mi-a urat succes in a instala Magento2 pe un calculator ultraportabil cu 8Gb de RAM. Nici macar nu era sarcastic, era mai degraba compasiune legata de decizia mea proasta in a-mi alege calculatorul de lucru.
O alta nevoie a fost sa am izolare si configuratii specifice intre proiecte, nu puteam sa instalez un server pe local si gata.
In trecut am folosit Vagrant si VirtualBox, o combinatie foarte buna, foarte usor de folosit (in mare parte). Dar pentru Magento2, am realizat ca avea nevoie de prea multe resurse si calculatorul meu nu facea fata.
Totodata trebuia sa fie si usor de folosit, nu-mi place sa scriu comenzi de 3 cuvinte din memorie, vreau doar sa apas tab de cateva ori si sa se rezolve totul.
Cerintele
Au fost cateva cerinte specifice:
- nginx config – trebuia sa meraga din prima, iar fisierul de configurare pentru Magento 2 nu e tocmai mic si usor de folosit;
- SSL – domeniul trebuia sa mearga si cu HTTPS, in mare parte din pricina API-urilor care aveau nevoie de o conexiune HTTPS, chiar daca certificatul nu este valid;
- bash – comenzile de Magento trebuiau sa fie rulate cu utilizatorul de pe sistemul gazda, nu ca root (asa cum ruleaza in general containerele). Aveam nevoie de asta ca sa nu fie probleme de drepturi intre fisierele generate de mine si cele generate de Magento.
- xdebug – trebuie sa ruleze out of the box si sa fie usor de integrat cu un IDE.
Implementare si intrebuintare
Magento2 oferea un container Docker pentru dezvoltare. Nu vreau sa spun nimic de el, pentru ca nu era deloc ce imi trebuia.
Sursa mea principala de inspiratie a fost: https://github.com/markoshust/docker-magento. Proiectul s-a schimbat foarte mult in ultimii 2 ani, dar merita sa-i acordati cateva minute.
Punctul de inceput este: https://github.com/claudiu-persoiu/magento2-docker-compose
Fisierele relevante sunt:
- magento2 – ar trebui sa contina un folder html in care se afla proiectul;
- dkc_short – poate sa stea oriunde, dar ar trebui adaugat la ~/.bash_profile or ~/.bashrc, acest fisier contine alias-uri si scurtaturi, nu este neaparat necesar dar mie imi face viata mai usoara;
- docker-compose.yml – contine toate maparile si containerele relevante.
NOTA: Cred ca ar trebui sa mentionez ca in containerul PHP se pot rula comenzi in doua feluri, ca utilizator de sistem sau ca root. Aceasta limitare este datorata modului in care ruleaza containerele in Linux, o sa revin la acest subiect mai tarziu.
Pasul 1:
Ce trebuie facut atunci cand vrei sa rulezi un proiect Magento2 existent:
1$ git clone https://github.com/claudiu-persoiu/magento2-docker-compose.git nume_proiect 2$ cd nume_proiect 3$ git clone calea_catre_repository magento2/html
Pasul 2 (optional):
Copierea alias-urilor in consola bash:
1$ cp dkc_short ~/ 2$ echo ~/dkc_short >> ~/.bash_profile 3$ source ~/.bash_profile
NOTE: Daca nu exista fisierul ~/.bash_profile atunci trebuie folosit ~/.bashrc
Pasul 3:
Pornirea containerelor:
1$ dkc-up -d
Va dura mai mult prima data, dar de data viitoare va fi mult mai rapid.
Pasul 4:
Instalat dependinte folosind composer:
1$ dkc-php-run composer install
Cam asta e tot.
Ce e chestia asta cu dkc?
Dupa cum spuneam, imi place sa folosesc tab cand scriu o comanda, asa ca mi-am adaugat cateva alias-uri care imi permit sa rulez comenzi fara sa tastez tot. De exemplu dkc[tab]p[tab]-[tab] si restul comenzii. Iubesc autocomplete-ul din bash.
Lista de comenzi este foarte simpla:
- dkc-up -d – pornesc toate containerele in background
- dkc-down – opresc toate containerele
- dkc-mag [command] – ruleaza o comanda Magento2
- dkc-clean – curata cache-ul
- dkc-php-run – ruleaza o comanda bash in containerul de PHP, cum a fost composer in exemplul anterior. NOTA: aceasta comanda ruleaza ca utilizator de sistem, nu root
- dkc-exec phpfpm [command] – la fel ca mai sus dar dar ruleaza ca root. In majoritatea cazurilor va fi nevoie doar de comanda de mai sus;
- dkc-exec [container] [command] – aceasta comanda are nevoie de explicatie mai extinsa:
- poate sa fie:
- app – pt serverul Nginx,
- phpfrm – pentru containerul PHP,
- db – pentru baza de date,
- cache sau fpc – pentru cache;
- aceasta comanda poate sa fie orice se aplica la un container, precum “bash” sau “bash composer”, etc.
- poate sa fie:
Stiu ca toate comenzile par ca mai adauga ceva de invatat, dar in mare parte din timp doar primele 4 sunt necesare.
Cum functioneaza toata magia?
Pai, comenzile de mai sus se pot vedea in fisierul “dkc_short”.
Mai sunt doua repositories de interes:
- https://github.com/claudiu-persoiu/magento2-docker-php – containerul phpfpm,
- https://github.com/claudiu-persoiu/magento2-docker-nginx – containerul cu serverul nginx.
Repository-urile sunt destul de mici si relativ usor de inteles.
Daca ai nevoie sa modifici ceva, poti face un fork fara grija.
Concluzia
Cam asta e tot ce este de stiut, eu folosesc aceasta configuratie de aproape 2 ani.
Pentru mine functioneaza fara probleme si am putut sa folosesc Magento2 pe un calculator ultraportabil cu 8Gb RAM fara niciun neajuns.
Final (fericit)!
-
De curand am trecut examenul pentru Zend Certified Engineer 2017, certificare oferita de Rogue Wave.
Desi experienta este cel mai important lucru pentru o certificare, cartile sunt cel mai bun mod de a-ti largi cunostintele, in opinia mea.
Pentru ca o certificare este ceva foarte specific, nu sunt foarte multe carti relevante disponibile.
Inainte de a incepe, trebuie notat ca cea mai exhaustiva resursa pentru a invata PHP este manualul, intotdeauna trebuie trecut prin toate clasele si functiile care sunt disponibile.
Zend Certified Engineer Exam Study Guide 20$
Am cumparat aceasta carte doar pentru ca am vrut sa-i fac un review si sa-mi castig dreptul de a-mi exprima parerea despre ea.
Acest ghid a fost introdus cu certificarea pentru PHP 5.3 si pe atunci era gratuit. Calitatea cartii s-a imbunatatit continuu intre timp, dar niciodata foarte mult, iar de la un moment nu a mai fost o resursa gratuita.
Am sperat ca in timp o sa devina din ce in ce mai bun, dar nu a fost asa. Este o carte scurta, cu font mare si multe, multe greseli.
Singura parte buna este ca la fiecare capitol exista intrebari. In afara de asta nu este o resursa prea buna si in mod sigur nu valoreaza 20$, probabil 5$ era mai aproape de realitate, avand in vedere ca de la o versiune la alta doar au actualizat-o doar cate putin si doar au adaugat noile schimbari si aditii din limbaj. Nici macar intrebarile nu par sa se schimbe prea mult in timp.
Asa ca daca vei cumpara o singura carte, mai bine sa o cumperi pe urmatoarea.
PHP 7 Zend Certification Study Guide – Andrew Beak – Apress 2017 – 19.99$
Cartea analizeaza in mai mult detaliu toate sectiunile din certificare, are peste 300 de pagini.
Aceasta carte arata mai mult ca o carte de programare decat un ghid. Calitatea cartii este mult mai buna decat cea a ghidului oficial, dar asta nu e dificil daca luam in considerare cat de slaba este calitatea aceluia.
Si in aceasta carte sunt intrebari dupa fiecare capitol, lucru util pentru a-ti testa cunostintele intr-un format apropiat examenului. Totusi intrebarile par un pic mai “blande” decat ghidul, examenul in sine are multe intrebari foarte “tricky”.
Evident acest ghid nu este chiar complet, nu poti avea cu adevarat un ghid care sa trateze absolut toate detaliile intr-o singura carte si, chiar daca ar exista, probabil nu ai avea timp sa o citesti.
Daca vei cumpara o singura carte, recomandarea mea este sa o iei pe aceasta, pentru ca este o carte, nu doar un ghid la nivel foarte inalt (si calitate joasa).
Zend PHP 5 Certification Study Guide, Third Edition – php[architect] – 22$
Daca ai impresia ca am gresit versiunea, ce pot spune? Ai dreptate!
Am vrut sa adaug si aceasta carte la lista pentru ca, pentru mine, a fost cel mai bun ghid de studiu. De-a lungul anilor au fost mai multe ghiduri, dar acesta mi-a placut cel mai mult.
Pentru certificarea de PHP 5 nu exista un ghid oficial de la Zend, doar prima editie din aceasta carte. A fost o carte de programare interesant de citit. Uneori cand vreau sa-mi reamintesc ceva ce nu am mai folosit de multa vreme, sau deloc, citesc capitolul din aceasta carte.
Cand am dat examenul pentru certificarea de PHP 5.5 (pentru ca a trebuit sa le am pe toate), am fost placut surprins sa aflu ca exista o noua versiune a aceastei carti.
Este in esenta aceeasi carte, dar actualizata pentru noua certificare. Poate doar imi place mine stilul de a scrie al lui Davey Shafik.
Cartea imi da senzatia ca e mai plina de informatii, mi se pare ca aduce mai mult cu un ghid de studiu decat cartea precedenta.
Totusi, aceasta carte nu are intrebari si nu mai este de actualitate.
Daca ai timp, poti sa o citesti oricum, eu o consider o carte buna de PHP.
Concluzii
Nu exista prea multe carti pentru aceasta vertificare, dar daca ar trebui sa aleg o singura recomandare, probabil ar fi: “PHP 7 Zend Certification Study Guide” de la Apress.
Din pacate nu prea exista competitie, pentru ca “Zend PHP 5 Certification Study Guide, Third Edition” de la PHP Arch nu mai este de actualitate, iar ghidul oficial pur si simplu nu valoreaza 20$.
Daca seful tau iti cumpara cartile, eu sugerez sa le iei pe toate! Pana la urma costa: 20$ + 19.99$ + 22$ = 61.99$! Nu e rau pentru trei carti de programare!
-
Da, PHP este probabil cel mai popular limbaj de programare server side pentru Web in acest moment. Si probabil va ramane asa pentru o vreme indelungata.
Este probabil cel mai bun!
Nu tocmai, dar nu te opri din citit…
De ce este atat de usor de invatat?
In primul rand, datorita sintaxei. Dar motivul pentru care este asa de popular nu este pentru ca ar avea cea mai buna sintaxa! Eu am inteles aproape imediat sintaxa cand am vazut primul exemplu de “hello world”, de ce? Pentru ca am studiat C la scoala, iar persoanele care vin din lumea Java au aceeasi senzatie.
Dar sa vedem cateva limbaje de programare care folosesc aceasta sintaxa: Java, C#, JavaScript, Perl, Go, PHP si, bineinteles, C si C++, adica aproape toate platformele si cam toata piata.
Dar spre deosebire de (majoritatea) limbajelor listate mai sus, este cel mai simplu pentru incepatori! Nu trebuie sa creezi o functie “main”, o clasa sau altceva, incepi direct!
Partea buna este ca poate sa fie atat de complex pe cat vrei sau cat ai nevoie. Acum exista clase si interfete similare cu Java, mostenire orizontala cu “traits”, programare functionala cu closures si functii anonime, generatori, iar, daca esti cu adevarat hipster, pana si goto!
Dar PHP nu suna chiar asa de rau…
Dar trebuie sa amintim un detaliu foarte important: PHP nu a devenit popular datorita caracteristicilor de mai sus, in schimb caracteristicile au aparut datorita popularitatii, chiar si “goto”. Nu inteleg de ce cineva ar adauga goto intr-un limbaj dupa mai bine de 10 ani de existenta, dar asta nu este treaba mea si nici nu este relevant pentru acest subiect.
Limbajul a devenit foarte popular cu versiunile 3 si 4. Pana cand a aparut un model decent de OOP era deja foarte popular! In special acum, de cand cu versiunea PHP 7, cand arata mult mai mult ca un limbaj decent de programare, dar acum 10 ani nu era aceeasi poveste.
Dar node.js probabil il va depasi!
Sigur ca da… va amintiti de Ruby? Python? Si altele…
Daca te gandesti la PHP, are un mare avantaj si dezavantaj totodata, este cat de “stateless” se poate.
Cu PHP ai impresia ca nu stii nimic despre lume, trebuie sa faci bootstrap (initializezi) totul de fiecare data. Avantajul este ca in cazul unui memory leak, in majoritatea cazurilor, este ok. Cand requestul se termina totul se va curata/elibera si nimanui nu-i va mai pasa. Si PHP avea multe memory leak-uri la inceput, pana sa devina foarte popular si nimanui nu parea sa-i pese.
Cand au inceput sa apara cron job-urile si alte procese de lunga durata, abia atunci a devenit o mare problema si a aparut nevoia de garbage collection explicit. Acesta a fost adaugat in versiunea 5.3 care aparut abia in 2009.
In mod normal, un proces care ruleaza continuu nu ar trebui sa fie un dezavantaj, dar morala povestii este ca nu este neaparat nici avantaj.
Nimeni nu va construi urmatorul Google cu el, dar macar niste blog-uri? Sau, si mai bine, niste magazine virtuale?
Nu este capabil de ceva precum motorul de cautare Google, si e ok pentru ca nu a fost facut pentru asta.
Un alt exemplu pentru “nu neaparat cel mai bun castiga” este ca WordPress este cea mai populara platforma de blogging.
Chiar mai mult, lumea foloseste WordPress in tot felul de moduri bizare, practic poti face orice cu el! Si nu ar trebui sa reporosam asta oamenilor care il folosesc, nu e ca si cum te uiti la ce piese sunt in cuptorul cu microunde atunci cand il cumperi, nu-ti doresti decat sa incalzeasca mancarea. Oamenii care forteaza limitele platformei WordPress fac la fel, ei pot sa faca ce au nevoie si nu exista un motiv bun pentru care sa nu o faca.
Ar trebui sa-l folosesc?
Sa luam doua exemple pozitive: Yahoo! si Facebook.
Yahoo! il foloseste de foarte mult timp in unele din produsele sale si, uneori, intr-o combinatie cu alte limbaje de programare.
Facebook l-a folosit de la inceput pentru ca este usor de invatat. Ei au impins limitele limbajului in mai multe randuri prin: HipHop for PHP si, mai recent, Hack, care a reprezentat si cea mai importanta motivatie din spatele PHP 7.
De ce atata deranj pentru un limbaj de programare? Pentru ca este usor de invatat si utilizat!
De obicei, este mai important sa lansezi “acum” decat sa ai ceva “perfect” mai tarziu, mai ales in universul world wide web.Este un motiv foarte bun pentru care un limbaj care nu este in mod sigur “cel mai bun”, dar este usor de folosit este atat de popular online, in timp ce un limbaj de programare ca C, care este mult mai dificil de invatat, este atat de popular offline.
Cu alte cuvinte, chiar daca PHP nu este cel mai bun, este in general suficient de bun.