Answer the question
In order to leave comments, you need to log in
MVC, what is the best way to avoid code duplication?
Hello everyone, I've been programming in yii for 2 years now, but I still don't know how to properly avoid code duplication in my controllers. All the time the same same type of question in all my projects. Maybe the habrasoobshchestvo can help me figure it out?
Example
Let's say we have a product catalog site where all products depend on the selected locality and may have reviews. An example from life is given in a very simplified form.
If we specify the task, we get:
<font color="black"><font color="#0000ff">class</font> CRUDController {<br/> <font color="#008000">// тут получаем список всех моделей и передаем вьюхе</font><br/> <font color="#0000ff">public</font> function actionIndex(){}<br/> <font color="#008000">// страница просмотра инф-ии о модели</font><br/> <font color="#0000ff">public</font> function actionView(){}<br/> <font color="#008000">// тут обрабатываем создание модели</font><br/> <font color="#0000ff">public</font> function actionCreate(){}<br/> <font color="#008000">// тут редактирование</font><br/> <font color="#0000ff">public</font> function actionUpdate(){}<br/> <font color="#008000">// и удаление</font><br/> <font color="#0000ff">public</font> function actionDelete(){}<br/> <font color="#008000">// к этому методу обращаются view, update и delete</font><br/> <font color="#0000ff">protected</font> function loadModel($id){<br/> $model=CActiveRecord($<font color="#0000ff">this</font>->modelClass)->findByPk($id);<br/> <font color="#0000ff">if</font>(!isset($model))<br/> <font color="#0000ff">throw</font> <font color="#0000ff">new</font> CHttpException(404,<font color="#A31515">'страница не найдена'</font>);<br/> }<br/> }<br/> </font><br/> <font color="gray">* This source code was highlighted with <a href="http://virtser.net/blog/post/source-code-highlighter.aspx"><font color="gray">Source Code Highlighter</font></a>.</font>
Answer the question
In order to leave comments, you need to log in
First of all, decide what you really want. It is not clear why the lack of verification of the parent is unprofessional. If it is not needed, then unprofessionalism is just writing it for the sake of some abstract idea. For example, for a region, it may be necessary to make a separate page if there is a country and it does not exist (“there is no such region for the specified country”). If all errors lead to the same inscription “page not found”, then additional checks are useless.
The next step is to decide on the implementation. But here you should already be more aware of what kind of architecture you have. In fact, everything proposed above comes down to the classic Strategy pattern: we leave all the general functionality in the parent class, and transfer all the particulars (the key point is that there should be few of them) to the heirs. In your case, the ancestor will be CRUDController with the implementation of methods tied to modelClass, and the descendants will be classes that define this modelClass and the checkRequest method. Jerking checkRequest prescribe where you like. I don’t know how Yii works, but if it allows you to create controllers of arbitrary classes without inheriting from anyone, then it makes sense to generally declare CRUDController abstract and write the checkRequest abstract method in it. Then it will be generally Strategy from the book, and you will get the opportunity to use checkRequest in other CRUDController methods without fear that it is not defined in the heirs. And usually in modern frameworks there is a method that twitches before any controller action. Perhaps there is the right place for your checkRequest.
Continuing to fantasize about the topic, you can make the type of the modelClass model passed in the parameter. Or receive it based on what you were given. You just need to make a map of valid values. Something like
array( ... 'region' => array( 'model' => 'regionModel', 'parent' => 'countryModel' ), 'country' => array( 'model' => 'countryModel', 'parent' => null ) )
Yii has a nice extension mechanism. Up to redefining base classes. So, it could well be done not at the controller level. Make some analogue of the function of the checkAccess() method
I don’t know how with this in puff, but in java I would inherit from one class in which I would implement the necessary common functions
You did not take into account all the rules - you created it in the wrong section. :) Throw it into posts.
Well, this is a question, as it were, I myself do not know how to do it right. Does it make sense to transfer? Since the introduction is gone, the meaning is not entirely clear. I'll rewrite it now.
I would do it stupidly, in the forehead: I would write
a separate function (not a method, but just a function) that checks all four parameters and returns 0 - if everything is ok, or a value from 1 to 15, as flags for invalid parameters.
<?php
function check4($a, $b, $c, $d)
{
return check1($a)+check1($b)*2+check1($c)*4+check1($d)*8;
}
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question