Le Grid dans Magento

Souvenez vous, dans le tutoriel précédent on a créé un contrôleur dans l'interface d’administration de magento pour gérer notre liste de films directement depuis l’administration de magento. C'est un bon premier pas mais c'est pas super sexy. Dans l’administration magento, quand vous voulez lister les produits (et que vous allez dans "Catalog" > "Manage Product"), vous voyez une GridView (une sorte de tableau avec lequel pouvez trier, editer un article, le supprimer etc…). Dans ce tutoriel on va voir comment utiliser ce composant pour lister nos films. On va donc remplacer notre bloc actuel par un Grid qui listera nos films.
Un Grid Magento est construit à partir d’un ensemble de fichiers qui vont se trouver dans le dossier Block/Adminhtml/ de votre module.

1- Le Grid Container

Créez un dossier : \app\code\local\Pfay\Films\Block\Adminhtml\ et mettez dedans un fichier Grid.php. C’est le fichier qui (comme son nom l’indique) va contenir votre Grid. Il contiendra :

<?php
class Pfay_Films_Block_Adminhtml_Films extends Mage_Adminhtml_Block_Widget_Grid_Container {

        public function __construct()
        {
            $this->_controller = 'adminhtml_films';
            $this->_blockGroup = 'pfay_films';

            $this->_headerText = 'Manage my films';
            $this->_addButtonLabel = 'Add a film';

            parent::__construct();
        }
}

Dans ce bloc bien spécifique (attention à ne pas confondre avec les autres) $this->_controller c'est le chemin vers vos blocs..
Exemple :
- pour charger notre bloc Monbloc on utilise le chemin 'pfay_films/monbloc' ce qui permet à magento de savoir qu'il doit aller chercher la classe Pfay_Films_Block_Monbloc.

Pour notre grid, on utilise pfay_films/adminhtml_grid ce qui veut dire que magento ira chercher le bloc avec la classe suivante : Pfay_Films_Block_Adminhtml_Grid

2- Le Grid

Vous indiquez que le controller du grid se trouvera dans le dossier films, creez donc le dossier : \app\code\local\Pfay\Films\Block\Adminhtml\Grid\ et dedans créez un fichier Grid.php qui contiendra :

<?php
class Pfay_Films_Block_Adminhtml_Films_Grid extends Mage_Adminhtml_Block_Widget_Grid
{
    public function __construct()
    {
        parent::__construct();
        $this->setId('filmsGrid');
        $this->setDefaultSort('id_pfay_films');
        $this->setDefaultDir('DESC');
        $this->setSaveParametersInSession(true);
    }

    protected function _prepareCollection()
    {
        $collection = Mage::getModel('pfay_films/film')->getCollection();
        $this->setCollection($collection);
        return parent::_prepareCollection();
    }

    public function _prepareColumns()
    {
        $this->addColumn('id_pfay_films', array(
            'header' => 'ID',
            'align' => 'right',
            'width' => '50px',
            'index' => 'id_pfay_films'
        ));


        $this->addColumn('name', array(
            'header' => 'NAME',
            'align' => 'left',
            'index' => 'name'
        ));

        return parent::_prepareColumns();
    }

    public function getRowUrl($row)
    {
        return $this->getUrl('*/*/edit', array('id' => $row->getId()));
    }


}

On configure notre Grid magento en lui indiquant la collection à utiliser pour interagir avec la base de donnée dans prepareCollection() (ici on va utiliser la collection du model 'pfay_films/film' qu’on a créé dans les tutoriels précédents). Puis avec prepareColumns() on lui indique quelles colonnes de notre table afficher grâce à la méthode addColumn(). Je n’explique pas plus le code que ça, il me parait assez évident que si vous voulez rajouter une colone (pour ajouter une date par exemple), il suffit de rajouter une inscription du style :

$this->addColumn('date',
       array(
           'header' => 'date',
           'align' =>'left',
           'index' => 'date',
       ));

Si vous voulez ajouter ces lignes, il faudra que le champs "date" soit présent dans votre table de la base de donnée.
Voila, notre Grid est maintenant configuré. Maintenant, quand on cliquera sur une des lignes, il faut qu’on arrive sur un formulaire pour pouvoir éditer notre film.

