Creazione di un Modulo di Magento

                      
                        
    

Creazione di un Modulo di Magento

Magento mette a disposizione una serie di tecniche per implementare funzioni al proprio codice. Tutto questo è molto utile ogni volta che avete bisogno di creare personalizzazioni molto particolari, come ad esempio se è necessario creare una pagina 404 che restituisca alcuni prodotti correlati in funzione del nome della pagina.

I moduli di Magento sono notevolmente più complicati da sviluppare rispetto ad altre piattaforme, ma ovviamente, se conosciamo adeguatamente la piattaforma, avremo la possibilità di ottenere risultati esaltanti.

Le estensioni posseggono delle proprietà dinamiche che permettono a magento di caricare i moduli tramite la combinazione di file/cartelle che sono contenute in locazioni specifiche del codice.

I moduli posso essere allocati nella cartella app/code/local oppure in app/code/comunity in una di queste cartelle (che una volta scelta la cartella di destinazione dovrà, per forza di cose, rimanere la stessa) bisogna creare una cartella con il nome della società ed una sottocartella con il nome del modulo, in modo da ottenere una cartella composta in questa maniera: app/code/local/Societa/Modulo

N.B. Solitamente le cartelle, i files e le classi che si andranno a creare, devono avere necessariamente la prima lettera maiuscola, mentre il resto dei nomi deve essere minusolo e senza spazi/underscore/caratteri speciali fatta eccezione per alcuni esempi che verranno trattati più avanti.

Per comodità, d'ora in poi utilizzeremo alcuni segnaposto che utilizzeremo durante lo sviluppo del modulo (una volta copiate le varie parti del codice, ricordate di sostituire ogni segnaposto con il vostro valore ed includendo le parentesi quadre):

[Societa] = Il nome della vostra società (o comunque un nickname che vi identifichi)

[Modulo] = Il nome del Modulo

[namespace] = nome che verrà utilizzato per richiamare le varie funzioni del modulo

Definizione del Modulo

Per informare magento del vostro nuovo modulo, la posizione del codice e la versione di manutenzione, è necessario creare un file xml nella cartella app/etc/modules/ e chiamarlo [Societa]_[Modulo].xml

All'interno inserire:

<?xml version="1.0"?>
<config>
    <modules>
        <[Societa]_[Modulo]>
            <active>true</active>
            <codePool>local</codePool>
        </[Societa]_[Modulo]>
    </modules>
</config>

Come si può notare, i tag <[Societa]_[Modulo]> <codePool>local</codePool> hanno una valenza importantissima: il primo informa magento sulla struttura del modulo, in base a questo bisognerà costruire una struttura adeguata di cartelle, nomi file e nomi classi adeguati a quanto definito in questo file di configurazione, il secondo <codePool>local</codePool> definisce che il tutto il codice del modulo è allocato nella cartella app/code/local (ovviamente sostituendolo con comunity il codice deve essere posizionato in app/code/comunity).

A questo punto è necessario fare una breve introduzione alle varie classi che si possono creare nell'estensione; magento prevede diversi metodi di implementazione: Model, Block, Controllers. Ognuna di queste classi ha un compito diverso: i modelli (Model) sono classi in cui si posso racchiudere porzioni di codice da utilizzare all'interno del progetto. I blocchi (Block) contengono le funzioni che possono essere richiamate all'interno del template, mentre il controller si occupa di fornire un accesso tra l'indirizzo del browser e l'estensione. In realtà esistono altre implementazioni (come le classi per l'integrazione del database) che però non verranno trattate in questa fase.

Creazione del file config.xml

Questo file definisce le impostazioni fondamentali dell'estensione e deve essere creato nella cartella del vostro Modulo. Indica le classi da utilizzare più altri parametri fondamentali. Nel file xml tutti i vari tag children dovranno essere racchiusi dal parent <config>

<config>
</config>

Come primo elemento inseriamo le informazioni del modulo:

<modules>
        <[Societa]_[Modulo]>
            <version>0.0.1</version>
        </[Societa]_[Modulo]>
</modules>

A questo punto è necessario definire le classi fondamentali Model e Block:

