CRUD – Create

  1. More file structure goodness:
    app/
      etc/
        modules/
          - SavantDegrees_All.xml (Or what ever your company name might be)
      code/
        local/
          SavantDegrees/ (Or what ever your company name might be)
            Twit/ (Or whatever your module name might be)
              Block/
                Admin/
                  - Main.php
                  Main/
                    - Grid.php
                  - New.php
                  New/
                    - Form.php
                - Index.php
              controllers/
                - AdminController.php
                - IndexController.php
              etc/
                - config.xml
              Helper/
                - Data.php
              Model/
                - Twit.php
                Mysql4/
                  - Twit.php
                  Twit/
                    - Collection.php
              sql/
                twit_setup/
                  - mysql4-install-0.2.0.php
                  - mysql4-upgrade-0.1.0-0.2.0.php

    Here we’ve added the block for the New container and Form

  2. Looking at the New.php code:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    
    <?php
    class SavantDegrees_Twit_Block_Admin_New extends Mage_Adminhtml_Block_Widget_Form_Container
    {
        public function __construct()
        {
            parent::__construct();
     
            $this->_blockGroup = 'twit';
            $this->_mode = 'new';
            $this->_controller = 'admin';
        }
     
        public function getHeaderText()
        {
            return Mage::helper('twit')->__('Add New Twit');
        }
    }
  3. Then the New/Form.php code
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    
    <?php
    class SavantDegrees_Twit_Block_Admin_New_Form extends Mage_Adminhtml_Block_Widget_Form
    {
        protected function _prepareForm()
        {
            $form = new Varien_Data_Form();
     
            $fieldset = $form->addFieldset('new_twit', array('legend' => Mage::helper('twit')->__('Twit Details')));
     
            $fieldset->addField('name', 'text', array(
                'name'      => 'name',
                'title'     => Mage::helper('twit')->__('Name'),
                'label'     => Mage::helper('twit')->__('Name'),
                'maxlength' => '50',
                'required'  => true,
            ));
     
            $fieldset->addField('tags', 'text', array(
                'name'      => 'tags',
                'title'     => Mage::helper('twit')->__('Tags'),
                'label'     => Mage::helper('twit')->__('Tags'),
                'maxlength' => '255',
                'required'  => true,
            ));
     
            $fieldset->addField('summary', 'textarea', array(
                'name'      => 'summary',
                'title'     => Mage::helper('twit')->__('Summary'),
                'label'     => Mage::helper('twit')->__('Summary'),
                'style'     => 'width: 98%; height: 200px;',
                'required'  => true,
            ));
     
            $form->setMethod('post');
            $form->setUseContainer(true);
            $form->setId('edit_form');
            $form->setAction($this->getUrl('*/*/post'));
     
            $this->setForm($form);
        }
    }

    Just like your listings/grid page, the New.php and Form.php classes are the Form Container and Form respectively. So the Form Container automagically creates the form. Did I mention why containers are good? They come with nice pretty buttons! (Save and Back).

  4. Then lastly the adminController with its newAction and postAction to load and save the form respectively

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    
     
    class SavantDegrees_Twit_AdminController extends Mage_Adminhtml_Controller_Action
    {
    	public function indexAction()
        {
    		$this->loadLayout()
    			->_addContent($this->getLayout()->createBlock('twit/admin_main'))
    			->renderLayout();
        }
     
    	public function deleteAction()
        {
            $twitId = $this->getRequest()->getParam('id', false);
     
            try {
                Mage::getModel('twit/twit')->setId($twitId)->delete();
                Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('twit')->__('Page successfully deleted'));
                $this->getResponse()->setRedirect($this->getUrl('*/*/'));
     
                return;
            } catch (Exception $e){
                Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
            }
     
            $this->_redirectReferer();
        }
     
        public function newAction()
        {
            $this->loadLayout()
            ->_addContent($this->getLayout()->createBlock('twit/admin_new'))
            ->renderLayout();
        }
     
        public function postAction()
        {
            if ($data = $this->getRequest()->getPost()) {
                $twit = Mage::getModel('twit/twit')->setData($data);
                try {
                    $twit->save();
                    Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('twit')->__('Twit was successfully saved'));
                    $this->getResponse()->setRedirect($this->getUrl('*/*/'));
                    return;
                } catch (Exception $e){
                    Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
                }
            }
            $this->getResponse()->setRedirect($this->getUrl('*/*/'));
            return;
        }
    }
  5. Reward yourself for your lightning fast copy-and-paste kung foo! Whats happening though?
    When the script receives a call newAction, it’ll show the form to enter data. The data is posted to the postAction method. That method creates an instance of the model, sets the post data into the model, saves it then redirects it back to the indexAction. Did i mention automagically? Yes, thats why we had to learn so much of the Magento code just to write this simple tutorial. The sql is automagically generated and run and the form is automagically created! *sheds a tear*

    Again, your well deserved create form can be found by clicking on the “Add New Twit” button from the Grid!

Just 1 more … CRUD – Update

CRUD – Delete

  1. The simplest step thus far, add a new function to your adminController.php
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    
    <?php
    class SavantDegrees_Twit_AdminController extends Mage_Adminhtml_Controller_Action
    {
        public function indexAction()
        {
    		$this->loadLayout()
    			->_addContent($this->getLayout()->createBlock('twit/admin_main'))
    			->renderLayout();
        }
     
        public function deleteAction()
        {
            $twitId = $this->getRequest()->getParam('id', false);
     
            try {
                Mage::getModel('twit/twit')->setId($twitId)->delete();
                Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('twit')->__('Page successfully deleted'));
                $this->getResponse()->setRedirect($this->getUrl('*/*/'));
     
                return;
            } catch (Exception $e){
                Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
            }
     
            $this->_redirectReferer();
        }
    }
