Создаем Zend_View_Helper для отображения картинок

Задача – создать хелпер для отображения картинок во вьюхах, не заботясь каждый раз о путях.
Наше приложение поддерживает различные скины (используются стандартные зендовские 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;
    }

Здесь добавляется путь к хелперам и вьюхам. Все. Теперь одной строчкой конфигурации мы можем координально сменить дизайн всего приложения.

Leave a Reply