четверг, 22 марта 2012 г.

Работа с flash-сообщениями в Yii Framework

Предисловие

Как-то захотелось выводить в приложении сообщения о результате каких-либо действий пользователя или после выполнения определённых транзакций выводить результат операции.

Оказалось, что в Yii уже заложен простой функционал вывода подобных сообщений. Работа с этим уже описана, например в [1]. Также можно заглянуть в описание API на yiiframework.com. Тем не менее разобравшись один раз, захотелось записать для себя, а может и ещё для кого-нибудь, более подробнее как это работает.

Работа с flash-сообщениями

Можно задать сколько угодно flash-сообщений. Для работы с ними используются методы класса CWebUser: setFlash, getFlash, hasFlash, hasFlashes.

Для обращения к методам необходимо воспользоваться свойством user объекта-приложения, возвращающего экземпляр класса CWebUser:

Yii::app()->user

Метод setFlash

Метод setFlash устанавливает сообщение, которое сохраняется в сессии пользователя ($_SESSION) и определено следующим образом:

setFlash($key,$value,$defaultValue=null)
где:
$key - идентификатор сообщения;
$value - собственно текст сообщения;
$defaultValue - судя по имени, сообщение по умолчанию. Но на самом деле особого значения не имеет. Как описано в API, если значение $defaultValue такое же, как и $value, то сообщение с идентификатором $key будет удалено. То есть для удаления сообщения можно при вызове функции указать значение $value как null для идентификатора $key, который необходимо удалить.

Примеры использования:

//Установка сообщения с идентификатором 'error'
setFlash('error','Ошибка выполнения операции')

//Сообщение с идентификатором 'error' будет удалено
setFlash('error',null)

Метод hasFlash

Метод hasFlash является функцией, проверяющей наличие уже установленного сообщения с идентификатором $key и возвращающая boolean значение в зависимости от результата. Синтаксис:

bool hasFlash($key)

Пример использования:

// Будет выведено сообщение с идентификатором 'error',
// если оно существует
if (Yii::app()->user->hasFlash('error'))
{
    echo Yii::app()->user->getFlash('error');
}

Метод getFlash и вывод сообщения

Метод getFlash:

string getFlash($key, $defaultValue=null, $delete=true)

Позволяет получить текст сообщения по заданному идентификатору $key. Так же можно задать необязательные параметры $defaultValue и $delete.

$defaultValue задаёт значение, которое будет выводиться, если сообщение с указанным идентификатором не существует. По умолчанию равно null.

$delete определяет будет ли удалено сообщение после вызова функцией getFlash или нет. По умолчанию равно true. То есть после вызова сообщения оно будет удалено, если явно не задать параметр $delete при вызове функции равным false.

// После вызова сообщение НЕ будет удалено
// и может быть вызвано повторно
Yii::app()->user->getFlash('error', 'Операция проведена успешно!', false); 

// После вызова сообщение будет удалено
Yii::app()->user->getFlash('error', 'Операция проведена успешно!'); 

На самом деле, функция getFlash возвращает всего лишь текст сообщения. Следовательно, если просто выводить его, например, инструкцией echo, то этот текст ничем не будет отличаться от остального.

Для визуализации flash-сообщения используются классы стилей оформления блока <div>, определённые в таблице стилей [каталог_приложения]/css/main.css:

flash-error - вывод информации об ошибке;
flash-notice - вывод уведомления, предупреждения;
flash-success - вывод информации об успешной операции.

Примерно в таком виде:

<div class="flash-error">
    <?php echo Yii::app()->user->getFlash('error'); ?>
</div>

Что выведет оформленный соостветствующим образом блок с сообщением об ошибке.

Используя main.css можно описать свой стиль оформления какого-нибудь сообщения, например, flash-info, для чего определить описание для соответствующего селектора (в данном случае div.flash-info) в таблице стилей подобно описанию существующих стилей блоков-сообщений.

Метод getFlashes

Метод getFlashes возвращает ассоциативный массив всех определённых в сеансе пользователя flash-сообщений в формате "идентификатор" => "сообщение":

array getFlashes($delete=true)

При вызове метода можно указать boolean-значение $delete, указывающее, надо ли удалять все сообщения. По умолчанию после вызова функции все сообщения будут удалены, если явно не указан параметр false при вызове функции.

Когда метод может быть полезен? Например, при выполнении транзакции, включающей в себя несколько операций, таких как, проверка на валидность введенных данных, запрос к БД, обработка результатов запроса и т.д., на каждом этапе может возникнуть исключение. Можно перехватывая эти исключения устанавливать соответствующие flash-сообщения, например 'check_error', 'db_error' и т.д. с текстом ошибки исключения (Exception::getMesage()). Затем после завершения транзакции, чтобы не перебирать все сообщения можно воспользоваться методом getFlashes:

$flashes = Yii::app()->user->getFlashes();
if ($flashes)
{
    echo "<div class=\"flash-error\">\n";
    echo "При выполнении операции возникли исключения:\n";
    foreach ($flashes as $error_id => $error_text)
    {
        echo "$error_id: $error_text<br /><br />\n";
    }
    echo "</div>\n";
}

Ссылки на использованные ресурсы

  1. Alexander Makarov. Yii 1.1 Application Development Cookbook. - PACKT Publishing, 2011
  2. Русскоязычное сообщество Yii
  3. Официальная страница Yii Framework