02. Использование Zend_Layout и помощников видов.


    В этой статье оптимизируем работу со скриптами видов используя, специально для этого предназначенные, компоненты фрэймворка. В 90% случаев, для каждой страницы, у нас одинаковые шапка и подвал. Чтобы не прописывать в каждом файле require('header.phtml'), require('footer.phtml'), будем использовать компонент Zend_Layout, к тому же это даст нам возможность использовать несколько полезнейших помощников видов по назначению.

    Начнем с того, что создадим макет сайта. В папку с видами нужно добавить файл layout.phtml

    app/views/layout.phtml

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru" lang="ru" dir="ltr">
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
	<title>Демо-сайт</title>
</head>
<body>
<div id="header">
	<h1>Демо-сайт</h1>
	<p><em>Только для примера</em></p>
</div>
<div id="menu">
	<a href="<?php echo HOST.BASEURL;?>/">Главная</a> 
	<a href="/index/about" title="Главная">О сайте</a>
</div><br /><br />
<div id="content">
	<!-- вывод скрипта вида -->
	<?php echo $this->layout()->content; ?>

</div><br /><br />
<div id="footer">
	<p class="textRight"> © 2009 2Developers.Net</p>
</div>
</body>
</html>

    Для того, что бы посмотреть как это работает изменим скрипт вида для действия index, оставив в нем только одну строку:

    app/views/index/index.phtml

<?php echo $this->message; ?>

    и для наглядности примера, добавим еще одно действие в index-контроллер, в результате, чего он будет иметь следующий вид:

    app/controllers/IndexController.php

require_once 'Divo/Controller.php';

class IndexController extends Divo_Controller 
{	
	public function divoInit() //__construct()
	{ }
	
	public function indexAction()
	{
		$this->view->assign("message", "Текст главной страницы");
	}
	
	public function aboutAction()
	{ }
}

    еще придется добавить скрипт вида для aboutAction с примерно таким текстом:

    app/views/index/about.phtml

<p>Страница с текстом о сайте и может быть контактной формой.</p>

    Теперь что бы заработало нужно прописать 2 строки в контроллере:


require_once 'Zend/Layout.php';
Zend_Layout::startMvc();

     Но что бы не писать это в каждом действии, следует добавить один метод запускающий layout в базовый контроллер (Divo_Controller) и вызывать его при каждом обращении к скрипту:

    lib/Divo/Controller.php

/** Базовый Класс между Zend_Controller_Action и нашими контроллерами действий.
	Содержит базовые методы которые необходимо использовать в более чем одном контроллере */

require_once 'Zend/Controller/Action.php';

class Divo_Controller extends Zend_Controller_Action
{
	public function init()
	{
		// Если каталог www расположен не в корне сервера (см. 11 строка www/index.php)
		if (BASEURL !== "") {
			$this->getRequest()->setBaseUrl(BASEURL.'/');
		}
		
		/** Настройки вида */
		// Указываем где искать скрипты вида
		$this->view->setScriptPath(APPPATH.'/views/');
		
		// Запустить layout
		$this->_divoStartLayout();

		$this->divoInit();
	}
	
	/** Используется вместо конструктора в дочерних контроллерах */
	public function divoInit()
	{	}

	// Метод запускающий layout
	private function _divoStartLayout()
	{
		require_once 'Zend/Layout.php';
		
		$options = array(
			'contentKey' => 'content', // Есть еще опции см. в мануале
		);
		Zend_Layout::startMvc($options);
	}
}

    теперь можно пробовать.

    Помощники видов (View Helpers).


    В составе Zend Framework, поставляются несколько незаменимых помощников видов, которые нам пригодятся для полноценной работы с Zend_Layout - это HeadMeta Helper, HeadScript Helper, HeadStyle Helper и HeadTitle Helper.

    Что бы увидеть их в работе, изменим наш макет:

    app/views/layout.phtml (часть)

<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />

<?php echo $this->headMeta() ?>

<?php echo $this->headTitle('Демо-сайт'); ?>

<link rel="stylesheet" type="text/css" href="/css/style.css" />
<?php echo $this->headStyle(); ?>

<?php echo $this->headScript(); ?>

