Claudiu Persoiu

Blog-ul lui Claudiu Persoiu


Archive for the ‘Magento’ tag

Magento2 si crudul adevar

without comments

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!

Written by Claudiu Persoiu

31 March 2020 at 4:24 PM

Posted in Magento,PHP

Tagged with , ,

Passing Magento Developer Plus certification

with 3 comments

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!

Written by Claudiu Persoiu

16 February 2013 at 8:23 PM

Posted in Magento,PHP

Tagged with , , ,

Suprascriere si dezactivare Observere in Magento

with 2 comments

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:

=> "global"(zona)
=> "controller_action_predispatch"(event)
=> "adminnotification"(identificator)

apoi:

=> "adminhtml"(zona)
=> "controller_action_predispatch"(event)
=> "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:

...
  <adminhtml>
...
    <events>
      <controller_action_predispatch>
        <observers>
          <adminnotification>
            <class>adminnotification/observer</class>
            <method>preDispatch</method>
          </adminnotification>
        </observers>
      </controller_action_predispatch>
    </events>
...
  </adminhtml>
...

Din exemplul de mai sus putem vedea:
– zona: adminhtml
– event: controller_action_predispatch
– identificator: adminnotification

Fisierul de activare a modulului va fi: app/etc/modules/CP_AdminNotification.xml

<?xml version="1.0"?>
<config>
  <modules>
    <CP_AdminNotification>
      <active>true</active>
      <codePool>local</codePool>
      <depends>
        <Mage_AdminNotification/>
      </depends>
    </CP_AdminNotification>
  </modules>
</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:

<?xml version="1.0"?>
<config>
  <modules>
    <CP_AdminNotification>
      <version>0.0.1</version>
    </CP_AdminNotification>
  </modules>
  <global>
    <models>
      <cp_adminnotification>
        <class>CP_AdminNotification_Model</class>
      </cp_adminnotification>
    </models>
  </global>
  <adminhtml>
    <events>
      <controller_action_predispatch>
        <observers>
          <adminnotification>
            <class>cp_adminnotification/observer</class>
            <method>overwrittenPreDispatch</method>
          </adminnotification>
        </observers>
      </controller_action_predispatch>
    </events>
  </adminhtml>
</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.

<?php

class CP_AdminNotification_Model_Observer {

  public function overwrittenPreDispatch(Varien_Event_Observer $observer) {
    // noua logica din observer
  }
}

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:

<?xml version="1.0"?>
<config>
...
  <adminhtml>
    <events>
      <controller_action_predispatch>
        <observers>
          <adminnotification>
            <type>disabled</type>
          </adminnotification>
        </observers>
      </controller_action_predispatch>
    </events>
  </adminhtml>
</config>

Written by Claudiu Persoiu

17 May 2012 at 9:59 PM

Posted in Magento,PHP

Tagged with ,

Magento – Create a custom shopping cart price rule

with 2 comments

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 = 10

Discountul rezultat:
– 0% prod 1
– 10% prod 2

– 50% prod 6
– 50% prod 7

Primul pas este activarea modulului cu fisierul: app/etc/modules/CP_ProductNrDiscount.xml

<?xml version="1.0" encoding="UTF-8"?>
<config>
    <modules>
        <CP_ProductNrDiscount>
            <active>true</active>
            <codePool>local</codePool>
        </CP_ProductNrDiscount>
    </modules>
</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.

<?xml version="1.0" encoding="UTF-8"?>
<config>
    <modules>
        <CP_ProductNrDiscount>
            <version>0.0.1</version>
        </CP_ProductNrDiscount>
    </modules>
    <global>
        <models>
            <productnrdiscount>
                <class>CP_ProductNrDiscount_Model</class>
            </productnrdiscount>
        </models>
        <events>
            <salesrule_validator_process>
                <observers>
                    <productnrdiscount>
                        <type>model</type>
                        <class>productnrdiscount/observer</class>
                        <method>salesruleValidatorProcess</method>
                    </productnrdiscount>
                </observers>
            </salesrule_validator_process>
        </events>
    </global>
    <adminhtml>
        <events>
            <adminhtml_block_salesrule_actions_prepareform>
            <observers>
                <productnrdiscount>
                    <type>model</type>
                    <class>productnrdiscount/observer</class>
                <method>adminhtmlBlockSalesruleActionsPrepareform</method>
                </productnrdiscount>
            </observers>
            </adminhtml_block_salesrule_actions_prepareform>
        </events>
    </adminhtml>
