zf – Блог Stafox'a https://stafox.cc О программировании и веб-разработке Tue, 29 Dec 2015 06:58:07 +0000 en-US hourly 1 https://wordpress.org/?v=5.8.2 Ошибка ‘Cannot redeclare class’ при запуске теста PHPUnit https://stafox.cc/cannot-redeclare-class-error-in-phpunit-test/ https://stafox.cc/cannot-redeclare-class-error-in-phpunit-test/#respond Mon, 03 Aug 2015 20:24:51 +0000 http://stafox.ru/?p=2560 Как избавиться от ошибки ‘Cannot redeclare class’ при выполнение теста PHPUnit? Разберем причины и способы устранения. Ошибка подобного рода может возникать когда при выполнении набора тестов один из классов определяется более 1 раза. Такое может возникнуть при выполнении интеграционных тестов. Рассмотрим пример простого интеграционного теста на Zend Framework: public function testValidateUserSuccess() { $this->getRequest() ->setMethod('POST') ->setPost(array('username' =>

Сообщение Ошибка ‘Cannot redeclare class’ при запуске теста PHPUnit появились сначала на Блог Stafox'a.

]]>
Как избавиться от ошибки ‘Cannot redeclare class’ при выполнение теста PHPUnit? Разберем причины и способы устранения.

Ошибка подобного рода может возникать когда при выполнении набора тестов один из классов определяется более 1 раза. Такое может возникнуть при выполнении интеграционных тестов.

Рассмотрим пример простого интеграционного теста на Zend Framework:


public function testValidateUserSuccess()
{
    $this->getRequest()
        ->setMethod('POST')
        ->setPost(array('username' => 'test', 'msisdn' => '375291234567'));

    $this->dispatch('/api/user/validate');
    $this->assertResponseCode(200);
}

public function testValidateUserFailure()
{
    $this->getRequest()
        ->setMethod('POST')
        ->setPost(array('username' => 'test', 'msisdn' => 'abc'));

    $this->dispatch('/api/user/validate');
    $this->assertResponseCode(400);
}

При выполнении данного набора тестов приложение будет запущено дважды, а значит дважды ининицализируются все методы Bootstrap‘а и Autoloader.
Один из вариантов решения – это запуск теста в отдельном процессе. Для этого необходимо добавить перед тестом @runInSeparateProcess.


/**
 * @runInSeparateProcess
 */
public function testValidateUserSuccess()
{
    ...
}

/**
 * @runInSeparateProcess
 */
public function testValidateUserFailure()
{
    ...
}

Можно запустить каждый тест в отдельном процессе, указав перед классом теста @runTestsInSeparateProcesses


/**
 * @runTestsInSeparateProcesses
 **/
class UserTest extends PHPUnit_Framework_TestCase
{
    public function testValidateUserSuccess()
    {
        ...
    }

    public function testValidateUserFailure()
    {
        ...
    }
}

Подводные камни

Во время запуска тестов я периодически ловил ошибку


RuntimeException: PHP Fatal error:  Uncaught exception 'Exception' with message 'Serialization of 'Closure' is not allowed' in -:36

Полный текст ошибки


PHPUnit 3.6.10 by Sebastian Bergmann.

Configuration read from /path/to/project/tests/phpunit.xml

E

Time: 0 seconds, Memory: 4.50Mb

There was 1 error:

1) UserTest::testValidateUserSuccess
RuntimeException: PHP Fatal error:  Uncaught exception 'Exception' with message 'Serialization of 'Closure' is not allowed' in -:36
Stack trace:
#0 -(36): serialize(Array)
#1 -(135): __phpunit_run_isolated_test()
#2 {main}
  thrown in - on line 36

Гуглил, нашел пару предположений:

  • PHPUnit пытается все сложить в переменную $GLOBALS и ошибка возникает когда в тесте есть замыкания. Фикс: не использовать замыкания. Не мой вариант – у меня замыканий не было.
  • Причина @runInSeparateProcess. Фикс: не используйте @runInSeparateProcess. Однозначно тоже не мой вариант.

Не сумев найти решения на просторах интернета, я решил обновить PHPUnit с 3.6.10 => 4.7.7 – помогло 🙂
P.S. совместимость Zend Framework 1.12.13 с PHPUnit 4.7 нормальная (несмотря на заявленную поддержку 3.7).

