MVC: сколько кода должно быть в представлении?

Я веб-разработчик, и я долгое время был кодером. Но я никогда не использовал чистую архитектуру MVC. Теперь я начал собственный проект и решил сделать html-css самостоятельно и нанять кодера. Мы выбрали популярную инфраструктуру PHP-MVC.

Первые шаги сделаны, некоторые страницы закодированы. И, посмотрев на результат, у меня возник вопрос … сколько кода должно быть в шаблонах (View)?

Например, вот файл шаблона:

<?php $this->load->view('header'); ?> <?php $this->load->view('banner'); ?> <div id="items"> <?php for($i=0; $i<count($main); $i++) { echo '<div class="item"> <div class="name">'.$main[$i]['name'].'</div>'; if($main[$i]['icq']=='') { } else { echo '<div class="phone">'.$main[$i]['phone'].'</div>'; } echo '</div>'; } ?> </div> <?php $this->load->view('footer'); ?> 

Считаете ли вы, что в этом шаблоне слишком много кода, или это нормально?

Related of "MVC: сколько кода должно быть в представлении?"

Первый ответ на самом деле был на месте, но пользователь удалил его (возможно, из-за давления сверстников). В принципе, вам не нужна логика в вашем шаблоне . В идеальном мире у вас есть тег для всех данных модели, но поскольку мы находимся в мире HTML, его нет, поэтому вам нужно либо использовать XSLT, либо использовать ViewHelpers.

Давайте сосредоточимся на подходе ViewHelper.

Это трудно поддерживать:

 <div id="items"> <?php for($i=0; $i<count($main); $i++) { echo '<div class="item"> <div class="name">'.$main[$i]['name'].'</div>'; if($main[$i]['icq']=='') { } else { echo '<div class="phone">'.$main[$i]['phone'].'</div>'; } echo '</div>'; } ?> </div> 

И это не улучшится, если вы замените PHP Smarty. Это легко поддерживать:

 <div id="items"> <?php echo itemlist($items, 'template.htm') ?>; </div> 

Ниже вопроса, который теперь был удален, был комментатор, возражающий против этого «кода, который нелегко поддерживать для некодиров, потому что теперь они не знают, где определен элемент itemlist и что он делает». но это полная тарабарщина. Подумайте об этом на секунду.

С одной стороны, они утверждают, что у некодеров есть проблемы с простым вызовом функции, но, с другой стороны, они ожидают, что они поймут мишмар PHP-кода, смешанный с HTML. Дизайнеру не нужна логика представления, а только фактическая презентация. Выход.

В одном вызове функции четко сказано: «вот список предметов», который гораздо легче понять, чем «здесь for этого есть эхо-сигнал div и, возможно, что-то еще, если icq задан». Вызов функции так же хорош, как и тег. Он имеет четко определенные входные и выходные данные. Как это достигается, выход не подходит никому, кроме разработчика.

Ваш ViewHelper инкапсулирует логику представления. Это фрагмент, который вы можете использовать во всех своих представлениях. Это намного удобнее, чем копировать и вставлять всю эту логику снова и снова, когда это необходимо. В приведенном выше примере для помощника есть два аргумента:

  • $ items – массив или другой доступный тип, содержащий ваши фактические данные элемента
  • «template.htm» – это имя файла шаблона, используемого для визуализации данных

Я сделаю второй вариант необязательным, потому что я предполагаю, что это всегда один и тот же шаблон. Но поскольку комментатор жаловался, что не-кодер не знал, где искать, я счел необходимым показать, как легко сказать не кодеру, где искать.

 function itemlist($items, $template = './templates/itemlist.htm') { ob_start(); foreach($items as $item) { include $template; } return ob_get_flush(); } 

Могут быть более эффективные подходы к решению вопроса о включении шаблона. Однако основная идея должна быть ясной. Скрыть логику представления от фактического шаблона. Тогда ваш «template.htm» будет выглядеть так:

 <div class="item"> <div class="name"><?php echo $item['name'] ?></div> <?php echo contact($item, 'icq' 'phone'); ?> </div> 

Нет, если и elses. Никаких конкатенаций строк или фигурных скобок. Логику решения, с которой можно связаться с пользователем, также скрывается в ViewHelper. Все, что не-кодер должен знать, теперь являются аргументами для ViewHelpers, и это так же просто, как знать, какой атрибут писать в тег. При необходимости дайте им чит-лист.

Связанная информация:


РЕДАКТИРОВАТЬ

Из-за двух комментариев ниже я решил расширить этот ответ. Вышеизложенное не абстракция для абстракции. Он предназначен для повторного использования и ремонтопригодности. Я уже указал это выше, но позвольте мне объяснить это здесь.

На самом деле, мне кажется странным возражать против использования ViewHelpers, потому что у вас будет «презентация в двух местах», но не жалуйтесь на разделение заголовка, баннера и нижнего колонтитула. Это то же самое. Вы изолируете детали, которые можно использовать повторно и помещать в свои собственные шаблоны. Разделение логики из шаблона на этом шаге является просто естественным следующим шагом для достижения еще большей ремонтопригодности.