3- Le Form Container

Créez donc un fichier Edit.php dans le même répertoire : \app\code\local\Pfay\Films\Block\Adminhtml\Films\ Ce fichier Edit.php contiendra le code suivant :

<?php
class Pfay_Films_Block_Adminhtml_Films_Edit extends Mage_Adminhtml_Block_Widget_Form_Container
{

    public function __construct()
    {
        parent::__construct();
        $this->_objectId = 'id';
        $this->_blockGroup = 'pfay_films';
        $this->_controller = 'adminhtml_films';
        $this->_updateButton('save', 'label', 'Save film');
        $this->_updateButton('delete', 'label', 'Delete film');
    }


    public function getHeaderText()
    {
        if (Mage::registry('films_data') && Mage::registry('films_data')->getId()) {
            return 'Editer le film ' . $this->htmlEscape(Mage::registry('films_data')->getTitle());
        } else {
            return 'Ajouter une film';
        }
    }
}

J’ai commenté le code, ce fichier est un Form Container (voir le extends) c'est-à-dire une structure qui va vous permettre de recevoir des formulaires, maintenant il faut faire le formulaire en lui-même.

4- Créer le Formulaire

Créez le dossier : \app\code\local\Pfay\Films\Block\Adminhtml\Films\Edit\ et dedans le fichier Form.php Ce fichier contiendra le code suivant :

<?php
class Pfay_Films_Block_Adminhtml_Films_Edit_Form extends Mage_Adminhtml_Block_Widget_Form
{
    protected function _prepareForm()
    {
        $form = new Varien_Data_Form(
            array(
                'id' => 'edit_form',
                'action' => $this->getUrl('*/*/save', array('id' => $this->getRequest()->getParam('id'))
                ),
                'method' => 'post',
            )
        );
        $form->setUseContainer(true);
        $this->setForm($form);
        return parent::_prepareForm();
    }
}

On crée ici un objet de type Varien_Data_Form qui est le type « standard » de formulaire magento, on définit l’attribut action du formulaire grâce à la fonction getUrl() et on définit la méthode d’envoi des informations.

Maintenant on va créer les lignes de notre formulaire.

Dans notre repertoire \app\code\local\Pfay\Films\Block\Adminhtml\Films\Edit\, creez un fichier Tabs.php qui est en fait une sorte de « tabs container » ;) Ce fichier contiendra le code suivant :

<?php
class Pfay_Films_Block_Adminhtml_Films_Edit_Tabs extends Mage_Adminhtml_Block_Widget_Tabs
{
    public function __construct()
    {
        parent::__construct();
        $this->setId('films_tabs');
        $this->setDestElementId('edit_form');
        $this->setTitle('Information sur le film');
    }

    protected function _beforeToHtml()
    {
        $this->addTab('form_section', array(
            'label' => 'About the movie',
            'title' => 'About the movie',
            'content' => $this->getLayout()
                ->createBlock('pfay_films/adminhtml_films_edit_tab_form')
                ->toHtml()
        ));

        return parent::_beforeToHtml();
    }
}

On lui dit que les entrées seront crées grâce au block du module Films, qui sera adminhtml_films_edit_tab_form.

Créez donc le dossier: \app\code\local\Pfay\Films\Block\Adminhtml\Films\Edit\Tab et dedans le Fichier Form.php.

<?php
class Pfay_Films_Block_Adminhtml_Films_Edit_Tab_Form extends Mage_Adminhtml_Block_Widget_Form
{
    protected function _prepareForm()
    {
        $form = new Varien_Data_Form();
        $this->setForm($form);
        $fieldset = $form->addFieldset('films_form',
            array('legend'=>'ref information'));
        $fieldset->addField('name', 'text',
            array(
                'label' => 'Name',
                'class' => 'required-entry',
                'required' => true,
                'name' => 'name',
            ));

        if ( Mage::registry('films_data') )
        {
            $form->setValues(Mage::registry('films_data')->getData());
        }

        return parent::_prepareForm();
    }
}


5- Insérer notre block dans le Layout