Сообщение Ошибка ‘Cannot redeclare class’ при запуске теста PHPUnit появились сначала на Блог Stafox'a.

]]>
https://stafox.cc/cannot-redeclare-class-error-in-phpunit-test/feed/ 0
Zend Framework: Как получить число Twitter-фоловеров через OAuth? https://stafox.cc/zend-framework-get-twitter-followers-via-oauth/ https://stafox.cc/zend-framework-get-twitter-followers-via-oauth/#comments Wed, 07 Jan 2015 16:19:48 +0000 http://stafox.ru/?p=2209 Zend Framework очень мощный инструмент, который содержит в себе множество готовых к использованию компонентов. Вот пример, того как получить количество фоловеров для twitter аккаунта через OAuth: [php] $accessToken = new Zend_Oauth_Token_Access(); $accessToken->setToken(‘00000001-mw1bgYIskElAH5s34kV2H4Al3PENrzmWGYwgv8N6q’); $accessToken->setTokenSecret(‘quTiCujgzNGeHaCfdR7KrBFX5EhGenv3alrXZA9QMNhxWw’); $twitter = new Zend_Service_Twitter(array( ‘username’ => ‘Stafox’, ‘accessToken’ => $accessToken, ‘oauthOptions’ => array( ‘consumerKey’ => ‘qS2mwYhiFzbhoSiRY4VJD’, ‘consumerSecret’ => ‘yP3aE1Yp7Njk7NdGeUWcZ1m5yqmKsjahWAVEBNqYmU’ ) )); $result

Сообщение Zend Framework: Как получить число Twitter-фоловеров через OAuth? появились сначала на Блог Stafox'a.

]]>
Zend Framework очень мощный инструмент, который содержит в себе множество готовых к использованию компонентов. Вот пример, того как получить количество фоловеров для twitter аккаунта через OAuth:

[php] $accessToken = new Zend_Oauth_Token_Access();
$accessToken->setToken(‘00000001-mw1bgYIskElAH5s34kV2H4Al3PENrzmWGYwgv8N6q’);
$accessToken->setTokenSecret(‘quTiCujgzNGeHaCfdR7KrBFX5EhGenv3alrXZA9QMNhxWw’);

$twitter = new Zend_Service_Twitter(array(
‘username’ => ‘Stafox’,
‘accessToken’ => $accessToken,
‘oauthOptions’ => array(
‘consumerKey’ => ‘qS2mwYhiFzbhoSiRY4VJD’,
‘consumerSecret’ => ‘yP3aE1Yp7Njk7NdGeUWcZ1m5yqmKsjahWAVEBNqYmU’
)
));

$result = $twitter->account->verifyCredentials();
$followersCount = $result->followers_count;
[/php]

How to get twitter followers using OAuth in Zend Framework 1.x

Сообщение Zend Framework: Как получить число Twitter-фоловеров через OAuth? появились сначала на Блог Stafox'a.

]]>
https://stafox.cc/zend-framework-get-twitter-followers-via-oauth/feed/ 2
Zend Framework: Реализация REST API https://stafox.cc/rest-api-using-zend-framework/ https://stafox.cc/rest-api-using-zend-framework/#respond Sun, 04 Jan 2015 20:26:12 +0000 http://stafox.ru/?p=2322 Небольшой HowTo о том, как реализовать REST API с использованием Zend Framework 1. Создадим новый модуль api (предполагается, что Ваш проект имеет модульную структуру). Создадим контроллер User и унаследуем его от Zend_Rest_Controller. [php] class Api_UserController extends Zend_Rest_Controller { public function init() { $this->getHelper(‘layout’)->disableLayout(); $this->getHelper(‘viewRenderer’)->setNoRender(); } public function indexAction() {} public function headAction() {} public function

Сообщение Zend Framework: Реализация REST API появились сначала на Блог Stafox'a.

]]>
Реализация REST API
Небольшой HowTo о том, как реализовать REST API с использованием Zend Framework 1.

Создадим новый модуль api (предполагается, что Ваш проект имеет модульную структуру).

Создадим контроллер User и унаследуем его от Zend_Rest_Controller.
[php] class Api_UserController extends Zend_Rest_Controller
{

public function init()
{
$this->getHelper(‘layout’)->disableLayout();
$this->getHelper(‘viewRenderer’)->setNoRender();
}

public function indexAction() {}

public function headAction() {}

public function getAction() {}

public function putAction() {}

public function postAction() {}

public function deleteAction() {}

}
[/php]

Для инициализации REST роутов воспользуемся классом [php]Zend_Rest_Route[/php]. Для этого в Bootstrap.php добавим следующий метод:

[php] protected function _initRoutes()
{
$front = Zend_Controller_Front::getInstance();
$restRoute = new Zend_Rest_Route($front, array(), array(‘api’));
$front->getRouter()->addRoute(‘rest’, $restRoute);
}
[/php]

Можно инициализировать REST роут только для User контроллера:

[php] $restRoute = new Zend_Rest_Route($front, array(), array(‘api’ => ‘user’));
[/php]

Есть еще одна проблема – это возможность вытянуть параметры из PUT запроса следующим образом:

[php] $userId = $request->getParam(‘id’);
[/php]

Для PUT запроса этот метод вернет [php]null[/php].

Исправить это можно при помощи плагина [php]Zend_Controller_Plugin_PutHandler[/php]. Просто добавьте следующий метод в Bootstrap.php:
[php] protected function _initPlugins()
{
$front = Zend_Controller_Front::getInstance();
$front->registerPlugin(new Zend_Controller_Plugin_PutHandler());
}
[/php]

Enjoy! 🙂