Шаблон представления, содержащий логику, фактически является скриптом, а не шаблоном. Любой шаблон представления, содержащий логику для сборки, обречен на повторение. Это может быть не проблема с небольшими сайтами, но если вы работаете на сайте с несколькими дюжинами или даже сотнями просмотров и виджетов, не абстрагируя эти части, это приведет к дублированию кода. Поместите всю логику в шаблон, и он быстро превратится в запутанную беспорядочную разметку c & p'ed, смешанную с условностями. Для любого дублирования вы удвоите время, необходимое для его изменения. Добавьте встроенные стили и навязчивый Javascript, и вы находитесь в обслуживании ад.

Если вы используете ООП для других частей своего приложения, то почему вы считаете процедурным на ваш взгляд? Если вы поняли, что вы должны отделять Javascript и CSS от своего HTML, почему вы должны смешивать PHP в свой шаблон? Это не имеет смысла. Фрагмент кода OP – это скрипт, а не шаблон. Таким образом, это домен разработчика. И из-за этого вы применяете всю хорошую практику, применяемую к другим частям вашего приложения. И это включает выделение логики в функции и / или классы.

Конечно, дизайнер, смотрящий на скрипт, может не сразу узнать, что происходит. Но опять же, возможно, она не знает об этом, как только вы начнете добавлять собственные функции PHP. Что делает mb_strimwidth ? И substr ? Что это ?: Построить? Чем более актуальным PHP вы добавите, тем труднее будет читать для не-разработчиков.

Если вы хотите, чтобы дизайнеры работали над шаблонами, не давайте им сценариев. Дайте им шаблоны. И если вы это сделаете, изолируйте от него логику и замените ее на простые вызовы функций. Используйте имена функций, которые четко сообщают, что делает функция. Поэтому дизайнеру нужно только знать, «если я использую это с этим вводом, я всегда буду получать этот вывод. Мне все равно, как это будет происходить. Я оставлю это разработчику».

Выделение логики в функции (или классы) также дает вам непосредственное преимущество в том, что вы можете протестировать логику, используемую для отдельного отображения отдельных частей на этой странице. Вам не нужно настраивать всю среду, необходимую для создания страницы, а просто передавать требуемый ввод и утверждать, что он выводится (поэтому функция буферизует строку, а не выводит ее btw).

¹ Для тех из вас, кто считает, что это не проблема, я настоятельно рекомендую найти себе устаревшее приложение, которое действительно сохраняет всю логику в шаблоне представления. Попытайтесь изменить несколько вещей. Как только вы получили удовольствие от еды по 2500 строк кода спагетти с по меньшей мере 500 символами каждый и содержащим сочетание повторяющихся PHP, HTML, CSS и JavaScript, вы узнаете, о чем я говорю.

Я не думаю, что вы пытаетесь достичь в представлении слишком много логики, но я думаю, что ее нужно немного очистить.

Что-то вроде:

 <?php foreach($main as $item): ?> <div class="item"> <div class="name"><?php echo $item['name']; ?></div> <?php if($item['icq']): ?> <div class="phone"><?php echo $item['phone']; ?></div> <?php endif; ?> </div> <?php endforeach; ?> 

Я считаю, что читать намного проще, и он выполняет ту же работу. Я также не думаю, что было бы сложно изменить не-кодер, что в конечном итоге является целью представления.

Когда шаблоны требуют много логики, может быть полезно ввести шаблон ViewModel

Логика, определяющая, когда отображается определенный блок, помещается в модель представления.

пример
Фрагмент шаблона:

 <?php if($item['show_phone_number']): ?> <div class="phone"><?php echo $item['phone_number']; ?></div> <?php endif; ?> 

Фрагмент модели представления:

 $item['show_phone_number'] = $item["icq"] == ''; 

короткий ответ:

Достаточно мало возможностей.

Просмотр не является шаблоном.

Или, по крайней мере, это не шаблон. Представления, как правило, представляют собой классы классов, которые отвечают за работу с презентационной логикой . Они жонглируют несколькими шаблонами и решают, какой из них использовать и какие данные передаются в них.

Но у CI этого нет. Вы в основном застряли в шаблоне, который претендует на роль «Вид», а также экземпляры ActiveRecord, которые они говорят вам, это «Модели». Ад .. в правильном MVC модель не является даже конкретным классом, а прикладным уровнем.

В долгосрочной перспективе эта ситуация заставит логику представления и бизнес-логику войти в контроллер, в то же время создавая жесткие шаблоны и классы activerecord.

Я думаю, что у Джеймса слишком много кода, но вы можете добавить переменную массива в функцию get_items (), чтобы управлять префиксом и суффиксом каждого элемента, например:

 $options = Array('item_prefix' => '<div class="item">', 'item_suffix' => '</div>'...) echo get_items(); 

В ваших представлениях обязательно должно содержаться большинство тегов html, поэтому я не думаю, что функция get_items должна быть размещена где-то в другом месте. Просто немного очистите свои шаблоны и работайте с альтернативным синтаксисом цикла, предложенным Карпи. Вы также можете подумать об использовании какого-либо существующего механизма моделирования шаблонов, такого как Twig, но с тем, что представления должны содержать некоторые ссылки на ваши данные … Что вы хотите достичь, так это то, что некодиры могут редактировать ваши html-файлы, не понимая слишком много логики сценариев.