Dans le layout.xml de votre thème d’administration, changer votre block par :

    <block type="pfay_films/adminhtml_grid" name="films" />
    
Et voila, votre grid fonctionne felicitation…

Ha non ca marche pas il ne fait aucune modification ? c’est normal ! Il faut que vous implémentiez la méthode save dans votre controller magento !

6- Implémenter les fonctions dans le controller

Allez donc dans votre fichier \app\code\local\Pfay\Films\controllers\Adminhtml\IndexController.php et editez le comme ceci :

<?php
class Pfay_Films_Adminhtml_FilmController extends Mage_Adminhtml_Controller_Action
{
    protected function _initAction()
    {
        $this->loadLayout()->_setActiveMenu('films/set_time')->_addBreadcrumb('Movies Manager','Movies Manager');
        return $this;
    }

    public function indexAction()
    {
        $this->_initAction();
        $this->renderLayout();
    }

    public function editAction()
    {
        $filmsId = $this->getRequest()->getParam('id');
        $filmsModel = Mage::getModel('pfay_films/film')->load($filmsId);

        if ($filmsModel->getId() || $filmsId == 0)
        {
            Mage::register('films_data', $filmsModel);
            $this->loadLayout();
            $this->_setActiveMenu('films/set_time');
            $this->_addBreadcrumb('films Manager', 'films Manager');
            $this->_addBreadcrumb('Films Description', 'Films Description');
            $this->getLayout()->getBlock('head')
                ->setCanLoadExtJs(true);
            $this->_addContent($this->getLayout()
                ->createBlock('pfay_films/adminhtml_films_edit'))
                ->_addLeft($this->getLayout()
                    ->createBlock('pfay_films/adminhtml_films_edit_tabs')
                );
            $this->renderLayout();
        }
        else
        {
            Mage::getSingleton('adminhtml/session')->addError('Films does not exist');
            $this->_redirect('*/*/');
        }
    }

    public function newAction()
    {
        $this->_forward('edit');
    }

    public function saveAction()
    {
        if ($this->getRequest()->isPost())
        {
            try {
                $postData = $this->getRequest()->getPost();
                if( $this->getRequest()->getParam('id') <= 0 ) {
                    $filmsModel = Mage::getModel('pfay_films/film')->load($this->getRequest()->getParam('id'));
                }else {
                    $filmsModel = Mage::getModel('pfay_films/film');
                }

                $filmsModel
                    ->addData($postData)
                    ->save();

                Mage::getSingleton('adminhtml/session')->addSuccess('successfully saved');
                Mage::getSingleton('adminhtml/session')->setfilmsData(false);
                $this->_redirect('*/*/');
                return;


            } catch (Exception $e) {

                Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
                Mage::getSingleton('adminhtml/session')->setfilmsData($this->getRequest()->getPost());
                $this->_redirect('*/*/edit', array('id' => $this->getRequest()->getParam('id')));
                return;
            }

            $this->_redirect('*/*/');
        }
    }

    public function deleteAction()
    {
        if($this->getRequest()->getParam('id') > 0)
        {
            try
            {
                $filmsModel = Mage::getModel('pfay_films/film');
                $filmsModel->setId($this->getRequest()->getParam('id'))->delete();
                Mage::getSingleton('adminhtml/session')->addSuccess('successfully deleted');
                $this->_redirect('*/*/');
            }
            catch (Exception $e)
            {
                Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
                $this->_redirect('*/*/edit', array('id' => $this->getRequest()->getParam('id')));
            }
        }
        $this->_redirect('*/*/');
    }
}

Maintenant ça marche vraiment !

Voila c’est fini pour aujourd’hui ;)

Ca peu paraitre abstrait, mais à force de l’utiliser ca viendra tout seul ne vous inquiétez pas.

N’hésitez pas à laisser vos messages en commentaire si vous avez des questions. Vous pouvez comme d'habitude télécharger le code du tutoriel pour le comparer avec le votre.
Documents disponibles pour cet article :
Questions sur cette leçon
Pas de questions pour cette leçon. Soyez le premier !

Vous devez etre connecté pour demander de l'aide sur une leçon.