Сообщение Zend Framework: Реализация REST API появились сначала на Блог Stafox'a.

]]>
https://stafox.cc/rest-api-using-zend-framework/feed/ 0
Zend Framework форма с использованием Bootstrap https://stafox.cc/zend-framework-form-using-bootstrap/ https://stafox.cc/zend-framework-form-using-bootstrap/#respond Wed, 26 Feb 2014 20:01:20 +0000 http://stafox.ru/?p=2226 Для того, чтобы показать как работают стандартные декораторы формы на примере, я решил реализовать вполне реальную задачу: стилизировать форму используя Bootstrap. Что такое Bootstrap? Если Вы еще не знаете, что такое Bootstrap, попробую объяснить в двух словах. Bootstrap – это простой и легко настраиваемый HTML, CSS и Javascript фреймворк для более быстрой и удобной Web-разработки.

Сообщение Zend Framework форма с использованием Bootstrap появились сначала на Блог Stafox'a.

]]>
Zend Framework форма с использованием Bootstrap
Для того, чтобы показать как работают стандартные декораторы формы на примере, я решил реализовать вполне реальную задачу: стилизировать форму используя Bootstrap.

Что такое Bootstrap?

Если Вы еще не знаете, что такое Bootstrap, попробую объяснить в двух словах. Bootstrap – это простой и легко настраиваемый HTML, CSS и Javascript фреймворк для более быстрой и удобной Web-разработки. Он содержит большое число компонентов, которые могут быть быть использованы почти в любом проекте. Bootstrap можно использовать как каркас для разработки фронтэнд части приложения. Подробнее читайте на официальном сайте Bootstrap.

Для начала создадим класс формы, в котором опишем основные элементы горизонтальной формы: поле ввода логина (email), поле ввода пароля, чекбокс Remember me и submit-кнопка.

[codegroup] [php tab=”Класс формы”] class Default_Form_Bootstrap extends Zend_Form
{

public function init()
{

$login = new Zend_Form_Element_Text(‘login’);
$login->setRequired(‘true’)
->setLabel(‘Email:’);

$password = new Zend_Form_Element_Password(‘password’);
$password->setRequired(‘true’)
->setLabel(‘Password:’);

$rememberMe = new Zend_Form_Element_Checkbox(‘remember_me’);
$rememberMe->setLabel(‘Remember me’);

$submit = new Zend_Form_Element_Submit(‘sign_in’);
$submit->setLabel(‘Sign In’);

$this->addElements(array($login, $password, $rememberMe, $submit));
}

}
[/php] [html tab=”Генерируемый контент”]

 
[/html] [/codegroup]

Теперь разберемся с формой. Избавимся от оборачивания содержимого формы в тег dl. Т.к. за это отвечает декоратор HtmlTag, необходимо отказаться от его использования. Поэтому зададим форме два декоратора FormElements и Form. А еще необходимо задать класс .form-horizontal форме и установить атрибут

role="form"

.

[codegroup] [php tab=”Класс формы”] class Default_Form_Bootstrap extends Zend_Form
{

public function init()
{
$this->setAttribs(array(‘class’ => ‘form-horizontal’, ‘role’ => ‘form’))
->setDecorators(array(‘FormElements’, ‘Form’));

$login = new Zend_Form_Element_Text(‘login’);
$login->setRequired(‘true’)
->setLabel(‘Email:’);

$password = new Zend_Form_Element_Password(‘password’);
$password->setRequired(‘true’)
->setLabel(‘Password:’);

$rememberMe = new Zend_Form_Element_Checkbox(‘remember_me’);
$rememberMe->setLabel(‘Remember me’);

$submit = new Zend_Form_Element_Submit(‘sign_in’);
$submit->setLabel(‘Sign In’);

$this->addElements(array($login, $password, $rememberMe, $submit));
}

}
[/php] [html tab=”Генерируемый контент”]


 
[/html] [/codegroup]

Зададим базовые декораторы, которые необходимы для всех элементов формы: ViewHelper и HtmlTag, причем как видно в примере, HtmlTag должен оборачивать контент в тег div с классом .form-group. Также, присвоим класс .form-control полям ввода.

[codegroup] [php tab=”Класс формы”] ‘div’, ‘class’ => ‘form-group’))
);

public function init()
{
$this->setAttribs(array(‘class’ => ‘form-horizontal’, ‘role’ => ‘form’))
->setDecorators(array(‘FormElements’, ‘Form’));

$login = new Zend_Form_Element_Text(‘login’);
$login->setRequired(‘true’)
->setAttrib(‘class’, ‘form-control’)
->setLabel(‘Email:’)
->setDecorators($this->baseElementDecorators);

$password = new Zend_Form_Element_Password(‘password’);
$password->setRequired(‘true’)
->setAttrib(‘class’, ‘form-control’)
->setLabel(‘Password:’)
->setDecorators($this->baseElementDecorators);

$rememberMe = new Zend_Form_Element_Checkbox(‘remember_me’);
$rememberMe->setLabel(‘Remember me’)
->setDecorators($this->baseElementDecorators);

$submit = new Zend_Form_Element_Submit(‘sign_in’);
$submit->setLabel(‘Sign In’)
->setDecorators($this->baseElementDecorators);

$this->addElements(array($login, $password, $rememberMe, $submit));
}

}
[/php] [html tab=”Генерируемый контент”]

