CRUD – Update
Very similar to the Create phase, this phase basically requires the Form and Form Container blocks, and the controller to save them. Thats all!

  1. Repeat the 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
                  - Edit.php
                  Edit/
                    - Form.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 Edit container and Form

  2. Looking at the Edit.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
    
    <?php
    class SavantDegrees_Twit_Block_Admin_Edit extends Mage_Adminhtml_Block_Widget_Form_Container
    {
        public function __construct()
        {
            parent::__construct();
     
            $this->_blockGroup = 'twit';
            $this->_mode = 'edit';
            $this->_controller = 'admin';
     
            if( $this->getRequest()->getParam($this->_objectId) ) {
                $twitData = Mage::getModel('twit/twit')
                    ->load($this->getRequest()->getParam($this->_objectId));
                Mage::register('frozen_twit', $twitData);
            }
        }
     
        public function getHeaderText()
        {
            return Mage::helper('twit')->__("Edit Twit'%s'", $this->htmlEscape(Mage::registry('frozen_twit')->getName()));
        }
    }

    The additional code loads the right Twit data based on the Request parameter, then stores that data in the Mage registry. We’ll be using that data on the Form page again later to populate the form.
    Notice that the saving code is Mage::register and the retrieving code is Mage::registry

  3. Then the accompanying Edit/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
    42
    43
    
    <?php
    class SavantDegrees_Twit_Block_Admin_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'
            ));
     
            $fieldset = $form->addFieldset('edit_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->setUseContainer(true);
            $form->setValues(Mage::registry('frozen_twit')->getData());
            $this->setForm($form);
            return parent::_prepareForm();
        }
    }
  4. Then lastly the adminController with its editAction and saveAction 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
    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
    
    <?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();
        }
     
        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;
        }
     
        public function editAction()
        {
            $this->loadLayout();
            $this->_addContent($this->getLayout()->createBlock('twit/admin_edit'));
            $this->renderLayout();
        }
     
        public function saveAction()
        {
            $twitId = $this->getRequest()->getParam('id', false);
            if ($data = $this->getRequest()->getPost()) {
                $twit = Mage::getModel('twit/twit')->load($twitId)->addData($data);
                try {
                    $twit->setId($twitId)->save();
     
                    Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('twit')->__('Twit was saved successfully'));
                    $this->getResponse()->setRedirect($this->getUrl('*/*/'));
                    return;
                } catch (Exception $e){
                    Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
                }
            }
            $this->_redirectReferer();
        }
    }
  5. Ok i admit the code is a tad inefficient. We have 2 separate functions that both does save. In fact, postAction and saveAction only differ that saveAction loads the right record via the ->load($twitId) function. Thats separates a CREATE from an UPDATE request.

    And we’re finally finally finally done! To test out the edit function, simply click on any row from the Grid! Thats assuming of course that you actually have some data.
    Magento Admin Form

For frontend stuff, carry on … Fontend – List

Otherwise, if it works for you, leave a comment! =)

Just to be sure, download the Magento tutorial files to see if you’ve made any mistakes here: Magento Tutorial


13 Responses to “Howto: Repackageable custom extension development in Magento – Part 8 – CRUD – Update”

  1. Margots Says:

    Thank you a lot for spending time to write this very very useful tutorial!

  2. congtq Says:

    Thanks very much. What a nice tutorial.
    But perhaps Admin Panel coundn’t search/filter yet !?

  3. gaweee Says:

    Hi Brendan
    frozen_twit is the object that is stored in Mage registry for access via different classes. Think of it as a better way of doing global
    To save something in the registry we use Mage::register
    and to retrieve it, we us Mage::registry

  4. Brendan Says:

    hi,

    really great tutorial.
    one question.

    what/how does the following code work?
    $form->setValues(Mage::registry(’frozen_twit’)->getData());

    I dont understand the “frozen_twit”
    is this referencing a call somewhere else?

    brendan

  5. Jared Says:

    Thanks so much for this tutorial. It really helped with beginning to understand Magento module Development.

  6. ravi Says:

    Thanks Jim. The tutorial was simply superb

  7. AJ Tarachanowicz Says:

    Many thanks for such an informative tutorial. Have you thought about moving it over to the Magento Wiki so that it can get more exposure to the community?

  8. Manish Says:

    Wow,

    great tutorial. Followed to the end and able to create the admin component.

    This is the first first tutorial that successfully worked for me.

    Great for putting time and effort to write these 8 blogs.

  9. tight Says:

    Many thx for this howto :)

  10. gaweee Says:

    Hi Jim
    the addField is implmented in the Varien_Data_Form code. See the docs at http://docs.magentocommerce.com/Varien/Varien_Data/Varien_Data_Form_Abstract.html
    It adds a Varien Form Element. See the children of the varien form abstract element at http://docs.magentocommerce.com/Varien/Varien_Data/Varien_Data_Form_Element_Abstract.html

    If you feel up to it, you can view the source files at the /lib/Varien/Data/Form folder.

  11. jim Says:

    hi once again gawee

    Another thing, I’d be very interested in learing where you found the details on the addField function.. I have tried changing the format from text to date and get an error about other formatting it needs but finding any docs on magento regarding addField has been a nightmare :)

  12. jim Says:

    hi again,

    o.k I have been searching around for this solution however still not got any closer…

    I notice that at the end of this tutorial I can see view the hello world on the screen by going store/twit …. so i tried this..

    1. created app/frontend/default/mytheme/templates/savantdegrees/twit/index.phtml and in it just entered “test”
    2. on my home page CMS content area added :
    lock type=”savantdegrees_twit/index” my_custom=”Test” template=”twit/index.phtml” />
    This didnt work, nothing displayed on my home page.. doh.. but no errors…

    Am I at all close? :)

    cheers again,
    Jimm

  13. jim Says:

    hi again gawee

    wow I got to the end.. a really great tutorial… you have put a lot of time in i can see, thanks.

    I do have a question though…. the whole setup of the documented twits module is geared towards displaying the twits in a grid within the admin pages…. do you have any information on displaying the twits outside of the grid format, within the front end of the store? Maybe, in block form in static blocks for example?

    Thanks again,
    Jimm!

Leave a Reply