📜 ⬆️ ⬇️

We use delegation together with inheritance to organize action controllers

Good afternoon, colleagues, today I will tell a fairy tale about my experience in organizing controllers in a project on ZF 1 (as historically).
In good OOP books, it is often written that inheritance cannot be carried away, one should prefer delegation or make them work together. Unfortunately, it is not always possible to quickly figure out how to apply a dry theory in practice (and when it finally comes to, you wonder “what’s so complicated?”), So I hope my experience will come in handy for someone.

And so first about the problem area:
31 Controller Action, most of them have indexAction (), addAction (), editAction (), searchAction () methods.
Problem number 1: most, but not all. In the rest, the availability of these methods varies,
Problem # 2: The editAction () and addAction () methods are massive in their own right, and almost the same for all controllers, form initialization differs, and the model is saved.

How I decided it, I will show it immediately in the code.

Fragment of base class controllers
Class Common_Controller extends Zend_Controller_Action { /** *     . * @var string; */ protected $modelClass = ''; /** *       . * @var string; */ protected $editFormClass = ''; /** * JS ,   ,      . * @var string; */ protected $jsModelFile = ''; /** *     , *  $id  -   ,   -  . * * @param mixed $id; * @return Model_Record $model; */ protected function modelFactory( $id = null ) { $modelClass = $this->modelClass; if ( $id ) { $model = $modelClass::find( $id ); } else { $model = $modelClass::create(); } return $model; } /** *      . * * @param Model_Record $model; * @return Zend_form $form; */ protected function formFactory( Model_Record $model ) { $formClass = $this->editFormClass; $form = new $formClass(); $form->setDefaults( $model->toArray(1) ); return $form; } /** *       . * * @param Model_record $model; * @param Zend_Form $form; */ protected function save( Model_Record $model , Zend_Form $form ) { $model->fromArray($form->getValues(), false); $model->save(); } /** *   , *     editAction()   . */ protected function _editActionHelper() { $id = $this->_request->getParam('id'); if ( !$id ) { throw new Zend_Controller_Action_Exception('  ' , 404); } //   $model = $this->modelFactory($id); if ( !$model ) { throw new Zend_Controller_Action_Exception('  ' , 404); } $this->view->model = $model; //   $this->view->PageTitle = $model->getFullTitle(); //    $form = $this->formFactory( $model ); $this->view->form = $form; //    get- -   ( ) ,     if ( $this->_request->isGet() ) { $form->redirect->setValue( $_SERVER['HTTP_REFERER'] ); } // ,       // ... //   $model->lock(); // js   if ( $this->jsModelFile ) { $this->view->headScript()->appendFile( '/js/models/' . $this->jsModelFile ); } //   if ( isset($_POST['save']) || isset($_POST['saveExit']) ) { //  if ( $form->isValid( $this->_request->getPost() ) ) { //   try { Model::connection()->beginTransaction(); $this->save( $model, $form ); Model::connection()->commit(); $model->releaseLock(); $this->view->Flash()->addSuccess( 'Success !' ); // ,     //      $redirect = '/' . $this->_request->getControllerName() . '/edit/id/' . $model->ID . '?redirect=' . $this->_request->getParam('redirect', '/'); //    if ( isset($_POST['saveExit']) ) { $redirect = $this->_request->getParam('redirect', '/'); } $this->_redirect( $redirect ); } catch (Exception $e) { Model::connection()->rollback(); $this->view->Flash()->addError( $e->getMessage() ); } } else { $this->view->Flash()->addError("   "); } } } } 

Protected The modelFactory () method creates an instance of the model associated with a particular controller. The model class is specified in the $ this-> modelClass variable and in most cases, customization ends there. If the model needs to be initialized in a special way, then we simply redefine this method in a particular controller.
')
Protected formFactory () method creates an editing form, customization is similar to modelFactory ().

The protected (save) method saves data from the submitted form to the transferred model, there is also room for maneuver, if in a particular controller the entity saving is spreading. The presence of such a method in the controller can be in doubt, therefore I will explain that in save () only calls to additional methods of the model are allowed, there are no sql queries, for this we define methods like addTag (), setChannles (), etc. instead of a single opaque saveFromArray () method.
With such a composition, the model and the form know nothing about each other, and the controller plays the role of an integrator.

The last protected method in this snippet is _editActionHelper (), if in the derived class we need support for editing the entity, then we simply add a method to it:
  public function editAction() { $this->_editActionHelper(); } 

Similarly for other common methods. Fragment of the derived controller for the example:
 Class Video extends Common_Controller { protected $modelClass = 'Video'; protected $editFormClass = 'Form_Video'; protected function save( Model_Record $model , Zend_Form $form ) { parent::save( $model , $form ); $model->setChannels( $form->channels->getValue() ); } public function editAction() { $this->_editActionHelper(); } public function addAction() { $this->_addActionHelper(); } public function indexAction() { $this->_indexActionHelper(); } } 


PS please, if something is wrong, write in the comments, it will be useful to all readers.

Source: https://habr.com/ru/post/213971/


All Articles