Задача – создать хелпер для отображения картинок во вьюхах, не заботясь каждый раз о путях.
Наше приложение поддерживает различные скины (используются стандартные зендовские layout’ы), структура папок следующая:
/layouts/default/images/myfile.png
/layouts/otherskin/images/myfile.png
в зависимости он настройки resources.layout.layout в конфигурационном файле, будет показана та или иная картинка (равно как та или иная вьюха и пр.)
В клиентском коде же хочется иметь универсальный механизм:
$this->image('myfile.png'); |
который сам будет отображать ту или иную картинку.
Приступим.
Для начала напишем юнит тест (используя phpunit), заодно определимся со всеми требованиями:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | <?php class ImageTest extends ControllerTestCase { private $_imgHelper; public function setUp() { parent::setUp(); $viewStub = $this->getMock('Zend_View'); $viewStub->expects($this->any()) ->method('escape') ->will($this->returnArgument(0)); $this->_imgHelper = new App_View_Helper_Image(); $this->_imgHelper->setView($viewStub); } function testImageWithoutParams() { $this->assertEquals( '<img src="/layouts/default/images/myfile.png" alt="" />', $this->_imgHelper->image('myfile.png') ); } function testImageWithId() { $this->assertEquals( '<img src="/layouts/default/images/myfile.png" id="testId" alt="" />', $this->_imgHelper->image('myfile.png', array('id' => 'testId')) ); } function testImageWithIdAndAlt() { $this->assertEquals( '<img src="/layouts/default/images/myfile.png" alt="testAlt" id="testId" />', $this->_imgHelper->image('myfile.png', array('alt' => 'testAlt', 'id' => 'testId')) ); } function testImageWithCustomAttribute() { $this->assertEquals( '<img src="/layouts/default/images/myfile.png" myAtt="myTestAtt" alt="" />', $this->_imgHelper->image('myfile.png', array('myAtt' => 'myTestAtt')) ); } } |
Тут все просто, единственный ньанс Zend_View_Helper_Abstract, который мы будем наследовать определяет метод setView принимающий в качестве аргумента параметр Zend_View_Interface.
Для него создадим заглушку $viewStub, так как тестируем мы только поведение нашего отдельно взятого хелпера. Также будем добавлять обязательный по спецификации аттрибут alt, даже если он явно не передан в списке параметров.
Теперь приступим к реализации:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | <?php /** * Image view helper. Create <img /> tag with full path, * according to current layout * e.g. $this->image('myfile.png') creates * <img src="/layouts/default/images/myfile.png" alt="" /> * if current layout is "default" * */ class App_View_Helper_Image extends Zend_View_Helper_Abstract { public $view; protected static $_baseurl = null; /** * Constructor */ public function __construct() { if (null === self::$_baseurl) { $config = Zend_Registry::get('config'); $url = Zend_Controller_Front::getInstance()->getRequest()->getBaseUrl(); $root = '/' . trim($url, '/'); if ('/' == $root) { $root = ''; } self::$_baseurl = $root . '/layouts/' . $config['resources']['layout']['layout'] . '/images/'; } } /** * Output the <img /> tag * * @param string $path * @param array $params * @return string */ public function image($path, $params = array()) { $paramList = array(); $imagePath = self::$_baseurl . ltrim($path, '/'); if (!isset($params['alt'])) { $params['alt'] = ''; } foreach ($params as $param => $value) { $paramList[] = $param . '="' . $this->view->escape($value) . '"'; } $paramStr = ' ' . join(' ', $paramList); return '<img src="' . $imagePath . '"' . $paramStr . ' />'; } } |
В конструкторе определяем базовый путь, который используем затем в методе image (который должен совпадать с именем хелпера).
Последний шаг – надо подсказать нашему приложению где искать наши добавленные хелперы, для этого добавляем в Bootstrap.php:
protected function _initView() { $view = new Zend_View(); $view->addHelperPath(APPLICATION_PATH . '/library/App/View/Helper', 'App_View_Helper'); $view->setScriptPath(APPLICATION_PATH . '/views/scripts/' . $this->_options['resources']['layout']['layout']; $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper( 'ViewRenderer' ); $viewRenderer->setView($view); return $view; } |
Здесь добавляется путь к хелперам и вьюхам. Все. Теперь одной строчкой конфигурации мы можем координально сменить дизайн всего приложения.