</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.

<?php
/**
 * Number of product discount module
 *
 * @author Claudiu Persoiu http://blog.claudiupersoiu.ro
 */
class CP_ProductNrDiscount_Model_Observer {

    // Noul tip de regula
    const PRODUCT_NR_DISCOUNT = 'product_nr_discount';

    /**
     * Adaugare nou tip de regula in meniul de administrare
     *
     * @param Varien_Event_Observer $observer
     */
    public function adminhtmlBlockSalesruleActionsPrepareform
              (Varien_Event_Observer $observer) {
        // Extragem campul din formular
    	$field = $observer->getForm()->getElement('simple_action');
        // Extragem valorile campului
        $options = $field->getValues();
        // Adaugam noua valoare
        $options[] = array(
            'value' => self::PRODUCT_NR_DISCOUNT,
            'label' => 'Product Number Discount'
        );
        // Setare camp
        $field->setValues($options);
    }

    /**
     * Aplicare discount
     * Discountul se va aplica la minim 2 produse progresiv cate un "step" pentru
     * fiecare produs, unde un "step" este discountul maxim / numarul de produse
     * pe care se aplica.
     *
     * @param Varien_Event_Observer $observer
     */
    public function salesruleValidatorProcess(Varien_Event_Observer $observer) {

        // $item typeof Mage_Sales_Model_Quote_Item
        $item = $observer->getEvent()->getItem();
        // $rule typeof Mage_SalesRule_Model_Rule
        $rule = $observer->getEvent()->getRule();

        // Numarul de produse de acest fel
        $qty = $item->getQty();

        // Trebuie verificat ce tip de regula este, pentru a izola tipul
        // nostu de regula
        if($rule->getSimpleAction() == self::PRODUCT_NR_DISCOUNT && $qty > 1) {

            // Detalii regula
            $discountAmount = $rule->getDiscountAmount();
            $discountQty = $rule->getDiscountQty();

            // Step de discount
            $step = $discountAmount/$discountQty;

            // Calcul discount
            $discount = 0;
            for($i = 1; $i < $qty; $i++) {
			    $itemDiscount = $i * $step;
                // Daca discountul este mai mare decat discountul maxim
                // atunci se foloseste discount maxim
                if($itemDiscount > $discountAmount) {
                    $itemDiscount = $discountAmount;
                }

                $discount += $itemDiscount;
            }

            // Discountul propriuzis
            $totalDiscountAmount = ($item->getPrice() * $discount)/100;

            // Discount in procente pentru fiecare quote item
            $item->setDiscountPercent($discount / $qty);

            // Setare discount efectiv, practic aceasta este valoarea de discount
            $result = $observer->getResult();
            $result->setDiscountAmount($totalDiscountAmount);
            $result->setBaseDiscountAmount($totalDiscountAmount);

        }
    }

}

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.

Written by Claudiu Persoiu

8 March 2012 at 9:37 PM

Magento native stack trace

with 5 comments

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:

Mage::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.

Written by Claudiu Persoiu

25 February 2012 at 11:48 AM

Posted in Magento,PHP

Tagged with , , ,

Magento dead end – Breadcrumbs

without comments

Intr-una din aventurile mele prin codul Magento, m-am lovit de urmatoarea problema: trebuia sa adaug un link la breadcrumb.

Cum documentatia nu e foarte bogata, dupa putin debug-ing (nu foarte mult), am ajuns in core la Mage_Page_Block_Html_Breadcrumbs.

Metoda este foarte auto-explicativa: addCrumb($crumbName, $crumbInfo, $after = false). Daca tot eram acolo am zis sa arunc un ochi in ea:

function addCrumb($crumbName, $crumbInfo, $after = false)
{
  $this->_prepareArray($crumbInfo, array('label', 'title', 'link', 'first', 'last', 'readonly'));
  if ((!isset($this->_crumbs[$crumbName])) || (!$this->_crumbs[$crumbName]['readonly'])) {
    $this->_crumbs[$crumbName] = $crumbInfo;
  }
  return $this;
}

Ce este interesant este parametul $after, dupa cum se poate observa, desi are chiar si o valoare default, nu se foloseste nicaieri. In rest functia functioneaza asa cum este de asteptat, probabil de asta nu se plange lumea atat de des.

Written by Claudiu Persoiu

3 February 2012 at 10:03 PM

Posted in Magento,PHP

Tagged with ,

A mai trecut un an iar PHP 6 ramane un mit – retrospectiva 2011

