Моя библиотека - социальная сеть любителей книг

Интро

Сидел на днях перечитывал RSS-ки за пару недель, пытался вновь войти в программистский римт… уж сильно меня увлекло мое давнее увлечение - конструирование шокеров. :) Но об этом, я скорее всего, напишу позже. Так вот, сидел-перечитывал и наткнулся на статьи Владимира Лучанинова “Вернуться назад и сообщить о результате” и “Разные flash для ошибок, сообщений и подтверждений“.

У него статьи посвящены flash-собщениям (я их люблю называть “светофорчиками”) в CakePHP. Читая я вспомнил, что у меня в проектах тоже есть такие сообщения, и они никак не зависят от системы, т.е. их без труда можно будет добавить на любой сайт.

Немного проектирования

Теперь когда все читатели блога в той или иной степени разобрались с UML (статья 1 & статья 2), я решил по мере сил, сопровождать диаграммами код из моих статей. И прошу вас, читатели, быть внимательными и искать неточности в диаграммах - ошибки бывают у всех. :) Будем учиться вместе.

Для реализации сообщений “светофорчиков” нам необходмы 2 класса:

  1. класс описывающий само сообщение;
  2. класс овечающий за отображение сообщений.

И так, диаграмма классов нашего примера:

Диаграмма классов

Все предельно просто и много кодить нам не придется. Зато посетителям сайта будут показываться красивые сообщения. =)

Теперь смоделируем алгоритм работы:

Диаграмма последовательности

На этой диаграмме, для большей налядности, я сделал небольшую неточность - инициализировать объект MessageBox будет скорее всего не пользователь, как показано на диаграмме, а некий объек, например, контроллер. Но т.к. я решил описать реализацию сообщений без привязки к определенной системе, было решено “нагрузить” этой задачей пользователя, но лишь виртуально. :)

Думаю, здесь все понятно и диаграммы не вызывают никаких вопросов. Если же вопросы есть - перчитайте мои статьи по UML.

И совсем немного кода

И вот настал момент, когда слово станет делом. :) Т.е. момент кодирования наших задумок.

Код класса Message выглядит следующим образом:


<?php
class Message
{
	private $content;

	public function __construct(string $content)
	{
		$this->content = $content;
	}

	public function send()
	{
		$_SESSION['session_messages'][] = $this->content;
	}

	public function view()
	{
		return $this->content;
	}
}
?>

Далее опишем класс MessageBox:


<?php
class MessageBox
{
	public $messages = array();

	public function __construct()
	{
		if (isset($_SESSION['session_messages']) && is_array($_SESSION['session_messages'])) {
			$messages = $_SESSION['session_messages'];
			$co = sizeof($messages);
			for ($i = 0; $i < $co; $i++) {
				$this->messages[] =  new Message($messages[$i]);
			}
		}

		//Очищаем массив сообщений он нам больше не нужен
		if (isset($_SESSION['session_messages'])) $_SESSION['session_messages'] = array();
	}

	public function getMessage()
	{
		$data = '';
		for ($i = 0, $k = sizeof($this->messages); $i < $k; $i++) {
			$data .= $this->messages[$i]->view() . '<br/>';
		}
		return $data;
	}
}
?>

Вот и весь код. А теперь как его использовать. Например, после добавлние поста, надо уведомить пользователя о результате опрации:


<?php
$post = new Post();
$post->title = 'Test';
$post->text = '<p>text</p>';

if ($post->save) {
	$msg = new Message('Ваш пост успешно добавлен.');
} else {
	$msg = new Message('Ошибка при добавлении!');
}
$msg->send();

//И редиректим куда необходимо...
header('Location: http://куда_надо');
exit(); //Никогда не забывайте ставить exit() после редиректа
?>

И далее, в зависимости от того как у вас устроена система вызываем класс MessageBox во фронт-контроллере. Например, отрывок кода index.php:


<?php
/**
* Здесь какой-то код
**/

//Т.к. сообщения мы показываем сразу после переадресации
//а она идет при помощи метода GET
if ('POST' != $_SERVER['REQUEST_METHOD']) {
	$mBox = new MessageBox();
	//Передаем сообщения в шаблонизатор
	$view->set('notice', $mBox->getMessage());
}

/**
* Здесь какой-то код
**/
?>

Все сообщения-светофорчики, они же flash-сообщения готовы!

Я описал самый простой вид сообщений. Совершенно логично было бы дополнить класс Message еще одним свойством, например, type. Который бы указывал на тип сообщения: уведомление, ошибка, подтверждение. И в зависимости от типа выбиралось бы CSS оформление сообщения.

Но это я оставляю вам, что б вы тоже не скучали. Может быть, кому то придут интересные мысли по доработке или полной модернизации этих классов, пишите в комментариях - обсудим.



