The magento admin grid

Remember, in the previous tutorial we created a controller in the Magento backend to manage our list of movies directly from it. This is a good first step but it is not super sexy. In magento administration, when you want to list the products (Go to "Catalog"> "Manage Product"), you can see a GridView (a kind of table which can be sorted, edited, etc... ). In this tutorial we will see how to use this component to list our movies. So we will replace our current block by a magento admin grid which will list our films.
Magento Grid is constructed from a set of files that will be in the Block/Adminhtml/ folder of your module.

1- Grid Container

Create a folder: \app\code\local\Pfay\Films\Block\Adminhtml\ and create an Grid.php file in it. This is the file which (as the name suggests) will contain your Grid :

class Pfay_Films_Block_Adminhtml_Grid extends Mage_Adminhtml_Block_Widget_Grid_Container
{

    public function __construct()
    {
     //indicate where we can find the controller
     $this->_controller = 'adminhtml_films';
     $this->_blockGroup = 'films';
     //header text
     $this->_headerText = 'Manage my movies;
     //button label 
     $this->_addButtonLabel = 'Add a movie';
     parent::__construct();
     }
}

In this specific block (do not confuse with others) $this->_controller is the path to your blocks ..
Exemple :
- to load our Monobloc block using the path 'pfay_films/monbloc' allowing magento knows to go for the class Pfay_Films_Block_Monbloc.

For our grid, we will use pfay_films/adminhtml_films, magento will use the block with the name : Pfay_Films_Block_Adminhtml_Films

2- The Grid

You will indicate that the grid controller is in the films folder, so create the folder: \app\code\local\Pfay\Films\Block\Adminhtml\Films\ with a Grid.php file in it :

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();
    }

   protected 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()));
    }
}

We configure our magento grid stating the collection to use to interact with the database in prepareCollection() (here we will use the collection of model 'pfay_films/film' we created in previous tutorials). Then we said in prepareColumns() which columns to display in our table through the addColumn() function. I do not explain more code than that, it seems pretty obvious to me that if you want to add a column (to add a date, for example), you just have to add an entry like this:

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

If you want to add these lines, the fields "date" must be the present in your database table.
Here we are, our Grid is now configured. Now, we want to edit a movie when we click on one of the line.

3- Le Form Container

Create a edit.php file in the same directory : \app\code\local\Pfay\Films\Block\Adminhtml\Films\ The file Edit.php must contains the following code :

class Pfay_Films_Block_Adminhtml_Films_Edit extends Mage_Adminhtml_Block_Widget_Form_Container{

   public function __construct()
   {
        parent::__construct();
        $this->_objectId = 'id';
        //you will notice that assigns the same blockGroup the Grid Container
        $this->_blockGroup = 'pfay_films';
        // and the same container
        $this->_controller = 'adminhtml_films';
        //we define the labels for the buttons save and delete
        $this->_updateButton('save', 'label','Save movie');
        $this->_updateButton('delete', 'label', 'Delete movie');
    }

       /* Here, we look at whether it was transmitted item to form
        * to put the right text in the header (Add or Edit)
        */

    public function getHeaderText()
    {
        if( Mage::registry('films_data') && Mage::registry('films_data')->getId() )
         {
              return 'Edit a movie '.$this->htmlEscape( Mage::registry('films_data')->getTitle() );
         }
         else
         {
             return 'Add a movie';
         }
    }
}

I commented the code, this file is a Form Container (see the "extends") that is to say, a structure that will allow you to receive forms. Now we need to create the form itself.

4- Create the form

Create the folder: \app\code\local\Pfay\Films\Block\Adminhtml\Films\Edit\ and in this folder, the following Form.php file with this code :

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();
   }
}

Here we create an object of type Varien_Data_Formwhich is the "standard" magento form, we define the action attribute of the form through the function getUrl() and we define the method of sending information ( here POST).

Now we will create the form inputs

In our directory \app\code\local\Pfay\Films\Block\Adminhtml\Films\Edit, create a file Tabs.php which is a kind of « tabs container » ;) This file contains the following code :

  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();
    }
}

It is said to magento that entries will be created through block of our module Films, which will be adminhtml_films_edit_tab_form.

Create the folder: \app\code\local\Pfay\Films\Block\Adminhtml\Films\Edit\Tab with the Form.php file in it as follow :

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- Insert our block in the Layout

In the layout.xml of your admin theme, change the block by :

    <block type="pfay_films/adminhtml_grid" name="films" />
    
Voila, yout magento grid works…Congralutation !

Ha no its not working there is no change? it's normal ! It takes you to implement the save method in your controller magento!

6-Implement the save functions in the controller

Edit the file \app\code\local\Pfay\Films\controllers\Adminhtml\IndexController.php like this :

class Pfay_Films_Adminhtml_IndexController extends Mage_Adminhtml_Controller_Action
{
    protected function _initAction()
    {
        $this->loadLayout()->_setActiveMenu('pfay_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('pfay_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()->getPost())
         {
               try {
                     $postData = $this->getRequest()->getPost();
                     $filmsModel = Mage::getModel('pfay_films/film');
    
                   if( $this->getRequest()->getParam('id') <= 0 ) {
                      $filmsModel->setCreatedTime( Mage::getSingleton('core/date')->gmtDate() );
                      $filmsModel
                        ->addData($postData)
                        ->setUpdateTime( Mage::getSingleton('core/date')->gmtDate())
                        ->setId($this->getRequest()->getParam('id'))
                        ->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('*/*/');
       }
}

Now it really works!

That is it for today ;) You works very well !

It just seem abstract, but by dint of using it will come alone do not worry

. Feel free to leave your messages in comments if you have any questions. You can download as usual tutorial code to compare it with yours (of course you shloud be premium...But the price is less than a Mc Donald menu and it's a way to make this blog living with new tutorials).
Available documents for this article :
Books that can help you :
  • Livre Magento Developer's Guide by Alan Mc Gregor
  • Livre Magento Performance Optimization
  • Livre Grokking Magento Vinai
Questions about this lesson
No questions for this lesson. Be the first !

You must be logged in to ask for help on a lesson.