Almost there … CRUD – Create

CRUD – Retrieve

  1. Lets add a new block to the file structure
    app/
      etc/
        modules/
          - SavantDegrees_All.xml (Or what ever your company name might be)
      code/
        local/
          SavantDegrees/ (Or what ever your company name might be)
            Twit/ (Or whatever your module name might be)
              Block/
                Admin/
                  - Main.php
                  Main/
                    - Grid.php
                - Index.php
              controllers/
                - AdminController.php
                - IndexController.php
              etc/
                - config.xml
              Helper/
                - Data.php
              Model/
                - Twit.php
                Mysql4/
                  - Twit.php
                  Twit/
                    - Collection.php
              sql/
                twit_setup/
                  - mysql4-install-0.2.0.php
                  - mysql4-upgrade-0.1.0-0.2.0

    We’ll create folder called Admin to store all the admin related blocks. Inside we’ll have a Main.php file that contains the Grid Container. Why do we need a grid container? To put the title and Create button!

  2. The Main.php code

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    <?php
    class SavantDegrees_Twit_Block_Admin_Main extends Mage_Adminhtml_Block_Widget_Grid_Container
    {
        public function __construct()
        {
            $this->_addButtonLabel = Mage::helper('twit')->__('Add New Twit');
            parent::__construct();
     
            $this->_blockGroup = 'twit';
            $this->_controller = 'admin_main';
            $this->_headerText = Mage::helper('twit')->__('Twit(s)');
        }
    }

    Here you see a first use of the helper, which will assist in translation

  3. The Grid.php itself

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    
    <?php
    class SavantDegrees_Twit_Block_Admin_Main_Grid extends Mage_Adminhtml_Block_Widget_Grid
    {
     
        public function __construct()
        {
            parent::__construct();
            $this->setId('twitGrid');
            $this->_controller = 'twit';
        }
     
        protected function _prepareCollection()
        {
            $model = Mage::getModel('twit/twit');
            $collection = $model->getCollection();
    		$this->setCollection($collection);
     
            return parent::_prepareCollection();
        }
     
     
     
        protected function _prepareColumns()
        {
     
            $this->addColumn('twit_id', array(
                'header'        => Mage::helper('twit')->__('ID'),
                'align'         => 'right',
                'width'         => '50px',
                'filter_index'  => 'dt.twit_id',
                'index'         => 'twit_id',
            ));
     
            $this->addColumn('name', array(
                'header'        => Mage::helper('twit')->__('Name'),
                'align'         => 'left',
                'width'         => '150px',
                'filter_index'  => 'dt.name',
                'index'         => 'name',
                'type'          => 'text',
                'truncate'      => 50,
                'escape'        => true,
            ));
     
            $this->addColumn('summary', array(
                'header'        => Mage::helper('twit')->__('Summary'),
                'align'         => 'left',
                'filter_index'  => 'dt.summary',
                'index'         => 'summary',
                'type'          => 'text',
                'escape'        => false,
            ));
     
            $this->addColumn('tags', array(
                'header'    	=> Mage::helper('twit')->__('Tags'),
                'align'         => 'left',
                'filter_index'  => 'dt.tags',
                'index'    	 	=> 'tags',
                'type'     	 	=> 'text',
                'escape'		=> true,
            ));
     
            $this->addColumn('action',
                array(
                    'header'    => Mage::helper('twit')->__('Action'),
                    'width'     => '150px',
                    'type'      => 'action',
                    'getter'	=> 'getTwitId',
                    'actions'   => array(
                        array(
                            'caption' => Mage::helper('twit')->__('Edit'),
                            'url'     => array(
                                'base'=>'*/*/edit'
                             ),
                             'field'   => 'id'
                        ),
                        array(
                            'caption' => Mage::helper('twit')->__('Delete'),
                            'url'     => array(
                                'base'=>'*/*/delete'
                             ),
                             'field'   => 'id'
                        )
                    ),
                    'filter'    => false,
                    'sortable'  => false
            ));
     
            return parent::_prepareColumns();
        }
     
        public function getRowUrl($row)
        {
            return $this->getUrl('*/*/edit', array(
                'id' => $row->getTwitId(),
            ));
        }
    }

    If you scrutinize the code (which i’d advise against), you’ll see most of the code is geared towards the setup of the grid columns and the edit/delete urls i’ll eventually call to perform the other CRUD functions.
    But whats going on? Where do we use this code? The main code (being a Grid_Container automatically adds the child Grid code associated to it. By child we’re talking about the Grid.php file in the Main folder. The folder’s name follows the file. So if you changed the folder’s name to Main2, it wouldnt work. That being said, you can just put any block code in the folder and expect it to run. The reason why this all works now is cause the geniuses at Magento already did alot of work to call the Grid child to run. They have no super time travel powers to tell what else you’re gonna put in there. So, it simply wont work (yet).

  4. Now lets make our adminController.php use that block instead of Hello world.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    class SavantDegrees_Twit_AdminController extends Mage_Adminhtml_Controller_Action
    {
        public function indexAction()
        {
    		$this->loadLayout()
    			->_addContent($this->getLayout()->createBlock('twit/admin_main'))
    			->renderLayout();
        }
    }

    Well it says createBlock doesnt it? What do you think it does? twit/admin_main as always refers to the twit namespace and the admin/main.php block file.

  5. Viola! Your very very very hard earned grid!
    Magento Admin Grid
Anytime now … Part 6 – CRUD – Delete