douou9786 2010-11-22 08:02
浏览 33
已采纳

DRY:建议如何不重复代码?

Ok here come my question, I have a database with such scheme

+-------------+ +------------+ +-----------+ 
+ Object      + + car        + + computer  +
+-------------+ +------------+ +-----------+
+ id          + + object_id  + + object_id +
+ some_col    + + max_speed  + + CPU_speed +
+ type        + + n_gears    + + memory    +
+-------------+ +------------+ +-----------+

So to summarize when my user input a computer for example, I create a object record, save all shared fields into it and I create a computer record with all specific data for computers being saved.

So far so good, here comes my problem by doing so I would have to duplicate every action (and controller methods view for each type of objects). So right now in my Controller, I have those actions:

  + new-car
  + new-computer
  + show-car
  + show-computer
  + edit-car
  + edit-computer
  + list-car
  + list-computer

So for each type I basically duplicate all the code and change few lines of codes (i.e replacing the car mapper by computer mapper, same for record object). I have to mention the application you the zend framework and is in PHP.

I would like to do something more "Don't repeat yourself" and not having to duplicate all the code. Any idea how to it more elegantly?

  • 写回答

3条回答 默认 最新

  • douyoupingji7238 2010-11-22 18:40
    关注

    I'll share with you my basic CRUD class. Supplied as-is. Test for yourself. Some bugs may be ;)

    <?php
    abstract class Controller_Crud extends Controller 
    {
    /* definované v dalších třídách */
    protected $_viewKey = '';
    protected $_url = 'admin/';
    protected $_modelClass;
    protected $_formClass;
    protected $_filterFormClass = null;
    protected $_title = 'Untitled';
    
    /* pro vnitřní potřebu */
    protected $_model;
    protected $_form;
    protected $_filterForm;
    private $_defaultViewKey = 'crud';
    
    /* 
     * Inicializace třídy, vytvoření instancí modelů a formulářů
     * @see Tul/Controller/Tul_Controller_Admin#init()
     */
    public function init()
    {
        parent::init();
        $this->_model = new $this->_modelClass();
        $this->_form = new $this->_formClass();
        $this->view->indexUrl = $this->_url;
        $this->view->viewKey = $this->_viewKey;
        $this->view->title = $this->_title;
    }
    
    public function postDispatch()
    {
        // Po provedení akce je nastaven titlek
        $this->view->headTitle($this->_title);
    }
    /**
     * základní akce zabezpečující výpis záznamů a filtrování
     * @return void
     */
    public function indexAction ()
    {
        if(null !== $this->_filterFormClass){
            $this->_filterForm = new $this->_filterFormClass;
        }
        $filter = null;
        if(null !== $this->_filterFormClass){
            if($this->_getParam('filter') && $this->_filterForm->isValid($this->_getAllParams())){
                $filter = $this->_filterForm->getValues();
            }
            $this->_filterForm->populate($this->_getAllParams());
    
        }
        /* @var Tul_Paginator */
        $paginator = $this->_model->getAllPaginator($filter);
        $paginator->setCurrentPageNumber($this->_getParam('page',1));
        $this->view->data = $paginator;
        $this->view->form = $this->_filterForm;
    }
    
    /* 
     * Načte ID záznamu a pokud není nalezeno přesměruje s chybovou hláškou na hlavní stránku
     * @see Tul/Controller/Tul_Controller_Admin#getId()
     */
    public function getId()
    {
        $id = $this->_getParam('id', false);
        if(false === $id){
            $this->addFlashMessage('error','Neplatné ID.');
            $this->_gotoUrl($this->_url);
        }
        return $id;
    }
    
    /**
     * akce pro přidání nového záznamu
     * @return void
     */
    public function pridatAction ()
    {
        $this->view->headTitle('Přidat');
        if ($this->_request->isPost()) {
            if ($this->_form->isValid($_POST)) {
                $data = $this->_form->getValues();
                try {
                    $this->_beforeAdd($data);
                    $result = $this->_model->insert($data);
                    $this->_afterAdd($data, $result);
                    $this->addFlashMessage('success','Úspěšně přidáno. ');
                } catch (Exception $e){
                    $this->addFlashMessage('error','Došlo k chybě při přidávání:<br />' . htmlspecialchars($e->getMessage()));
                }
                $this->_gotoUrl($this->_url);
            } else {
                $this->_form->populate($_POST);
            }
        }
        $this->view->form = $this->_form;
        $this->_renderView('pridat.phtml');
    } 
    
    /**
     * Akce pro smazání záznamu
     * @return void
     */
    public function smazatAction ()
    {
        $id = $this->getId();
        try{
            $this->_beforeDelete($id);
            $result = $this->_model->delete($this->_model->quoteInto('id = ?',$id));
            $this->_afterDelete($id, $result);
            $this->addFlashMessage('success','Úspěšně smazáno. ');
        } catch (Exception $e){
            $this->addFlashMessage('error','Došlo k chybě při mazání:<br />'.htmlspecialchars($e->getMessage()));
        }
        $this->_gotoUrl($this->_url);
    } 
    
    /**
     * akce pro úpravu záznamu
     * @return void
     */
    public function upravitAction ()
    {
        $this->view->headTitle('Upravit');
        $id = $this->getId();
        $item = $this->_model->getById($id);
        if ($this->_request->isPost()) {
            if ($this->_form->isValid($_POST)) {
                $data = $this->_form->getValues();
                try {
                    $this->_beforeUpdate($data, $item);
                    $result = $this->_model->update($data, $this->_model->quoteInto('id = ?',$id));
                    $this->_afterUpdate($data, $result);
                    $this->addFlashMessage('success','Úspěšně upraveno. ');
                } catch (Exception $e){
                    $this->addFlashMessage('error','Došlo k chybě při úpravě:<br />'.htmlspecialchars($e->getMessage()));
                }
                $this->_gotoUrl($this->_url);
            } else {
                $this->_form->populate($_POST);
            }
        } else {
            $this->_form->populate((array)$item);
        }
        $this->view->form = $this->_form;
        $this->_renderView('upravit.phtml');
    }
    
    /**
     * Pokud existuje načte pohled zděděné třídy, pokud neexistuje použije interní
     * @param $name string název pohledu
     * @return void
     */
    private function _renderView($name)
    {
        $completeName = $this->_viewKey . '/' . $name;
        /* @var Zend_View_Abstract */
        foreach ($this->view->getScriptPaths() as $dir) {
            if (is_readable($dir . $completeName)) {
                return $this->renderScript($completeName);
            }
        }
        return $this->renderScript($this->_defaultViewKey . '/' . $name);
    }
    
    /**
     * Metoda, která je zavolaná těsně před přidáním záznamu. 
     * Umožňuje upravit data podle potřeby před vložením do databáze. 
     * Vyhozením vyjímky přidání záznamu skončí chybou
     * @param $data array data, která budou přidána
     * @return void
     */
    protected function _beforeAdd(&$data){}
    /**
     * Metoda, která je zavolaná těsně po přidání záznamu. 
     * Umožňuje upravit data podle potřeby ještě po vložení do databáze. 
     * Vyhozením vyjímky přidání záznamu skončí chybou
     * @param $data array data, která budou přidána
     * @param $result mixed primární klíč přidaného záznamu
     * @return void
     */
    protected function _afterAdd(&$data, $result){}
    /**
     * Metoda, která je zavolaná těsně před úpravou záznamu. 
     * Umožňuje upravit data podle potřeby ještě před úpravou v databázi. 
     * Vyhozením vyjímky uprava záznamu skončí chybou
     * @param $data array data, která budou upravena
     * @param $item mixed původní data
     * @return void
     */
    protected function _beforeUpdate(&$data,$item){}
    /**
     * Metoda, která je zavolaná těsně po úpravě záznamu. 
     * Umožňuje upravit data podle potřeby po úpravě v databázi. 
     * Vyhozením vyjímky uprava záznamu skončí chybou
     * @param $data array data, která budou upravena
     * @param $result integer počet ovlivněných záznamů
     * @return void
     */
    protected function _afterUpdate(&$data,$result){}
    /**
     * Metoda, která je zavolána před smazáním záznamu. 
     * Vyhozením vyjímky smazání záznamu skončí chybou
     * @param $id id mazaného záznamu
     * @return void
     */
    protected function _beforeDelete($id){}
    /**
     * Metoda, která je zavolána po smazání záznamu. 
     * Vyhozením vyjímky smazání záznamu skončí chybou
     * @param $id id mazaného záznamu
     * @param $result počet smazaných řádků
     * @return void
     */
    protected function _afterDelete($id, $result){}
    
    }
    

    And then a concrete implementation:

    <?php
    class FunkceController extends Controller_Crud
    {
        protected $_url = '/admin/funkce/';
        protected $_modelClass = 'Admin_Functions';
        protected $_formClass = 'Form_Admin_Functions';
        protected $_filterFormClass = 'Form_Admin_FilterFunctions';
        protected $_viewKey = 'funkce';
        protected $_title = 'Funkce';
    }
    

    Hope this helps ;)

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥15 在获取boss直聘的聊天的时候只能获取到前40条聊天数据
  • ¥20 关于URL获取的参数,无法执行二选一查询
  • ¥15 液位控制,当液位超过高限时常开触点59闭合,直到液位低于低限时,断开
  • ¥15 marlin编译错误,如何解决?
  • ¥15 有偿四位数,节约算法和扫描算法
  • ¥15 VUE项目怎么运行,系统打不开
  • ¥50 pointpillars等目标检测算法怎么融合注意力机制
  • ¥20 Vs code Mac系统 PHP Debug调试环境配置
  • ¥60 大一项目课,微信小程序
  • ¥15 求视频摘要youtube和ovp数据集