[/html] [/codegroup]

Теперь оотбразим лэйблы для полей ввода. Для этого воспользуемся декоратором Label. Также сразу определим необходимые классы для него. Обратите внимание на теги, которые оборачивают поля ввода. Для того, чтобы добиться такого порядка вложенности тегов, необходимо последовательно применить декораторы: ViewHelper, Label, HtmlTag.

[codegroup] [php tab=”Класс формы”] ‘div’, ‘class’ => ‘form-group’)));
private $inputDecorators = array(
array(
‘Label’,
array(‘class’ => ‘col-sm-2 control-label’)
)
);

public function init()
{
$this->setAttribs(array(‘class’ => ‘form-horizontal’, ‘role’ => ‘form’))
->setDecorators(array(‘FormElements’, ‘Form’));

$login = new Zend_Form_Element_Text(‘login’);
$login->setRequired(‘true’)
->setAttrib(‘class’, ‘form-control’)
->setLabel(‘Email:’)
->setDecorators($this->baseElementDecorators)
->addDecorators($this->inputDecorators)
->addDecorators($this->htmlTagBaseDecorator);

$password = new Zend_Form_Element_Password(‘password’);
$password->setRequired(‘true’)
->setAttrib(‘class’, ‘form-control’)
->setLabel(‘Password:’)
->setDecorators($this->baseElementDecorators)
->addDecorators($this->inputDecorators)
->addDecorators($this->htmlTagBaseDecorator);

$rememberMe = new Zend_Form_Element_Checkbox(‘remember_me’);
$rememberMe->setLabel(‘Remember me’)
->setDecorators($this->baseElementDecorators)
->addDecorators($this->htmlTagBaseDecorator);

$submit = new Zend_Form_Element_Submit(‘sign_in’);
$submit->setLabel(‘Sign In’)
->setDecorators($this->baseElementDecorators)
->addDecorators($this->htmlTagBaseDecorator);

$this->addElements(array($login, $password, $rememberMe, $submit));
}

}
[/php] [html tab=”Генерируемый контент”]



[/html] [/codegroup]

Поля ввода необходимо отдельно обернуть в div c классом col-sm-10. Для этого необходимо применить декоратор HtmlTag. Т.к. HtmlTag оборачивает весь контент элемента, применим декоратор в тот момент, когда сгенерируется только контент
[html] [/html] т.е. после декоратора ViewHelper.

[codegroup] [php tab=”Класс формы”] class Default_Form_Bootstrap extends Zend_Form
{

private $baseElementDecorators = array(
‘ViewHelper’
);
private $htmlTagBaseDecorator = array(array(‘HtmlTag’, array(‘tag’ => ‘div’, ‘class’ => ‘form-group’)));
private $inputDecorators = array(
array(
array(‘data’ => ‘HtmlTag’), array(‘tag’ => ‘div’, ‘class’ => ‘col-sm-10’)
),
array(
‘Label’,
array(‘class’ => ‘col-sm-2 control-label’)
)
);

public function init()
{
$this->setAttribs(array(‘class’ => ‘form-horizontal’, ‘role’ => ‘form’))
->setDecorators(array(‘FormElements’, ‘Form’));

$login = new Zend_Form_Element_Text(‘login’);
$login->setRequired(‘true’)
->setAttrib(‘class’, ‘form-control’)
->setLabel(‘Email:’)
->setDecorators($this->baseElementDecorators)
->addDecorators($this->inputDecorators)
->addDecorators($this->htmlTagBaseDecorator);

$password = new Zend_Form_Element_Password(‘password’);
$password->setRequired(‘true’)
->setAttrib(‘class’, ‘form-control’)
->setLabel(‘Password:’)
->setDecorators($this->baseElementDecorators)
->addDecorators($this->inputDecorators)
->addDecorators($this->htmlTagBaseDecorator);

$rememberMe = new Zend_Form_Element_Checkbox(‘remember_me’);
$rememberMe->setLabel(‘Remember me’)
->setDecorators($this->baseElementDecorators)
->addDecorators($this->htmlTagBaseDecorator);

$submit = new Zend_Form_Element_Submit(‘sign_in’);
$submit->setLabel(‘Sign In’)
->setDecorators($this->baseElementDecorators)
->addDecorators($this->htmlTagBaseDecorator);

$this->addElements(array($login, $password, $rememberMe, $submit));
}

}
[/php] [html tab=”Генерируемый контент”]

[/html] [/codegroup]

Теперь займемся декорированием чекбокса. Т.к. поместить input внутри label не выйдет, придется заменить метод setLabel на setDescription и убрать оборачивание в тег описания, задав опцию tag=false. Оборачивания чекбокса добиваемся при помощи декоратора HtmlTag, у которого опция