Комментарии (24) на запись «“Светофорчики” или flash-сообщения»

  1. Andrey MonsterID Icon Andrey | 10.12.2007 в 01:34

    Класс Message свойство content всё же сделал бы protected, что бы всё таки можно было переопеделить место хранения сообщения…. Так же не привязывал свойство content к Строке, иногда и объектами надо “светится”.
    Класс MessageBox опять же идёт жесткая привязка к месту хранения, + метод getMessage возращает стороку, лучше массив…

  2. Anton Shevchuk MonsterID Icon Anton Shevchuk | 10.12.2007 в 10:38

    Я бы еще добавил поддержку типов сообщений, и не совал бы все так категорично в сессию.

    И еще насчет реализации, я бы MessageBox() сделал singleton’ом, в нем регистрировал все сообщения и ошибки. В конце выводил бы все сообщения в шаблон.
    Использовал бы сессию только в случае если необходимо сделать редирект и вывести сообщение.

  3. admin MonsterID Icon admin | 10.12.2007 в 14:54

    Andrey
    Класс Message свойство content всё же сделал бы protected, что бы всё таки можно было переопеделить место хранения сообщения…. Так же не привязывал свойство content к Строке, иногда и объектами надо “светится”.
    Класс MessageBox опять же идёт жесткая привязка к месту хранения, + метод getMessage возращает стороку, лучше массив…

    Андрей, все верно. Но вот на счет protected я не уверен… хотя можно и protected :)))
    Я описал самую первую версию реализации сообщений. В последней, четвертой версии, используются типы сообщений и сообщения передаются в виде массивов, а не строк. Но это, как написал в статье, я оставил на совесть читателя.

    Anton Shevchuk
    Я бы еще добавил поддержку типов сообщений, и не совал бы все так категорично в сессию.

    И еще насчет реализации, я бы MessageBox() сделал singleton’ом, в нем регистрировал все сообщения и ошибки. В конце выводил бы все сообщения в шаблон.
    Использовал бы сессию только в случае если необходимо сделать редирект и вывести сообщение.

    Антон, вы не очень внимательно читали мою статью, в конце говориться о добавлении типов сообщений.

    На счет категоричности сессии я думал, и решил что для этой реализации это лучший носитель, хранить в файле или в БД напряжней, и выгоды из этого мы НИКАКОЙ не получим.

    На счет singleton’а согласен. Но дальше немного не понятно, если не сложно объясните как бы вы делали вот это:

    в нем регистрировал все сообщения и ошибки

    А вот эта фраза как-то не соотносится со статьей:

    Использовал бы сессию только в случае если необходимо сделать редирект и вывести сообщение.

    Ведь изначально flash-сообщения - это сообщения показываемые после редиректа. Так, что это замечание мне кажется неуместным, и отсюда следует, что вопрос с местом хранения сообщений решен - это сессии. :)

  4. Andrey MonsterID Icon Andrey | 10.12.2007 в 16:09

    Я не мойму черезмерное желание всё сделать singleton’ом. Куда не глянь если надо инстанцировать объект только в ожном экзампляре, то singleton. Такое впечатление что друих, паттернов никто не знает… Почитайте же вы про управление зависимостьями в коде.

    Последние время private использую крайне редко, если и надо что-то скрыть то protected

  5. admin MonsterID Icon admin | 10.12.2007 в 16:15

    Andrey
    Я не мойму черезмерное желание всё сделать singleton’ом. Куда не глянь если надо инстанцировать объект только в ожном экзампляре, то singleton. Такое впечатление что друих, паттернов никто не знает… Почитайте же вы про управление зависимостьями в коде.

    Не суетись ))) Есть другие, есть. Здесь в принципе подойдет Registry, который уже кстати был описан в этом блоге. =)

    Andrey
    Последние время private использую крайне редко, если и надо что-то скрыть то protected

    А вот с этого места по-подробнее, с чем это связано? Какие плюсы? И на сколько это верно с точки зрения теории ООП?

  6. Andrey MonsterID Icon Andrey | 10.12.2007 в 16:40

    А вот с этого места по-подробнее, с чем это связано? Какие плюсы? И на сколько это верно с точки зрения теории ООП?

    Связано это прежде в всего с тестированием…
    Плюсы, меньше хаков при тестировании и наследовании…
    теории ООП, ну я не призываю всё делать protected, а только там где нужно…

  7. admin MonsterID Icon admin | 10.12.2007 в 16:44

    ну я не призываю всё делать protected, а только там где нужно…

    В данном случае, зачем использовать protected?

  8. Andrey MonsterID Icon Andrey | 10.12.2007 в 17:00

    Например нам надо реализовать помимо хранения сообщений в сессиях ещё и хранение в файлах,

    class MessageBoxWhithFile extend MessageBox
    {
    public function __construct()
    {
    parent::__construct();
    //$messages вызывается в методе _GetMessageFile
    $this->_GetMessageFile();
    }
    }
    Пример конечно плохой, т.к. MessageBox вообще не должен знать место хранения....

  9. admin MonsterID Icon admin | 10.12.2007 в 17:02

    Согласен, не должен, но при чем тут protected?

    _GetMessageFile - это плохо… нужно сделать через полиморфизм, без всяких новых методов, типа _GetMessageFile.

  10. Andrey MonsterID Icon Andrey | 10.12.2007 в 17:07

    можно и без метода _GetMessageFile, но в класс потомок должен видеть свойтво $messages.

  11. admin MonsterID Icon admin | 10.12.2007 в 17:11

    Точно))) Вот и родилась в споре первая истина ))))

  12. Anton Shevchuk MonsterID Icon Anton Shevchuk | 10.12.2007 в 18:28

    Да действительно - не очень внимательно :( - как-то выпал последний абзац. Насчет редиректа - как по мне лучше сделать единый механизм управления сообщениями и пусть сам разработчик поределяет нужен ему редирект или нет.

  13. admin MonsterID Icon admin | 11.12.2007 в 15:41

    @Anton Shevchuk
    Такие сообщения обычно выводятся в ответ на какое-либо действие пользователя, например, добавление или редактирование некоторых данных, при этом редирект просто обязателен, т.к. предотвращает повторную отправку данных.

    Назовите мне случай когда и как можно вывести подобное сообщение без редиректа.

  14. ICEBeer MonsterID Icon ICEBeer | 17.12.2007 в 12:04

    Интересно, а что будет после рефреша страницы сохранения. Уж не пропадёт ли сообщение ;-).

  15. admin MonsterID Icon admin | 17.12.2007 в 23:51

    ICEBeer
    Интересно, а что будет после рефреша страницы сохранения. Уж не пропадёт ли сообщение ;-).

    Простите, не понял… что вы собираетесь обновлять? Какую страницу? До отправки данных или после?

  16. ICEBeer MonsterID Icon ICEBeer | 18.12.2007 в 13:25

    To Admin.
    После отправки данных. Скрипт меня перенаправил на страницу, где выводится сообщение об ошибке либо об успешном сохранении. Так вот, судя по коду, когда я нажму F5 данное сообщение пропадёт…

  17. admin MonsterID Icon admin | 19.12.2007 в 01:57

    После отправки данных. Скрипт меня перенаправил на страницу, где выводится сообщение об ошибке либо об успешном сохранении.

    Конечно пропадет. Оно же должно показаться только один раз. И вы его уже увидели, раз жмете F5. )))

  18. ICEBeer MonsterID Icon ICEBeer | 19.12.2007 в 12:30

    To Admin.
    Ну ситуации разные бывают. Например я использую отдельную страницу для отображения результата сохранения. Я делаю вот таким каким образом, сохраняю в сессии URI страницы, для которой предназначено это сообщение и только при условии, что мы находимся не на странице результатов удаляю из сессии переменные.

  19. admin MonsterID Icon admin | 19.12.2007 в 21:23

    ICEBeer
    Ну ситуации разные бывают. Например я использую отдельную страницу для отображения результата сохранения. Я делаю вот таким каким образом, сохраняю в сессии URI страницы, для которой предназначено это сообщение и только при условии, что мы находимся не на странице результатов удаляю из сессии переменные.

    Да ситуации разные бывают, но меня пока описанные классы не подводили.
    Я раньше тоже использовал промежуточную страницу для вывода результатов, но за пару лет сумел убедиться, что это жутко не удобно, да и не нужно.

  20. FX Poster MonsterID Icon FX Poster | 14.01.2008 в 10:23

    Ну что ж, с открытием ;)

  21. admin MonsterID Icon admin | 14.01.2008 в 14:53

    FX Poster, ты об чем?

  22. FX Poster MonsterID Icon FX Poster | 24.01.2008 в 15:09

    О библиотеке. Я на ИШ прочитал. :)

  23. admin MonsterID Icon admin | 24.01.2008 в 16:23

    О библиотеке. Я на ИШ прочитал. :)

    А, спасибо! Я долго ждал этого открытия)))

  24. LARIN.in » Архив блога » AJAX-светофорчики | 12.08.2008 в 22:21

    [...] свободная минутка… В далеком 2007-ом году у меня была статья о “flash-сообщениях” - сообщения которые мы показываем пользователю после [...]

Оставить комментарий


Copyright, 1983 – 2010