<global>
       <models>
            <[namespace]>
                <class>[Societa]_[Modulo]_Model</class>
            </[namespace]>
        </models>
        <blocks>
            <[namespace]>
                <class>[Societa]_[Modulo]_Block</class>
            </[namespace]>
        </blocks>
</global>

 Per finire, definiamo il controller che vi permetterà di interagire con l'estensione:

<frontend>
        <routers>
            <[Societa]_[Modulo]>
                <use>standard</use>
                <args>
                    <module>[Societa]_[Modulo]</module>
                    <frontName>frontedUrl</frontName>
                </args>
            </[Societa]_[Modulo]>
        </routers>
    </frontend>

la parte interessante del file è <frontName>frontedUrl</frontName> che corrisponde all'indirizzo al quale potete accedere alla vostra estensione (es: http://installazione-magento/frontedUrl )

Definizione della Classe dei Blocchi

Questa classe contiene tutte le funzioni personalizzate che potrete richiamare in ogni pagina .phtml del modulo personalizzato. In questo file bisogna definire tutte le funzioni che vi serviranno all'interno del template. E' possibile creare più classi diverse e con nomi diversi, l'importante è che ogni pagina abbia come nome una cosa simile a [namespace_BlockClass].php e che sia contenuta nella cartella app/code/local/Societa/Modulo/Block/


class [Societa]_[Modulo]_Block_[namespace_BlockClass] extends Mage_Core_Block_Template {
    public function methodblock() {
        return "informations about my block !!";
    }
 
    public function MostraProdottiCorrelati() {
        $ids = array();
 
        $url = $_SERVER['REQUEST_URI'];
        $url = trim(str_replace(array(".","html", ".html"), "", $url), "/") ;
        $searchText = preg_replace("/\W{1,}/i", "%", $url);
        $searchText = preg_replace("/[0-9]+/i", "", $searchText) ;
        $searchText = preg_replace("/\s[a-zA-Z]{1,2}\s/i", "", $searchText) ;
        $searchText = trim($searchText, "%") ;
        $collection = Mage::getResourceModel('catalog/product_collection');
        $collection->addAttributeToSelect("*") ;
        $collection->addAttributeToFilter('name', array('like' => '%'.$searchText.'%')) ;
       $collection->setPageSize(20) ;
 
        foreach ($collection as $product) {
            $ids[] = $product;
        }
        if(!$ids) :
            return $this->ProdottiPiuVenduti() ;
        endif;
        return $ids;
    }
 
    public function ProdottiPiuVenduti() {
        $date = new Zend_Date();
        $toDate = $date->setDay(1)->getDate()->get('Y-MM-dd');
        $fromDate = $date->subMonth(1)->getDate()->get('Y-MM-dd');
        $ids = array() ;
        $storeId    = Mage::app()->getStore()->getId();
        $products = Mage::getResourceModel('catalog/product_collection')
            ->addAttributeToSelect(Mage::getSingleton('catalog/config')->getProductAttributes())
            ->addStoreFilter()
            ->addPriceData()
            ->addTaxPercents()
            ->addUrlRewrite()
            ->setPageSize(20)
//            ->order('sold_quantity', 'DESC')
                ;
        $products->getSelect()
            ->joinLeft(
                array('aggregation' => $products->getResource()->getTable('sales/bestsellers_aggregated_monthly')),
                "e.entity_id = aggregation.product_id AND aggregation.store_id={$storeId} AND aggregation.period BETWEEN '{$fromDate}' AND '{$toDate}'",
                array('SUM(aggregation.qty_ordered) AS sold_quantity')
            )
            ->group('e.entity_id')
            ->order(array('sold_quantity DESC', 'e.created_at'));
        Mage::getSingleton('catalog/product_status')->addVisibleFilterToCollection($products);
        Mage::getSingleton('catalog/product_visibility')->addVisibleInCatalogFilterToCollection($products);
        foreach ($products as $product) {
            $ids[] = $product;
        }
        return $ids ;
    }
 
}