tag="label"

. По аналогии с полями ввода, применяем еще два декоратора типа HtmlTag.

[codegroup] [php tab=”Класс формы”] class Default_Form_Bootstrap extends Zend_Form
{

private $baseElementDecorators = array(
‘ViewHelper’
);
private $htmlTagBaseDecorator = array(array(‘HtmlTag’, array(‘tag’ => ‘div’, ‘class’ => ‘form-group’)));
private $inputDecorators = array(
array(
array(‘data’ => ‘HtmlTag’), array(‘tag’ => ‘div’, ‘class’ => ‘col-sm-10’)
),
array(
‘Label’,
array(‘class’ => ‘col-sm-2 control-label’)
)
);

public function init()
{
$this->setAttribs(array(‘class’ => ‘form-horizontal’, ‘role’ => ‘form’))
->setDecorators(array(‘FormElements’, ‘Form’));

$login = new Zend_Form_Element_Text(‘login’);
$login->setRequired(‘true’)
->setAttrib(‘class’, ‘form-control’)
->setLabel(‘Email:’)
->setDecorators($this->baseElementDecorators)
->addDecorators($this->inputDecorators)
->addDecorators($this->htmlTagBaseDecorator);

$password = new Zend_Form_Element_Password(‘password’);
$password->setRequired(‘true’)
->setAttrib(‘class’, ‘form-control’)
->setLabel(‘Password:’)
->setDecorators($this->baseElementDecorators)
->addDecorators($this->inputDecorators)
->addDecorators($this->htmlTagBaseDecorator);

$rememberMe = new Zend_Form_Element_Checkbox(‘remember_me’);
$rememberMe->setDescription(‘Remember me’)
->setDecorators($this->baseElementDecorators)
->addDecorators(array(
array(‘Description’, array(‘tag’ => false)),
array(array(‘Input’ => ‘HtmlTag’), array(‘tag’ => ‘label’)),
array(array(‘Checkbox’ => ‘HtmlTag’), array(‘tag’ => ‘div’, ‘class’ => ‘checkbox’)),
array(array(‘Data’ => ‘HtmlTag’), array(‘tag’ => ‘div’, ‘class’ => ‘col-sm-offset-2 col-sm-10’))
))
->addDecorators($this->htmlTagBaseDecorator);

$submit = new Zend_Form_Element_Submit(‘sign_in’);
$submit->setLabel(‘Sign In’)
->setDecorators($this->baseElementDecorators)
->addDecorators($this->htmlTagBaseDecorator);

$this->addElements(array($login, $password, $rememberMe, $submit));
}

}
[/php] [html tab=”Генерируемый контент”]

[/html] [/codegroup]

Ну, и остается последний штрих – кнопка. Добавляем ей класс, а также применяем два декоратора HtmlTag, чтобы обернуть кнопку в div‘ы.

[codegroup] [php tab=”Класс формы”] class Default_Form_Bootstrap extends Zend_Form
{

private $baseElementDecorators = array(
‘ViewHelper’
);
private $htmlTagBaseDecorator = array(array(‘HtmlTag’, array(‘tag’ => ‘div’, ‘class’ => ‘form-group’)));
private $inputDecorators = array(
array(
array(‘data’ => ‘HtmlTag’), array(‘tag’ => ‘div’, ‘class’ => ‘col-sm-10’)
),
array(
‘Label’,
array(‘class’ => ‘col-sm-2 control-label’)
)
);

public function init()
{
$this->setAttribs(array(‘class’ => ‘form-horizontal’, ‘role’ => ‘form’))
->setDecorators(array(‘FormElements’, ‘Form’));

$login = new Zend_Form_Element_Text(‘login’);
$login->setRequired(‘true’)
->setAttrib(‘class’, ‘form-control’)
->setLabel(‘Email:’)
->setDecorators($this->baseElementDecorators)
->addDecorators($this->inputDecorators)
->addDecorators($this->htmlTagBaseDecorator);

$password = new Zend_Form_Element_Password(‘password’);
$password->setRequired(‘true’)
->setAttrib(‘class’, ‘form-control’)
->setLabel(‘Password:’)
->setDecorators($this->baseElementDecorators)
->addDecorators($this->inputDecorators)
->addDecorators($this->htmlTagBaseDecorator);

$rememberMe = new Zend_Form_Element_Checkbox(‘remember_me’);
$rememberMe->setDescription(‘Remember me’)
->setDecorators($this->baseElementDecorators)
->addDecorators(array(
array(‘Description’, array(‘tag’ => false)),
array(array(‘Input’ => ‘HtmlTag’), array(‘tag’ => ‘label’)),
array(array(‘Checkbox’ => ‘HtmlTag’), array(‘tag’ => ‘div’, ‘class’ => ‘checkbox’)),
array(array(‘Data’ => ‘HtmlTag’), array(‘tag’ => ‘div’, ‘class’ => ‘col-sm-offset-2 col-sm-10’))
))
->addDecorators($this->htmlTagBaseDecorator);

$submit = new Zend_Form_Element_Submit(‘sign_in’);
$submit->setLabel(‘Sign In’)
->setAttrib(‘class’, ‘btn btn-default’)
->setDecorators($this->baseElementDecorators)
->addDecorator(array(‘Button’ => ‘HtmlTag’), array(‘tag’ => ‘div’, ‘class’ => ‘col-sm-offset-2 col-sm-10’))
->addDecorators($this->htmlTagBaseDecorator);

$this->addElements(array($login, $password, $rememberMe, $submit));
}

}
[/php] [html tab=”Генерируемый контент”]