</head>

    HeadMeta Helper


    Предназначен для добавления мета-тегов в заголовок html документа, из скриптов вида. Для того что бы добавить на главную мета-тэги keywords и description напишем следующие строки в скрипте вида indexAction:

    app/views/index/index.phtml

$this->headMeta()->appendName('keywords', 'демо, тест, ZF, фрэймворк, PHP');
$this->headMeta()->appendName('description', 'Демо-сайт. Разработано с использованием Zend Framework');
$this->headMeta()->appendName('copyright', '© 2009 2Developers.Net');

    Теперь вы можете увидеть что в заголовке главной страницы появилась следующая информация для поисковых машин, на том месте где в Layout.phtml (строка 6) мы вызывали HeadMeta-хелпер.

<meta name="keywords" content="демо, тест, ZF, фрэймворк, PHP"  />
<meta name="description" content="Демо-сайт. Разработано с использованием Zend Framework"  />
<meta name="copyright" content="2Developers.Net 2009"  />

    Еще существует способ добавлять мета-тэги с информацией для браузера:

    пример:

$this->headMeta()->appendHttpEquiv('Refresh', '3; URL=http://zf-demo.2developers.net');

    результат:

<meta http-equiv="Refresh" content="3; URL=http://zf-demo.2developers.net"  />

    HeadScript Helper


    Предоставляет два полезнейших метода, незаменимых при работе с Zend_Layout, которые позволяют подключать файлы .js в заголовок страницы, вызывая хелпер из скриптов вида:


    пример:

$this->headScript()->appendFile('/js/example.js');

    результат:

<script type="text/javascript" src="/js/example.js"></script>

    И самое интересное, отображать javaScript-код (написанный в скрипте вида), в заголовке страницы во время выполнения:


<?php $this->headScript()->captureStart() ?>
	bkLib.onDomLoaded(
	function() 
	{ 
		nicEditors.allTextAreas({fullPanel : true})
	});
<?php $this->headScript()->captureEnd(); ?>

    вывод:

<script type="text/javascript">
//<!--
	bkLib.onDomLoaded(
	function() 
	{ 
		nicEditors.allTextAreas({fullPanel : true})
	});
//-->
</script>

    Весь вывод, после вызова метода captureStart() и до вызова captureEnd(), будет подставлен на место, где вызывается данный помощник в Layout.phtml (строка 13).

    HeadStyle


    Работает, точно по такому же принцпу как и HeadScript-хэлпер, только служит для вывода и подключения каскадных таблиц стилей.

    пример:

$this->headStyle()->appendStyle('/css/example.css');

    результат:

<link rel="stylesheet" type="text/css" href="/css/example.css" />

    пример (из ZF-мануала):

<?php $this->headStyle()->captureStart() ?>
body {
	background-color: <?= $this->bgColor ?>;
}
<?php $this->headStyle()->captureEnd() ?>

    HeadTitle Helper


    Дает возможность указать заголовок страницы в любое время, для этого в скрипт вида следует добавить:


$this->headTitle('Главная страница');

    в том случае, если в Layout был передан заголовок по умолчанию

<?php echo $this->headTitle('Демо-сайт'); ?> // Демо-сайт (по умолчанию)

    то хэлпер будет добавлять указанные заголовки в начало:

    app/views/index/index.phtml


$this->headTitle('Главная страница ');

    результат:

<title>Главная страница Демо-сайт</title>

    Чтобы части составного заголовка не смешивались, установим разделитель строк для хэлпера HeadTitle методом setSeparator() в базовом контроллере

    lib/Divo/Controller.php (часть)

public function init()
{
	// Если каталог www расположен не в корне сервера (см. 11 строка www/index.php)
	if (BASEURL !== "") {
		$this->getRequest()->setBaseUrl(BASEURL.'/');
	}
	
	/** Настройки вида */
	// Указываем где искать скрипты вида
	$this->view->setScriptPath(APPPATH.'/views/');
	$this->view->headTitle()->setSeparator(' | ');
	
	// Запустить layout
	$this->_divoStartLayout();

	$this->divoInit();
}

    Это все, что касается компонента Zend_Layout в нашем приложении, а использование других хэлперов вида, в том числе и написание своих, рассмотрим позже в следующих статьях.


Прикрепленные файлы:

ZF - Layout & Helpers (Загрузок: 82)