In questo esempio, sono presenti due funzioni MostraProdottiCorrelati() e ProdottiPiuVenduti(). Queste due funzioni non contengono direttamente output in HTML ma solo oggetti da richiamare all'interno del template. La funzione MostraProdottiCorrelati() contiene tutta una serie di istruzioni per ricavare l'url della pagina da cui proviene l'utente e che magento non trova, eliminare le parti non necessarie (come l'estensione .html) e sostituire agli spazi, caratteri speciali e numeri il simbolo % che è necessario nelle ricerche di tipo LIKE. Poi mette insieme tutti i prodotti con nome simili in un array e li restituisce. Nel caso in cui non si abbiano risultati richiama la funzione ProdottiPiuVenduti() e restituisce i sui oggetti.

Definizione del Controller

Il controller è una classe personalizzata che si occupa di offrire un interfacciamento tra l'url e il vostro modulo. Deve essere creato nella cartella app/code/local/Societa/Modulo/controllers e deve chiamarsi IndexController.php

Il contenuto potrebbe essere questo:

class [Societa]_[Modulo]_IndexController extends Mage_Core_Controller_Front_Action {
 
  
    public function notfoundAction() {
 
        $this->loadLayout();
 
        $block = $this->getLayout()->createBlock(
                '[Societa]_[Modulo]_Block_[namespace_BlockClass]', 'pages', array('template' => '[Modulo]/[namespace_pagina].phtml')
        );
        $this->getLayout()->getBlock('content')->append($block);
 
        $this->getLayout()->getBlock('head')->setTitle($this->__('Pagina non trovata'));
        $this->renderLayout();
 
        $this->getResponse()->setHeader('HTTP/1.1', '404 Not Found');
    }
 
}

Cerchiamo di capire questo codice:

abbiamo inizzializzato la classe e al suo interno abbiamo definito la funzione notfoundAction() che contiene il codice da eseguire quando richiamate nel browser l'url del tipo http://installazione-magento/frontedUrl/notfound. In questo frangente è necessario che ognuno metta il suo a seconda delle operazioni che il modulo dovrà svolgere. In questo esempio, creiamo una pagina 404 personalizzata, perciò le prime cose da fare sono: 

  1. caricare il layout del template
  2. inserire nella pagina un blocco definito nella cartella del template (che ancora bisogna creare) in modo da rendere la personalizzazione più veloce
  3. Impostare il titolo della pagina
  4. Impostare il codice di risposta che dovrà restituire la pagina (404 Not Found)

Il primo punto è abbastanza semplice, basta richiamare la funzione $this->loadLayout(); per far assumere alla pagina la grafica del template in uso. N.B. Senza questa funzione richiamereste una pagina bianca. 

Il secondo punto è composto da questa parte:

 $block = $this->getLayout()->createBlock(
                '[Societa]_[Modulo]_Block_Pages', 'pages', array('template' => '[Modulo]/[namespace_pagina].phtml')
        );
        $this->getLayout()->getBlock('content')->append($block);

In pratica si crea un blocco, ovvero una porzione di codice misto HTML + PHP da incorporare nella pagina. Questo blocco avrà nome [namespace_pagina].phtml e si troverà nella cartella app/design/frontend/base/default/template/[Modulo]

questa pagina conterrà qualcosa di simile:

<h1>La pagina che stai cercando non esiste!</h1>
<p>
    Forse possono interessarti questi prodotti:
</p>
<?php foreach($this->MostraProdottiCorrelati() AS $_product) : ?>
 
 
<a href = '<?php echo $_product->getProductUrl() ?>'>
    <div class="cerca-prodotto">
        <h2><?php echo $_product->getName() ; ?></h2>
        <img src="<?php echo $this->helper('catalog/image')->init($_product, 'small_image')->resize(170); ?>"  class="immagine-lista" alt="<?php echo $this->stripTags($this->getImageLabel($_product, 'small_image'), null, true) ?>" />
    </div>
    </a>
<?php endforeach; ?>

In pratica si ciclano i prodotti restituiti dalla funzione MostraProdottiCorrelati() e si costruisce l'output HTML che si avrà ogni volta che si richiamerà quel blocco.