[/html] [/codegroup]

А вот и результат.
bootstrap-zend-form
По желанию добавляем недостающие атрибуты (id, placeholder и прочие параметры) и на этом все.

Сообщение Zend Framework форма с использованием Bootstrap появились сначала на Блог Stafox'a.

]]>
https://stafox.cc/zend-framework-form-using-bootstrap/feed/ 0
Zend Framework: стандартные декораторы формы https://stafox.cc/zend-framework-form-decorators/ https://stafox.cc/zend-framework-form-decorators/#comments Sat, 22 Feb 2014 19:43:25 +0000 http://stafox.ru/?p=2185 Я не раз замечал, как декораторы форм вызывают трудности у начинающих разработчиков. И дело не столько в их сложности, сколько в отсутствии качественной документации к ним. Да, даже в официальной документации к Zend Framework написано не густо. И так, в этой статье речь пойдет о стандартных декораторах формы. Для чего нужны декораторы? Декораторы используются для

Сообщение Zend Framework: стандартные декораторы формы появились сначала на Блог Stafox'a.

]]>
Zend Framework: стандартные декораторы формы
Я не раз замечал, как декораторы форм вызывают трудности у начинающих разработчиков. И дело не столько в их сложности, сколько в отсутствии качественной документации к ним. Да, даже в официальной документации к Zend Framework написано не густо. И так, в этой статье речь пойдет о стандартных декораторах формы.

Для чего нужны декораторы?

Декораторы используются для визуализации и кастомизации форм, а также их элементов. Декораторы позволяют задавать вид выводимого контента для элемента или формы. В данном случае следует помнить, что в понятие “элемент формы” в Zend Framework входит сразу несколько составляющих. Рассмотрим на примере Zend_Form_Element_Text. объект этого класса позволяет сгенерировать следующий контент:

  • Тег input, являющийся элементом ввода
  • Тег label, который выступает в роли заголовка
  • Блок описания, в котором можно вывести подсказку к полю либо образец заполнения
  • Блок ошибок, который используется для вывода ошибок валидатора формы

Стиль каждого из этих объектов можно изменить при помощи декоратора.

Стандартные декораторы

Давайте посмотрим как работают декораторы на примере. Создадим простую форму и посмотрим какой контент она генерирует.
[codegroup] [php tab=”Класс формы”] class Default_Form_TestForm extends Zend_Form
{

public function init()
{
$text = new Zend_Form_Element_Text(‘text_element’);
$text->setRequired(‘true’)
->setLabel(‘Text’);

$textarea = new Zend_Form_Element_Textarea(‘textarea_element’);
$textarea->setOptions(array(
‘class’ => ‘form-textarea’,
‘rows’ => 7
));

$submit = new Zend_Form_Element_Submit(‘submit_element’);
$submit->setLabel(‘Do it!’)
->setOptions(array(‘class’ => ‘btn btn-default’));

$this->addElements(array($text, $textarea, $submit));
}

}
[/php] [html tab=”Генерируемый контент”]

 
 
[/html] [/codegroup]

Как мы видим, контент формы оборачивается в тег dl, а каждый ее элемент в dd, метка же (label) заключается в тег dt. Обратите внимание, что метка оборачивается в тег независимо от того была она задана, или нет. Все этого достигается благодаря стандартным декораторам, которые применяются к элементам в процессе создания объекта. Ниже я приведу список стандартных декораторов элементов формы:

  • ViewHelper – декоратор, отвечающий за отображение контента элемента.
  • Errors – декоратор, отвечающий за отображение ошибок валидации формы.
  • Description – декоратор, позволяющий задать вид описания элемента.
  • HtmlTag – декоратор, отвечающий за оборачивание контента элемента.
  • Label – декоратор, позволяющий настроить отображение метки элемента.

Благодаря этой пятерке, Вы можете кардинально изменить внешний вид ваших элементов форм.

У формы также есть стандартные декораторы:

  • FormElements – декоратор, отвечающий за отображение элементов формы.
  • HtmlTag – декоратор, который отвечает за обертку.
  • Form – декоратор, влияющий на отображение тега формы.

Манипуляции с декораторами