Добавлена: 31-01-2009 | Изменена: 08-02-2009 | Пользователем: djaarf | Просмотров: 5220

Комментарии

lcf 17-03-2009 02:07
  •  - Вот так: я бы не рекомендовал делать, это как-то не вписывается малость в общую красоту и интуитивность. Обычно делают view helper baseUrl() или, просто устанавливают такую переменную (baseUrl) в объект вида на этапе инициализации.
  •  - Процесс инициализации лэйаута, вместе с хитрым нагроможеднием инициализаций (divoInit) также ведет к тому что страдает интуитивность кода. Кроме того, это решение... не то чтобы неправильное (оно ведь работает), но, вообщем и целом с точки зрения проектирования оно не совсем корректно, так как эти методы помещать в родительский контроллер и тащить по всем объектам нет никакого смысла - все эти настройки совершенно спокойно и правильно делаются один раз на этапе конфигурации приложения, перед запуском цикла диспетчеризации (в bootstrap так называемом). А что если вам придется выполнить за одно отображение страницы 2 действия разных контроллеров ( с помощью добавления в ActionStack)? А что если вы воспользуетесь _forward на другой контроллер? Ведь инициализация будет занова вызвана и все эти методы запуска лэйаута тоже... Может оно и работает, но, пожалуй, все таки нет - такой подход не верен. Махинации по настройке окружения надо делать до запуска диспчетеризации и уж конечно их не стоит помещать в контроллер.
  •  - Первое сообщение мой, так что еще замечание организационного характера - просто как личное мнение, не более - читать код при таком сочетании фонов, почему то неудобно (может быть символы слишком большие).
lcf 17-03-2009 02:34

Я так понимаю пхп код вырезался вначале? Я вообще то там писал что вот так: ?php echo HOST.BASEURL; не стоит делать.

Мне кажется вырезать теги на сайте про программирование как-то не того. Может их просто заменять на соотвествующие значки?) И предлагаю сделать как на вашем другом сайте программерз (я там уже тоже один гадкий комментарий оставил, простите :))) делать возможность вставки кода и как-то об этом написать как там, по-моему было удобно.

Или эт я напутал и сдуру нескопипастил ваш код? Тест:

djaarf 17-03-2009 02:46
  • 1. Нечего сказать, конечно так и нужно делать, но по большей части приложения находятся в корне сервера и засорять скрипты вида байзурлом кажется нецелесообразным, в демо + еще позже прибавляется к этой каше в видах еще и $this->translate('для всех текстов'), хотя с другой стороны где еще как не в демо.
  • 2. Вызов метода в другом контроллере!!! Отличное замечание, поэкспериментирую... возможно bootstrap в совокупности с отчищением родительского контроллера, действительно решает ту проблему о которой я не догадывался.
  • 3. Спасибо учту.

djaarf 17-03-2009 02:48
Тест провален 10 минусов ))! Спасибо, поправим...
djaarf 17-03-2009 02:49
Не говорите о времени добавления комментариев )
cccp_mockba 22-10-2009 17:33
С использованием хелперов, хидер получится примерно так. Помоему лайоуты лучше разделить на хидер, футер, контент. Можно будет заменить только отдельную часть.

<?php echo $this->doctype() ?>
<head>
    <base href="<?php echo $_SERVER['HTTP_HOST'] ?>" />
    <?php
        $this->headMeta()->appendHttpEquiv('Content-Type', 'text/html; charset=utf-8'); //Указываем кодировку
        $this->headTitle()->setSeparator(' - '); //Указаваем сеператор для разделения текста в тайтле
        $this->headLink()->appendStylesheet('/css/global.css'); //Добавляем CSS

        $this->headScript()->prependFile('/js/jquery/jquery.min.js'); //Добавляем JS
    ?>
    <?php echo $this->headTitle($this->translate('My First Project'))) ?>
    <?php echo $this->headMeta() ?>
    <?php echo $this->headLink() ?>
    <?php echo $this->headScript() ?>
</head>


Оставить комментарий



Капча *

Captcha

Комментарий будет опубликован после проверки модератором

Для подсветки синтаксиса исходный код следует обрамлять следующими тэгами
<pre><code class="синтаксис" >код</code></pre>
Подерживаются следующие: cpp php javascript sql html-xml css ini