without comments

A devenit o traditie pentru mine sa incep retrospectiva anuala cu acest subiect.

PHP 6 este la fel de aproape de lansare cum era si anul precedent, sau acum doi ani, adica lipsit de perspectiva. In 2011, PHP 5.4 a ajuns la RC4 si probabil se va lansa in curand versiunea finala, lucru care inseamna ca inca nu se previzioneaza o data pentru lansarea PHP 6. Dar despre PHP 5.4 cu alta ocazie, este pe lista mea de “TODO” sa vad ce a ajuns in RC4.

Cum in PHP 5.3 cuvintele cheie pentru mine au fost namespaces, Anonymous functions, closures si garbage collector, in PHP 5.4 se pare ca aceste cuvinte cheie vor fi traits, din nou closures si scalar type hinting, alaturi de multe alte noutati.

Cand am scris primul meu blog anual despre PHP 6, lucram in principal la site-uri in romana, de acolo si dorinta mea pentru o versiune care sa suporte in mod nativ aceasta limba sau oricare alta fara nici o modificare. Pe atunci lucram in cea mai mare parte direct cu limbajul, de cele mai multe ori fara sa folosesc un framework . Dar de atunci a trecut mult timp si mutle lucruri s-au schimbat, acum folosesc aproape exclusiv framework-uri si platforme care m-au indepartat de limbaj oferindu-mi o noua perspectiva arhitecturala.

Dupa mai bine de un an in cadrul NCH, am decis ca este timpul pentru o schimbare. Si de data asta este vorba tot de o corporatie venita din state cu o sucursala in Romania. De data asta este vorba de Optaros. Desi nu intentionam sa-mi schimb locul de munca, am dat curs unei invitatii la interviu si pe scurt, am plecat. De mult simteam nevoia sa lucrez din nou pentru clienti externi, dupa experienta NCH unde toate proiectele erau interne, simteam nevoia de o schimbare.

Din nou proiectele sunt si mai mari, cu alte probleme de scalabilitate. Dar cred ca asta face web development-ul atat de interesant, cu cat ai probleme mai mari de scalabilitate, cu atat inseamna ca lucrezi la un proiect mai mare.

Anul trecut cuvintele cheie au fost Linux si Symfony framework. Pentru anul care tocmai s-a incheiat cuvintele cheie probabil au fost: Magento si Drupal.

Dupa o scurta perioada de lucru cu Magento, pot spune ca mi se pare incredibil cum o platforma atat de mare are atat de putina documentatie si de multe ori atat de multa inconsistenta. Este o plaforma foarte complexa cu care poti face foarte multe lucruri, dar cand vine vorba de documentatie, se pare ca abordarea se rezuma la a analiza core-ul. Venind din lumea Symfony, unde exista literalmente carti intregi de documentatie, puse la dispozitie in mod gratuit, mi se pare incredibil cat de putina si descentralizata documentatie este pentru Magento. Dar de asemenea este un subiect pentru un alt blog. Cred ca aici echipa Optaros m-a ajutat destul de mult ca sa inteleg cum sa abordez problemele.

Un alt eveniment important pentru mine acest anul trecut a fost Yahoo! Open Hack Day, eveniment tinut si in Romania in 2011. Nu stiu daca am mai vazut atata entuziasm si energie intr-un singur loc, intr-o singura zi. Pentru mine ca programator a fost o experienta de neuitat, unul din momentele care m-au facut sa-mi aduc aminte de ce am ales aceasta profesie.

In acest an am dat si examenul de certificare pentru PHP 5.3, chiar la inceptului anului. Examenul nu a fost atat de greu cum ma asteptam, desi se pare ca emotiile raman neschimbate. Faptul ca am mai sustinut un examen m-a ajutat mult, incredibil cat de multe lucruri iti aduci aminte cand le recitesti. Anul trecut mi-am propus sa sustin cel putin un examen de certificare pe an, deci trebuie sa incep pregatirile pentru urmatorul examen.

Concluzionand, 2011 a fost un an bun, plin de realizari si provocari, chiar daca nu am bifat foarte multe lucruri pe rezolutia de an, am realizat si multe lucruri care nu erau pe ea. Dar acum este timpul pentru o noua rezolutie de an.

Iar acum va urez un 2012 mai bun si mai plin de realizari! La multi ani!

Written by Claudiu Persoiu

3 January 2012 at 4:45 PM

Posted in Diverse

Tagged with , , , ,