Записки Вредного программиста

enjoy, motherfuckers ;)

Zend Framework: вставляем viewHelper куда душе угодно

Здравствуйте, уважаемые коллеги-разработчики, в сегодняшней заметке я поделюсь с вами своим костылем-решением. Пишу в свободное время свою модульную CMS (ведь каждый разработчик должен написать в своей жизни хотя бы одну) на базе Zend Framework’а и возникла необходимость вставлять в контент форму обратной связи и еще что-нибудь в произвольное место. Для создания стратичных страниц я использую свой модуль Static, который ничего не умеет, кроме создания стратичных страниц WYSIWYG’ом и прикрепления к уже имеющимся.

Первое, что пришло в голову это заменять какой-нибудь placeholder аля {placeholder_feedback_form(0)} на содержимое. Сказано-сделано, приведу кусок view Helper’а, который отображает нестандартную форму и валидирут посредстом отправления AJAX запросов на сервер.

View_Helper: на что будем менять

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
<?php

class Feedback_View_Helper_Form extends Zend_View_Helper_Abstract
{
    // form with ajax validation
    public function form($form = null)
    {
        $html = <<< karamba
        <form action="#" method="post">
                <div class="fancyform">
                        <label for="username"><span>Ваше имя</span></label>
                        <div class="it"><div><input type="text" name="username" id="username"></div></div>
                        <label for="email"><span>Ваш E-mail</span></label>
                        <div class="it"><div><input type="text" name="email" id="email"></div></div>
                        <label for="phone"><span>Ваш телефон</span></label>
                        <div class="it"><div><input type="text" name="phone" id="phone"></div></div>
                        <div class="ta"><div><textarea name="message"></textarea></div></div>
                        <div class="is"><div><input type="submit" name="submit" id="submit" value="Отправить"></div></div>
                        <p class="spasibo"><span></span></p>
                </div><!-- /fancyform -->
        </form>
karamba;
        $view = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer')->view;
        $view->headScript()->captureStart() ?>
            $().ready(function() {
                $('form').submit(function() {
                    $.get('/feedback', $(this).serialize(), function(response) {
                        if ('ok' == response.code) {
                            // transmission completed
                            $(':input', 'form')
                                .not(':button, :submit, :reset, :hidden')
                                .val('')
                            $('p.spasibo span').text('Спасибо! Обязательно отвечу!');
                        } else {
                            // print error message
                            $('p.spasibo span').text('Ошибка при заполнении');
                        }
                    }, 'json');
                    return false;
                });
            });
        <?php $view->headScript()->captureEnd();
        return $html;
    }

}

данный view Helper у меня располагается в папке application/modules/feedback/view/helpers/Form.php

Action_Helper: замена placeholder’ов

Более или менее универсальное решение по замене placeholder’ов вида {placeholder%moduleName%%viewHelper(%param%)} реализовал в виде Action Helper’а, вот его код

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
<?php

/**
 * content replacer
 *
 * replace {placeholder_moduleName_helperName(param)} with
 * Modulename_View_Helper_HelperName::helperName($param) return
 */
class Vredniy_Controller_Action_Helper_ContentReplacer extends Zend_Controller_Action_Helper_Abstract
{

    public function postDispatch()
    {
        //$this->getResponse()->setBody('replaced');
        // label {placeholder_image_gallery(param)}
        //call_user_func_array($function, $param_arrarray);
        // \{placeholder_(\w+)_(\w+)\((((\w+)?,?)*)\)\}
        if ('admin' === substr($this->getRequest()->getControllerName(), 0, 5))
            return;
        $regExp = '@\{placeholder_(\w+)_(\w+)\((\d+)\)\}@';
        if (preg_match_all($regExp, $this->getResponse()->getBody(), $matches)) {
            //var_dump($matches);
            $matchesFound = count($matches[0]);
            $allMatches = array();
            for($i = 0; $i < $matchesFound; $i++)
                $allMatches[] = array(
                    'module' => $matches[1][$i],
                    'helper' => $matches[2][$i],
                    'param' => $matches[3][$i],
                    'assembledString' => "{placeholder_{$matches[1][$i]}_{$matches[2][$i]}({$matches[3][$i]})}"
                );
            foreach($allMatches as $currentMatch) {
                $className = ucfirst($currentMatch['module']) . '_View_Helper_' . ucfirst($currentMatch['helper']);

                if (class_exists($className)) {
                    $viewHelper = new $className;
                    if (method_exists($viewHelper, ucfirst($currentMatch['helper']))) {
                        $this->getResponse()->setBody(
                                str_replace(
                                        $currentMatch['assembledString'], // assembled regexp
                                        call_user_func(array($viewHelper, ucfirst($currentMatch['helper'])), $currentMatch['param']), // call it
                                        $this->getResponse()->getBody() // old body
                                )
                        );
                    }
                }
            }
        }
    }

}

Регистрируем наш ActionHelper

Осталось только подключить наш Action Helper, я делаю это в основном application/Bootstrap.php

1
2
3
4
protected function _initActionHelpers()
{
   Zend_Controller_Action_HelperBroker::addHelper(new Vredniy_Controller_Action_Helper_ContentReplacer());
}

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

Комментарии