Для манипуляции с декораторами у каждого элемента, унаследовавшего класс Zend_Form_Element (или Zend_Form), имеются методы:

  • addDecorator($decorator) ( addDecorators(array $decorators) ) – добавляет декоратор объекту, в качестве аргумента принимает строку (массив) – имя (имена) декоратора (-ов).
  • removeDecorator($decorator) – удаляет декоратор. Аргументом выступает строка – имя декоратора.
  • clearDecorators() – очищает список декораторов.
  • setDecorators(array $decorators) – принимает в качестве аргумента массив с декораторами. Последовательно вызывает метод clearDecorators(), затем addDecorators(array $decorators).
  • setDisableLoadDefaultDecorators($flag) – отключить загрузку стандартных декораторов.

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

[php] $this->setDecorators(array(
‘FormElements’,
array(‘HtmlTag’, array(‘tag’ => ‘div’, ‘class’ => ‘form-inline’, ‘id’ => ‘test_form’)),
‘Form’
));
[/php]

Элемент массива декораторов, может быть как строкой (пример выше декораторы FormElements и Form), так и массивом (пример – HtmlTag). В первом случае задается использование декоратора со стандартными опциями. Во втором – опции задаются в массиве.
В нашем случае мы указали следующие опции: tag – задает тег, который будет использовать декоратор, class – добавляет атрибут class к тегу декоратора, id – задает атрибут id для тега декоратора.

В результате контент формы будет обернут в тег
[html]

[/html]

А теперь приступим к декорированию элементов формы. Первое, что Вы наверняка захотите сделать – это заменить теги dd, dt на div‘ы. Для этого необходимо воспользоваться декоратором HtmlTag.

[codegroup] [php tab=”Класс формы”] class Default_Form_TestForm extends Zend_Form
{

public function init()
{
$this->setDecorators(array(
‘FormElements’,
array(‘HtmlTag’, array(‘tag’ => ‘div’, ‘class’ => ‘form-inline’, ‘id’ => ‘test_form’)),
‘Form’
));

$text = new Zend_Form_Element_Text(‘text_element’);
$text->setRequired(‘true’)
->setLabel(‘Text’)
->setDecorators(array(
‘ViewHelper’,
‘Label’,
array(‘HtmlTag’, array(‘tag’ => ‘div’, ‘class’ => ‘form-element’)),
));

$textarea = new Zend_Form_Element_Textarea(‘textarea_element’);
$textarea->setOptions(array(
‘class’ => ‘form-textarea’,
‘rows’ => 7
))->setDecorators(array(
‘ViewHelper’,
‘Label’,
array(‘HtmlTag’, array(‘tag’ => ‘div’, ‘class’ => ‘form-element’)),
));

$submit = new Zend_Form_Element_Submit(‘submit_element’);
$submit->setLabel(‘Do it!’)
->setOptions(array(‘class’ => ‘btn btn-default’))
->setDecorators(array(
‘ViewHelper’,
array(‘HtmlTag’, array(‘tag’ => ‘div’, ‘class’ => ‘form-element’)),
));

$this->addElements(array($text, $textarea, $submit));
}

}
[/php] [html tab=”Генерируемый контент”]


[/html] [/codegroup]

Я также добавил декоратор Label для отображения тега заголовка элемента, если он был задан. У него, кстати, есть свои особенности. Можно задавать его местоположение, при помощи опции placement у которой может быть два значения: prepend и append. Хочу отметить, что по умолчанию placement = prepend. Т.е. label будет находиться перед элементом. Попробуем установить его за ним.
[codegroup] [php tab=”Код элемента формы”] $text = new Zend_Form_Element_Text(‘text_element’);
$text->setRequired(‘true’)
->setLabel(‘Text’)
->setDecorators(array(
‘ViewHelper’,
array(‘Label’, array(‘placement’ => ‘append’)),
array(‘HtmlTag’, array(‘tag’ => ‘div’, ‘class’ => ‘form-element’)),
));
[/php] [html tab=”Генерируемый контент”]


[/html] [/codegroup]

Также, декоратор Label имеет опцию tag, но работает она не так, как в декораторе HtmlTag. Он не заменяет тег label на указанный, а лишь оборачивает его в этот тег. Зато опции class и id работают также.

Вы можете применить несколько декораторов типа HtmlTag, которые как и HtmlTag обернут Ваш контент в еще один элемент. Вы также можете указать ключ (например, row), чтобы знать для чего он был применен.
[php] array(array(‘row’ => ‘HtmlTag’), array(‘tag’ => ‘div’, ‘id’ => ‘drag_drop_area’, ‘class’ => ‘drag’))
[/php]

К элементам формы можно задавать описание. Делается это при помощи метода setDescription(). С использовании декоратора Description выглядит это так.

[codegroup] [php tab=”Код элемента формы”] $textarea = new Zend_Form_Element_Textarea(‘textarea_element’);
$textarea->setOptions(array(
‘class’ => ‘form-textarea’,
‘rows’ => 7
))->setDescription(‘Введите текст сообщения’)
->setDecorators(array(
‘ViewHelper’,
‘Description’,
array(‘HtmlTag’, array(‘tag’ => ‘div’, ‘class’ => ‘form-element’)),
));
[/php] [html tab=”Генерируемый контент”]

Введите текст сообщения

