-
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!
-
De ceva mai bine de un an de zile am inceput sa lucrez pe platforma Magento. In primavara anului trecut, un coleg de la Optaros si-a dat examenul de certificare pentru Magento Developer Plus. De atunci a inceput sa-mi placa ideea de a da certificarea, mai mult ca sa ma motiveze sa invat dedesubturile Magento.
Acum cateva luni am fost inscris intr-un grup de studiu pentru certificare in cardul companiei. Aceasta a fost prima data cand am fost sponsorizat pentru o certificare (da, pana acum totul a fost pe banii mei). Sa te pregatesti in cadrul unui grup a fost o cu totul alta experienta.
Cei care au mai multa experienta intr-un anumit domeniu echilibreaza situatia pentru ceilalti si pot oferi explicatii mai bune din propria lor experienta. E mai usor sa intelegi cand ai exemple concrete, decat sa incerci sa-ti imaginezi scenarii.
Certificarea este disponibila prin Prometric. Deci, cand te-ai hotarat, poti intra pe site sa cumperi un voucher si sa iti programezi examenul.
Pretul unui voucher este de 260$, nu foarte mic, dar daca reusesti sa-ti convingi seful sa il plateasca, probabil nu va fi asa grav. 🙂
Dar sa trecem la subiectul mai interesant, pregatirea.
Materiale
Magento nu sta prea bine la subiectul asta, materialele sunt putine si nu sunt centralizate.Sursele mele au fost:
– Magento® Certified Developer Plus Exam Study Guide – e imperativ sa citesti ghidul si sa incerci sa gasesti raspunsurile la toate intrebarile.
– Magento training – in special Fundamentals of Magento Development
– bloguri – nu vreau sa dau nume, sunt multe si multi care scriu despre problemele pe care le intalnesc si care povestesc despre ce este examenul.Din pacate nu ai modalitatea, cum este la PHP, ZF sau Symfony, sa gasesti cam tot ce ai nevoie intr-un singur loc. Practic, depinde de noroc si skilluri de cautare, nu exista mereu o “varianta oficiala”. Lucrurile devin mai ciudate cand gasesti mai multe abordari in functie de versiune.
Cum m-am pregatit eu
Am inceput cu trainingul video. Nu este perfect, dar ajuta mult. Cred ca problema pentru majoritatea certificarilor este ca nu lucrezi cu toate modulele disponibile, la fel cum in PHP nu ai posibilitatea sa lucrezi prea mult cu socketuri si streamuri.Chiar daca nu primesti codul si uneori sunt greu de urmarit si transcris exemplele, cred ca tutorialele video sunt una dintre cele mai importante surse in momentul actual.
In al doilea rand, cu Study Guide-ul in mana, am inceput sa incerc sa raspund la intrebarile din el. Cand am intrat in study group, munca s-a impartit la toti cei din grup. Avantajul meu a fost ca era a doua generatie de grup si am putut profita de documentatia deja construita de primul grup.
Daca te pregatesti singur, cred ca cel mai important este sa incepi, este cel mai greu pas. Iar daca nu stii de unde sa incepi, cauta pe Google intrebarile din Magento, sunt multi care au scris deja explicatiile.
Cel mai usor se gasesc raspunsuri pentru intrebarile de la primele capitole. Pe masura ce numarul capitolului creste si rezultatele pe Google scad.
Dar dupa primele intrebari ar trebui sa intelegi despre ce este vorba si teoretic nu vei mai avea nevoie de documentatie.
Foloseste Mage::log(Varien_Debug::backtrace(true, false)); pentru stack trace si xdebug (http://xdebug.org/) pentru a urmari ce se intampla in spate.
Cu rabdare, toate intrebarile isi gasesc raspunsul.Pentru ca a fost un grup, studiul a fost mult mai usor pentru mine, dar chiar si asa, pentru a fi sigur de raspuns am studiat adanc in cod.
Examenul
Unele intrebari sunt dificile, dar sunt si intrebari accesibile. Cam toate gradele de dificultate se intalnesc in examen.Pentru Plus, examenul dureaza 2h, nu 2.5h, cum scrie in guide.
Daca optezi pentru Plus, exista 11 intrebari de Enterprise si de dificulatate mai ridicata, din care trebuie sa rezolvi 7 corect, practic in asta consta diferenta de dificultate. Aici conteaza cata experienta ai pe Enterprise.
In fiecare ghid subiectele sunt defalcate procentual pe capitole.
Pentru ca la certificarea fara Plus nu exista intrebari de Enterprise inseamna ca trebuie raspunzi doar la procentul necesar ca sa iei examenul, nu sa faci un minim pentru un anumit capitol.
Lucrurile care se fac in mod uzual sunt studiate in amanunt, e important sa intelegi cum functioneaza fiecare functie pe care se pune accentul din fiecare modul si ce fac toate tag-urile din fisierele xml.
In general sunt lucruri cu care lucrezi, sau mai bine zis cu care este o probabilitate buna sa lucrezi din modulele listate in ghid.
Dupa examen
Inainte sa iesi din sala vei afla daca ai trecut sau nu. Cand iesi din sala vei primi o hartie cu numarul de intrebari corecte din totalul de intrebari pe fiecare sectiune.In cazul in care nu ai avut succes, vei primi de la Magento un mail cu un voucher cu o reducere pentru o ulterioara incercare. Ei spun ca ar trebui sa mai studiezi cam 3 saptamani inainte de a incerca din nou. Oricum, dupa ce ai dat examenul o sa ai o viziune mai buna daca esti pregatit sau nu pentru o noua incercare.
Dupa cateva zile (cred ca 3 in cazul meu) vei putea sa-ti vezi si profilul pe site-ul Magento, pentru referinta.
Diploma ajunge cam intr-o luna in Romania, la adresa care este trecuta pe site-ul Magento.
Multa bafta!
-
Uneori trebuie sa suprascriem un observator (observer). Prima metoda care vine in general in minte este suprascrierea modelului. In general se numeste Observer.php, pentru ca aceasta este “best practice”.
Dar NU, nu trebuie suprascris modelul. Oricum Observer.php nu extinde nimic si in general contine toti observatorii pentru modul, deci nu poti suprascrie in mai multe module acelasi observer.
Cum functioneaza?
In magento cand se adauga un nou observer, acesta trebuie sa aiba un identificator unic. Acest identificator este cheia!De fapt, mai este un element: “zona”. Cand se face Mage::dispatchEvent(…) se vor rula evenimentele dupa “zona” si dupa “identificator”.
De exemplu sistemul de notificari din admin, care se leaga de evenimentul “controller_action_predispatch”, va rula:
1=> "global"(zona) 2=> "controller_action_predispatch"(event) 3=> "adminnotification"(identificator)
apoi:
1=> "adminhtml"(zona) 2=> "controller_action_predispatch"(event) 3=> "adminnotification"(identificator)
Daca era vorba de un event in frontend, ar fi fost: “global” apoi “frontend”.
Suprascrierea
Suprascrierea, de fapt, consta intr-un observer definit in aceeasi zona de config ca evenimentul initial(global, frontend sau adminhtml), atasat la acelasi eveniment si cu acelasi identificator cu cel initial (ex: adminnotification).Sa zicem ca trebuie sa suprascriem “adminnotification”. Acest observer se afla in modulul Mage/AdminNotification. Identificatorul unic este in etc/config.xml:
1... 2 <adminhtml> 3... 4 <events> 5 <controller_action_predispatch> 6 <observers> 7 <adminnotification> 8 <class>adminnotification/observer</class> 9 <method>preDispatch</method> 10 </adminnotification> 11 </observers> 12 </controller_action_predispatch> 13 </events> 14... 15 </adminhtml> 16...
Din exemplul de mai sus putem vedea:
– zona: adminhtml
– event: controller_action_predispatch
– identificator: adminnotificationFisierul de activare a modulului va fi: app/etc/modules/CP_AdminNotification.xml
1<?xml version="1.0"?> 2<config> 3 <modules> 4 <CP_AdminNotification> 5 <active>true</active> 6 <codePool>local</codePool> 7 <depends> 8 <Mage_AdminNotification/> 9 </depends> 10 </CP_AdminNotification> 11 </modules> 12</config>
Am adaugat si dependinte pentru ca fara acel modul, modulul de fata este iuntil.
Este “best practice” sa denumesti un modul suprascris la fel ca modulul initial.
Fisierul de configurare pentru modul va contine practic tot ce avem nevoie pentru suprascriere: zona, event si identificator. Fisierul se afla in app/code/local/CP/AdminNotification/etc/config.xml:
1<?xml version="1.0"?> 2<config> 3 <modules> 4 <CP_AdminNotification> 5 <version>0.0.1</version> 6 </CP_AdminNotification> 7 </modules> 8 <global> 9 <models> 10 <cp_adminnotification> 11 <class>CP_AdminNotification_Model</class> 12 </cp_adminnotification> 13 </models> 14 </global> 15 <adminhtml> 16 <events> 17 <controller_action_predispatch> 18 <observers> 19 <adminnotification> 20 <class>cp_adminnotification/observer</class> 21 <method>overwrittenPreDispatch</method> 22 </adminnotification> 23 </observers> 24 </controller_action_predispatch> 25 </events> 26 </adminhtml> 27</config>
Observerul ar trebui sa contina noua logica. Fisierul este in app/ code/local/CP/AdminNotification/Model/Observer.php, asa cum era si evident, dupa structura de mai sus.
1<?php 2 3class CP_AdminNotification_Model_Observer { 4 5 public function overwrittenPreDispatch(Varien_Event_Observer $observer) { 6 // noua logica din observer 7 } 8}
Dezactivarea
Dezactivarea este destul de similara cu suprascrierea, diferenta este in config si faptul ca nu mai este nevoie de un fisier observer, pentru ca nu mai exista o noua logica.Noul fisier de config.xml este:
1<?xml version="1.0"?> 2<config> 3... 4 <adminhtml> 5 <events> 6 <controller_action_predispatch> 7 <observers> 8 <adminnotification> 9 <type>disabled</type> 10 </adminnotification> 11 </observers> 12 </controller_action_predispatch> 13 </events> 14 </adminhtml> 15</config>
-
Acesta nu este un tutorial despre cum se seteaza o regula de tip Shopping Cart Price Rule in Magento, dar despre cum se implementeaza una noua.
Un tip nou de regula in Magento presupune doua lucuri:
– modificarea admin-ului pt a adauga noua regula folosind un observer pentru adminhtml_block_salesrule_actions_prepareform,
– un mod de aplicare pentru noua regula folosind un observer pentru salesrule_validator_process.Sa luam un exemplu. Sa zicem ca exista o regula de tip Shopping Cart Price Rule care ofera discount diferit in functie de numarul de produse din cos. Se va calcula o valoare de incrementare pentru fiecare pas ($step). Primul produs nu va primi nici un discount, al doilea produs va primi un discount de $step, al doilea produs un discount de 2*$step, pana se ajunge la valoarea maxima de discount. Urmatoarele produse vor avea discount maxim. Ex:
Discount Amount = 50
Discount Qty = 5
Step = Discount Amount / Discount Qty = 10Discountul rezultat:
– 0% prod 1
– 10% prod 2
…
– 50% prod 6
– 50% prod 7Primul pas este activarea modulului cu fisierul: app/etc/modules/CP_ProductNrDiscount.xml
1<?xml version="1.0" encoding="UTF-8"?> 2<config> 3 <modules> 4 <CP_ProductNrDiscount> 5 <active>true</active> 6 <codePool>local</codePool> 7 </CP_ProductNrDiscount> 8 </modules> 9</config>
Primul observer, adminhtml_block_salesrule_actions_prepareform, trebuie sa fie in config in zona “adminhtml”, pentru ca se va aplica admin-ul. Acest observer are acces la formularul din admin, permitand modificarea acestuia.
Al doilea observer, salesrule_validator_process, poate sa fie in zona de “frontend” sau “global” din config. Daca este in “frontend” se va aplica doar in partea de frontend, daca este in global acesta se va aplica si in backend daca este nevoie. In general global este necesar atunci cand se fac operatiuni pe cart din backend.
1<?xml version="1.0" encoding="UTF-8"?> 2<config> 3 <modules> 4 <CP_ProductNrDiscount> 5 <version>0.0.1</version> 6 </CP_ProductNrDiscount> 7 </modules> 8 <global> 9 <models> 10 <productnrdiscount> 11 <class>CP_ProductNrDiscount_Model</class> 12 </productnrdiscount> 13 </models> 14 <events> 15 <salesrule_validator_process> 16 <observers> 17 <productnrdiscount> 18 <type>model</type> 19 <class>productnrdiscount/observer</class> 20 <method>salesruleValidatorProcess</method> 21 </productnrdiscount> 22 </observers> 23 </salesrule_validator_process> 24 </events> 25 </global> 26 <adminhtml> 27 <events> 28 <adminhtml_block_salesrule_actions_prepareform> 29 <observers> 30 <productnrdiscount> 31 <type>model</type> 32 <class>productnrdiscount/observer</class> 33 <method>adminhtmlBlockSalesruleActionsPrepareform</method> 34 </productnrdiscount> 35 </observers> 36 </adminhtml_block_salesrule_actions_prepareform> 37 </events> 38 </adminhtml> 39</config>
Al doilea observer trebuie sa fie atasat la “frontend” sau “global”, daca trebuie sa ruleze doar in frontend sau si in backend.
Asa cum se poate vedea mai sus, trebuie facut un model Observer care sa aiba cele doua metode care modifica admin-ul si aplica discountul.
1<?php 2/** 3 * Number of product discount module 4 * 5 * @author Claudiu Persoiu https://blog.claudiupersoiu.ro 6 */ 7class CP_ProductNrDiscount_Model_Observer { 8 9 // Noul tip de regula 10 const PRODUCT_NR_DISCOUNT = 'product_nr_discount'; 11 12 /** 13 * Adaugare nou tip de regula in meniul de administrare 14 * 15 * @param Varien_Event_Observer $observer 16 */ 17 public function adminhtmlBlockSalesruleActionsPrepareform 18 (Varien_Event_Observer $observer) { 19 // Extragem campul din formular 20 $field = $observer->getForm()->getElement('simple_action'); 21 // Extragem valorile campului 22 $options = $field->getValues(); 23 // Adaugam noua valoare 24 $options[] = array( 25 'value' => self::PRODUCT_NR_DISCOUNT, 26 'label' => 'Product Number Discount' 27 ); 28 // Setare camp 29 $field->setValues($options); 30 } 31 32 /** 33 * Aplicare discount 34 * Discountul se va aplica la minim 2 produse progresiv cate un "step" pentru 35 * fiecare produs, unde un "step" este discountul maxim / numarul de produse 36 * pe care se aplica. 37 * 38 * @param Varien_Event_Observer $observer 39 */ 40 public function salesruleValidatorProcess(Varien_Event_Observer $observer) { 41 42 // $item typeof Mage_Sales_Model_Quote_Item 43 $item = $observer->getEvent()->getItem(); 44 // $rule typeof Mage_SalesRule_Model_Rule 45 $rule = $observer->getEvent()->getRule(); 46 47 // Numarul de produse de acest fel 48 $qty = $item->getQty(); 49 50 // Trebuie verificat ce tip de regula este, pentru a izola tipul 51 // nostu de regula 52 if($rule->getSimpleAction() == self::PRODUCT_NR_DISCOUNT && $qty > 1) { 53 54 // Detalii regula 55 $discountAmount = $rule->getDiscountAmount(); 56 $discountQty = $rule->getDiscountQty(); 57 58 // Step de discount 59 $step = $discountAmount/$discountQty; 60 61 // Calcul discount 62 $discount = 0; 63 for($i = 1; $i < $qty; $i++) { 64 $itemDiscount = $i * $step; 65 // Daca discountul este mai mare decat discountul maxim 66 // atunci se foloseste discount maxim 67 if($itemDiscount > $discountAmount) { 68 $itemDiscount = $discountAmount; 69 } 70 71 $discount += $itemDiscount; 72 } 73 74 // Discountul propriuzis 75 $totalDiscountAmount = ($item->getPrice() * $discount)/100; 76 77 // Discount in procente pentru fiecare quote item 78 $item->setDiscountPercent($discount / $qty); 79 80 // Setare discount efectiv, practic aceasta este valoarea de discount 81 $result = $observer->getResult(); 82 $result->setDiscountAmount($totalDiscountAmount); 83 $result->setBaseDiscountAmount($totalDiscountAmount); 84 85 } 86 } 87 88}
Acest observer se va aplica la fiecare request cand exista module in cart pentru care se aplica regula. Daca discountul trebuie sa se aplice doar pentru anumite produse acestea se pot filtra folosind sesiunea de “Conditions” a regulii definite, asa cum este normal.
-
Exista momente cand ai nevoie sa vezi stack trace-ul, sa stii cum ai ajuns pana la un anumit punct. PHP are doua functii native pentru a realiza acest lucru: debug_backtrace() si debug_print_backtrace. Prima intoarce un array iar a doua afisaza stacktrace-ul pe ecran.
Problema in sine este ca acestea trebuie customizate pentru Magento, pentru ca este foarte posibil cand rulezi debug_backtrace() sa ramai fara memorie inainte sa poti trimite rezultatul catre un fisier de log.
Magento are o functie nativa pentru acest lucru: Varien_Debug::backtrace([bool $return = false], [bool $html = true], [bool $withArgs = true]). Pentru a trimite catre log stacktrace-ul se apeleaza pur si siplu:
1Mage::log(Varien_Debug::backtrace(true, false));
Aceasta tehnica este foarte utila in momentul in care vrei sa vezi de unde se initializeaza anumite obiecte si ce metode se ruleaza pana in acel moment.