[/html] [/codegroup]

Как видите, по умолчанию описание заключается в тег p с классом hint. Давайте поместим описание в тег span, причем в описании будут присутствовать html теги.

[codegroup] [php tab=”Код элемента формы”] $textarea = new Zend_Form_Element_Textarea(‘textarea_element’);
$textarea->setOptions(array(
‘class’ => ‘form-textarea’,
‘rows’ => 7
))->setDescription(‘Введите текст сообщения (не более 2000 символов)’)
->setDecorators(array(
‘ViewHelper’,
array(‘Description’, array(‘tag’ => ‘span’, ‘escape’ => false)),
array(‘HtmlTag’, array(‘tag’ => ‘div’, ‘class’ => ‘form-element’)),
));
[/php] [html tab=”Генерируемый контент”]

Введите текст сообщения (не более 2000 символов)
[/html] [/codegroup]

Для того, чтобы изменить тег в котором находится текст описания, мы воспользуемся опцией tag, а вот для того, чтобы отобразить html теги в описании, необходимо задать опции escape значение false. Опция escape отвечает за то, будет ли текст описания обработан функцией htmlentities, которая преобразует все возможные символы в соответствующие HTML-сущности.

За отображение ошибок, возникающих при валидации формы отвечает декоратор Errors. О нем мы поговорим в другой раз, когда будем разбирать работу валидаторов формы.

Сообщение Zend Framework: стандартные декораторы формы появились сначала на Блог Stafox'a.

]]>
https://stafox.cc/zend-framework-form-decorators/feed/ 3
Zend Framework: реализация хранения сессий в базе данных https://stafox.cc/zend-framework-store-sessions-in-database/ https://stafox.cc/zend-framework-store-sessions-in-database/#respond Sun, 19 Jan 2014 17:29:10 +0000 http://stafox.ru/?p=2115 Хранение сессий в файловой системе может стать серьезной проблемой, когда число пользователей проекта переваливает за несколько сотен тысяч. Стоит подумать об альтернативных способах хранения сессий. Одним из таковых является хранение сессий в БД. И я хотел бы рассказать о том, как реализовать хранение сессий в БД с использованием Zend Framework. Для начала нам понадобится создать

Сообщение Zend Framework: реализация хранения сессий в базе данных появились сначала на Блог Stafox'a.

]]>
Zend Framework: реализация хранения сессий в базе данных
Хранение сессий в файловой системе может стать серьезной проблемой, когда число пользователей проекта переваливает за несколько сотен тысяч. Стоит подумать об альтернативных способах хранения сессий. Одним из таковых является хранение сессий в БД. И я хотел бы рассказать о том, как реализовать хранение сессий в БД с использованием Zend Framework.

Для начала нам понадобится создать таблицу sessions для хранения сессий:
[sql] CREATE TABLE IF NOT EXISTS `sessions` (
`id` char(32) NOT NULL DEFAULT ”,
`modified` int(11) DEFAULT NULL,
`lifetime` int(11) DEFAULT NULL,
`data` text,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
[/sql]

В классе Bootstrap объявим метод _initSessions():
[php] protected function _initSession()
{
$this->_bootstrap(‘db’); // устанавливает соединение к БД, параметры которой описаны в application.ini
$lifeTime = 1 * 24 * 60 * 60; // время жизни сессии – 1 день
$config = array(
‘name’ => ‘sessions’, // задаем имя таблицы, где будут хранится сессии
‘primary’ => ‘id’, // столбец первичного ключа
‘modifiedColumn’ => ‘modified’, // столбец, для хранения даты изменения сессии
‘dataColumn’ => ‘data’, // столбец для хранения данных
‘lifetimeColumn’ => ‘lifetime’ // столбец для хранения времени жизни сессии
);
Zend_Session::setOptions(array(
‘gc_probability’ => 1, // вероятность 1% запуска функции сборщика мусора (удаления данных)
‘gc_maxlifetime’ => $lifeTime // время, по истечению которого, данные могут быть удалены
));

Zend_Session::setSaveHandler(new Zend_Session_SaveHandler_DbTable($config)); // установим обработчик сохранения сессий
Zend_Session::start(); // запустим сессию
}
[/php]

Все. После этого, все Ваши сессии будут сохраняться в таблице sessions.

Для того, чтобы не возникло проблем при работе с Zend_Auth, необходимо объявить метод инициализации Zend_Auth после метода инициализации сохранения сессий. А также задать хранилище для хранения – Zend_Auth_Storage_Session.
[php] protected function _initAuth()
{
$auth = Zend_Auth::getInstance();
$auth->setStorage(new Zend_Auth_Storage_Session());
return $auth;
}
[/php]

Либо, добавить
[php] $this->_bootstrap(‘Session’);
[/php] в начало метода _initAuth(). Это позволить вызвать метод _initSession первым.

Сообщение Zend Framework: реализация хранения сессий в базе данных появились сначала на Блог Stafox'a.

]]>
https://stafox.cc/zend-framework-store-sessions-in-database/feed/ 0