{{Laracast Laravel 5 Fundamentals, 20, Flash Messaging, 4.02.2015, 15.07.2016, https://laracasts.com/series/laravel-5-fundamentals/episodes/20}} %%(hvlraw) %% (0:00) Вот о чём я хочу, чтобы вы подумали. Часто когда пользователь выполняет какое-либо действие в вашем приложении, вы хотите дать ему какое-то уведомление, чтобы сообщить, например: "Эй, ваша учетная запись была успешно деактивирована". Поэтому, возможно, это было бы полезно и для нашего маленького блога здесь. Введём %%(t)Blog Article%%, небольшой текст и опубликуем статью. И заметьте, что, да, нас сюда перенаправили, и если честно, в данном случае совершенно очевидно, что всё прошло успешно. (0:30) Но, как вы можете себе представить, во многих других случаях, вам действительно понадобятся какие-то уведомления. Даже нечто настолько простое, как нажатие на кнопку %%(t)Log Out%%, может выдать вам сообщение, подтверждающее статус: "Вы вышли из системы". Давайте в этом уроке разберёмся как с этим справиться. Я покажу вам два способа, во-первых, мы сделаем это вручную, а затем дальше, я покажу вам небольшой пакет, который вы сможете притянуть, и с его помощью можно до смешного просто всё это сделать. Наш первый шаг - идём на %%ArticlesController%%. (1:00) Теперь, когда пользователь создаёт новую статью, как мы знаем, метод %%store()%% вызывается, когда мы сделали новую статью и сохранили её. И на самом деле, немного не в тему - здесь мы создаём статью и передаём её методу сохранения %%save()%%, но также, если вы предпочитаете, то могли бы использовать метод %%create()%%. Так же, как мы это делали, когда мы передавали массив атрибутов: %% Article::create([]); %% то же самое было бы верно здесь. Так что если вы хотите, вы могли бы сказать: получить статьи аутентифицированного пользователя и создать новую, используя запрос из формы: %% Auth::user()->articles()->create($request->all()); %% (1:30) так что, если мы удалим вот это, то всё будет по-прежнему работать точно таким же образом. Хорошо, но в любом случае, мы создали новую статью, и мы перенаправим пользователя назад к списку статей, но я также хочу отобразить то, что мы называем "сообщением-вспышкой" (flash). Сообщение, которое показывается на экране для следующего запроса, а позднее, если перезагрузить страницу, его больше не будет видно. Вот как мы можем сделать это в Laravel. У нас есть фасад сессии, так что мы могли бы сказать: %% \Session::flash('flash message', 'Your article has been created!'); %% (2:00) Я хочу показать сообщение, мы даём ему какой-нибудь идентификатор, %%(t)flash message%%, а затем тело, как насчет %%(t)Your article has been created%% (т.е. ваша статья была создана). Хорошо, это сработает для конкретной сессии. Однако, когда мы перенаправляем, то мы не увидим это сообщение, нам всё равно нужно отобразить его где-то в нашем представлении. Так давайте сделаем это. Давайте вернёмся к нашей мастер-странице; если это относится к каждому виду, то мастер-страница – хорошее место, куда это стоит поместить. (2:30) И давайте вставим это прямо здесь, в верхней части нашего контейнера, и позднее мы сможем извлечь паршл, но сейчас давайте просто вставим наш код прямо здесь. Давайте скажем, если у сессии есть этот ключ: %% @if (Session::has('flash message')) %% то в этом случае мы хотим отобразить его. Так почему бы нам не использовать: %%(h)
%% Это специфические классы из Twitter Bootstrap, которые просто немного облегчат нам работу. И потом внутри здесь мы выведем сообщение %% {{ Session::get('flash_message') }} %% (3:00) ОК, таким образом, мы уже узнали несколько методов API. Для начала – %%\Session::flash()%%. Думайте о нём, в качестве единовременного флэш-сообщения. Также есть такие вещи, как %%\Session::put()%% – поместить это в сессию. Разница между этим и flash-сообщением в том, что последнее носит временный характер, только для одного запроса. Так что у нас есть эти два, и ещё мы можем увидеть такие методы, как %%Session::has()%%. Есть ли у нас этот ключ в сессии? (3:30) И если он есть, то через %%get()%% получим значение, связанное с этим ключом. Давайте посмотрим, как это выглядит в браузере. Поэтому ещё раз я создам новую статью. Просто напишем %%(t)test%% (в название) и %%(t)test%% (в тело), и, когда мы добавим статью, точно, вы увидите сообщение прямо здесь. Теперь вот что я имел в виду про то, что это одноразовое сообщение. Если мы перезагрузим эту страницу, сообщение только промелькнуло, так что мы его больше не видим, и это значит, что это идеально подходит для таких маленьких сообщений с уведомлениями. (4:00) Вы вероятно обнаружите, что для большинства производственных приложений вам понадобится немного больше гибкости. Например, когда нас перенаправляют назад на эту страницу с flash-сообщением, оно как бы отображается всё время. Может быть, вы хотите отображать сообщение в течение четырех секунд и чтобы затем оно ускользнуло наверх? Вы хотите, чтобы оно исчезло. Но в других ситуациях, для действительно важных сообщений, вы и правда хотите, чтобы они отображались постоянно. И чтобы пользователь должен был нажать на маленькую кнопку 'х', чтобы признать, что "Да", он прочитал сообщение и теперь хочет удалить его. (4:30) Так что, похоже, что на самом деле, нам нужно здесь чуть больше гибкости. Давайте посмотрим, как мы могли бы это сделать. Ну, для начала, если мы вернёмся к нашему представлению, то почему бы нам не добавить маленький %%(t)х%% наверху, и я просто вставлю вот этот код: %%(h) %% Это на самом деле взято с сайта Twitter Bootstrap. Просто код, который можно добавить чтобы поставить кнопочку %%(t)х%%. Итак, позвольте мне показать вам, как это выглядит. %%(t) laravel5.dev/articles/create %% %%(t)test2%%, опубликуем статью. И теперь мы получаем сообщение, и вы увидите, вот он маленький %%(t)х%%. (5:00) Но если я нажму на него, то ничего пока не происходит, потому что Twitter Bootstrap там требуется немного JavaScript. Так почему бы нам не добавить его? Давайте разместим это внизу, прямо перед закрывающим %%(t)%%. И для реального проекта вы, вероятно, будете хранить его локально. Но я просто вставлю это здесь. Мы получаем последнюю версию jQuery, даже не версию в кэше, просто будем ссылаться на неё напрямую. И далее у нас есть весь JavaScript для Twitter Bootstrap, который хранится на CDN. (5:30) Так что имейте в виду, мы делаем это для удобства. На самом деле, если вы используете Twitter Bootstrap, вы можете загрузить специальный файл JavaScript, который будет включать в себя только те компоненты, которые ваше приложение на самом деле станет использовать. Но это всего лишь пример, и для нас этого здесь вполне достаточно. Так что теперь давайте попробуем ещё разок. Мы создадим третью тестовую статью %%(t)test3%%, и если мы добавим её сейчас, то у нас есть кнопка %%(t)х%%, и если мы нажимаем на неё, наше сообщение будет удалено. Довольно просто. (6:00) Но, как я уже сказал, в некоторых ситуациях, вы можете захотеть это использовать, а в других, вам не нужно, чтобы пользователь нажимал на кнопку закрытия. Вы просто захотите быстрое сообщение, которое исчезнет через две-три секунды. Так что, может быть, вы могли бы отображать кнопку только тогда, когда в сессии устанавливается некоторое другое значение. Например: %% @if (Session::has('flash_message_important')) %% в таком случае мы хотим сохранить его на экране до тех пор, пока пользователь не удалит его. Так что отображаем кнопку только при этом условии. (6:30) Мы могли бы сказать: если у нас есть %%(t)flash_message_important%%, в этом случае давайте добавим здесь класс %%(t)alert_important%%. В противном случае мы не должны ничего отображать: %% {{ Session::has('flash_message_important') ? 'alert-important' : '' }} %% И кстати, здесь, у нас также есть функции-помощники, в Laravel 5 есть функция %%session()%%. И она на самом деле может быть довольно гибкой. Если мы посмотрим на неё вот здесь (в %%(t)Foundation/helpers.php%%). (7:00) Если мы просто вызовем %%(t)session()%%, и мы ничего не передадим, нам вернётся то, что хранится в контейнере IoC, так что вы всё ещё можете делать нечто вроде %%session()->get()%% or %%session()->flash()%%, и всё прочее. Очень похоже на использование %%redirect()%% или %%view()%%. Но если мы передаем туда массив, то Laravel будет считать, что мы даём что-то для сессии. И, наконец, если мы просто передаём какую-то строку, то предполагается, что мы делаем эквивалент %%Session::get()%%. И это значит, если я переключусь обратно (к %%(t)app.blade.php%%), вы могли бы изменить это примерно так: %% {{ session('flash_message') }} %% (7:30) и получить точно такой же эффект. Также это означает, идём назад в %%ArticlesController%%, что вместо того, чтобы добавлять %%use Session%% в верхней части файла или глобально ссылаться на него, как мы сделали здесь, вы могли бы просто сказать %%session()->flash()%%. Вот так. Хорошо, давайте вернемся к нашему представлению. Теперь, если мы даём сессии ключ %%(t)flash_message%%, то на самый следующий запрос мы отобразим его. Но также, если существует нечто под названием %%(t)flash_message_important%%, то мы хотим также отобразить кнопку закрытия. (8:00) Наконец, мы могли бы написать немного JavaScript, чтобы скрыть сообщение. И я просто использую здесь немного jQuery. Мы по сути хотим сказать: "дайте мне %%(t)div%%, с классом %%(t)alert%%, то есть, дайте мне коллекцию всех элементов на странице, которые соответствуют CSS, но отфильтруйте их, потому что я не заинтересован в элементах класса %%(t)alert_important%%, которые не должны применяться. %%(js) $('div.alert').not('.alert-important') %% Тогда мы просто хотим подождать, задержку в течение примерно 3 секунд, и затем сдвинуть сообщение вверх. %%(js) $('div.alert').not('.alert-important').delay(3000).slideUp(300) %% (8:30) Хорошо, давайте посмотрим на это в браузере. Так что ещё раз мы создаем четвёртый пост в блоге. Мы добавляем его и обратите внимание, что сообщение отображается в течение нескольких секунд, а затем ускользает наверх. Круто, не так ли? Но теперь мы передадим дополнительный ключ к этой сессии. Вернёмся к нашему редактору, открываем %%ArticlesController%%, и теперь, на самом деле, мы можем это сделать несколькими способами. Один, продублируем это, вот так: %% session()->flash('flash_message', 'Your article has been created!'); session()->flash('flash_message_important', true) %% (9:00) Давайте посмотрим, если это сработает. Это будет наша пятая попытка (пишем %%(t)Fifth%%). Таким образом, мы добавим статью, и теперь вы увидите, что она не скрылась, но у нас есть кнопка %%(t)х%%, так что вы можете вручную отключить сообщение, когда его прочитаете. Круто, но, как я уже сказал, есть несколько способов сделать это. Так что да, мы могли бы сделать это так, но также мы могли бы добавить здесь метод %%with()%%. Итак, когда мы делаем %%redirect()%% и вызываем %%with()%%, это предполагает, что мы выведем flash-сообщение. (9:30) Так что мы могли бы сделать так: %% return redirect('articles')->with([ 'flash_message' => 'Your article has been created', 'flash_message_important' => true ]); %% И этот подход был бы эквивалентен. Теперь, всякий раз когда мы создаем новую статью, мы перенаправляем обратно на страницу списка статей, и также, в процессе через "вспышку" передаём несколько ключей для сессии. Сообщение и индикатор того, является ли оно важным и должно остаться или не столь важное и может исчезнуть. (10:00) Так что, если мы вернемся к %%(t)app.blade.php%%, это прекрасный пример того, что можно выделить в partial. Давайте откроем нашу боковую панель и перейдём в %%(t)resources/views%%. И давайте добавим здесь каталог %%(t)partials%% - %%(t)partials/flash.blade.php%% и сюда я его и вставлю. Теперь, если я переключусь назад, я могу сказать: %% @include('partials.flash') %% и мы получим тот же конечный результат. (10:30) Здорово, теперь вы знаете, как это делать, но до сих пор это не меняет тот факт, что код всё ещё является немного громоздким. На самом деле, вот что я предпочёл бы сделать в моём реальном проекте. Может быть, я бы вызвал функцию %%flash()%% например так: %% flash('Your article has been created'); %% и затем я мог бы удалить всё это и перенаправить. И это бы всё ещё дало тот же самый результат. И потом, если бы я захотел показать что это важно, то может быть, я бы ещё добавил метод important(): %% flash('Your article has been created')->important(); %% Это было бы предпочтительнее, на мой взгляд. И на самом деле нечто подобное очень легко реализовать. (11:00) Я уже забежал вперёд и сделал это, так что если вы хотите, то можете притянуть небольшой пакет, который даёт вам такого рода API. Давайте я покажу как это сделать. Назад в терминал, я сделаю: %%(sh) composer require laracasts/flash %% и теперь пока это притягивается, мы можем пойти в наш файл %%(t)config/app.php%% и нам нужно добавить поставщика услуг, так что мы можем сделать это прямо здесь: %% 'Laracasts\Flash\FlashServiceProvider' %% (11:30) и быстрое замечание здесь, если вы когда-нибудь задумывались, "Откуда же я должен был это знать?". Для любого пакета, который вы можете притянуть, вам достаточно посмотреть документацию часто прямо на GitHub, и там вам скажут точно что нужно делать. * Шаг 1 - %%(t)composer require%% * Шаг 2 - добавить поставщика услуг * Шаг 3 - добавить псевдоним (alias) И на этой ноте, если вы хотите сделать специальный фасад, то вы можете добавить его здесь, но это не обязательный шаг. Вы могли бы сделать что-то вроде этого: %% 'Flash' => 'Laracasts\Flash\Flash' %% (12:00) Хорошо, это должно сработать. Назад к %%ArticlesController%%. Теперь, да, у нас есть вспомогательная функция, которую вы могли бы использовать. Или, если вы предпочитаете подход с фасадом, то могли бы сказать %%\Flash%%... и информационное сообщение: %% \Flash::info() %% или сообщение об ошибке: %% \Flash::error() %% или сообщение об успешном выполнении: %% \Flash::success() %% а потом за кадром автоматически обрабатывается процесс настройки для вас этих ключей. Позвольте мне показать вам, как это выглядит. Существует класс-уведомитель, и заметьте, к примеру, если бы мы запустили %%\Flash::success()%%, то мы создаём новое flash-сообщение, и оно только передаёт несколько ключей в сессию. (12:30) Очень похоже на то, как мы делали раньше. Это просто даёт вам более хороший API или более хорошую обертку, чтобы вам не пришлось повторяться снова и снова. И также круто, что у вас есть несколько представлений, которые вы могли бы притянуть и модифицировать как вам нужно. Итак, позвольте мне показать вам, как это работает. Давайте вернёмся к %%(t)app.blade.php%%, и мы не будем ссылаться на наш собственный partial, мы сошлёмся на partial из представления. Откроем %%(t)flash/message.blade.php%%. (13:00) И вы увидите – это то, что мы получаем из пакета. Так что, если мы переключимся назад, я могу включить представление из пакета с помощью ссылки на имя пакета – %%(t)flash::%% и затем имя нужного представления (в этом случае оно называется %%(t)message%%): %% @include ('flash::message') %% Итак, давайте посмотрим, как это выглядит. Просто чтобы убедиться, что вы всё поняли – мы создаём статью, мы выдаём flash-сообщение, и затем мы перенаправляемся назад к списку статей. ОК, давайте попробуем. (13:30) Мы создаём новую статью. Я думаю, что мы сейчас находимся на седьмой, добавим её, и ещё раз мы получим тот же самый результат. В данном случае у нас было информационное сообщение, но может быть, вы захотите сообщение об успешном исполнении, тогда можно сказать: %% flash()->success() %% и передать текст сообщения. И вы увидите, что в основном, вся разница в том, что мы добавили другое имя класса, а затем Twitter Bootstrap узнал его, но если вы не используете его, то вы можете подключиться к нему с помощью CSS и стилизовать его как вы захотите. (14:00) Так что на этот раз я думаю, что результат должен быть зелёным. И, да, сообщение зелёное. Мы уже видели flash-сообщения, которые должны оставаться или скрываться, но, возможно, вы также захотите, своего рода, накладываемое сообщение. Так, например, если вы зарегистрируетесь на Laracasts, я отображаю модальное окно, которое говорит: "Эй, добро пожаловать на Laracasts! Большое спасибо за регистрацию!". Это немного другой стиль и он также идёт в пакете. Позвольте я вам покажу. На этот раз, вместо сообщения %%success()%%, мы используем сообщение %%overlay()%%. (14:30) И вы увидите, если мы перейдём прямо к нему, к функции %%overlay()%% в %%(t)FlashNotifier.php%%, то здесь мы даём ей сообщение, а также заголовок, так что, мы могли бы сказать: %% flash()->overlay('Your article has been successfully created!', 'Good Job'); %% На самом деле не очень хороший пример для использования наложения, но вы поняли идею. Так что если вы захотите использовать этот метод, то единственное, что вам придётся сделать, это активировать его. Так что я закомментирую вот это, и мы выберем %%modal()%%. Если мы вкратце его рассмотрим, то вы увидите, что у нас есть %%(t)id="flash-overlay-modal"%%. (15:00) Так что вы можете найти его просто вызывая на нём метод %%modal()%%: %%(js) $('#flash-overlay-modal').modal(); %% Ещё раз, мы просто используем здесь плагин Twitter Bootstrap, поэтому мы ссылаемся на скрипт, и затем мы активируем плагин, так сказать. Хорошо, так почему бы нам не попробовать это в браузере? Последний раз уже, я думаю. Мы пишем: %%(t)final%%, %%(t)final%%, добавим статью, и на этот раз мы получаем накладку, которую вы можете просмотреть и закрыть, когда готовы. Итак, на самом деле это всё что нужно здесь знать. (15:30) Вы можете притянуть этот пакет, или если вы не хотите этим заморачиваться, то не забывайте, что вы всё ещё можете сказать: %% session()->flash('') %% и потом всё, что вам нужно сделать, это в вашем представлении слушать, существует ли ключ с таким именем, и если это так, то выдать значение, связанное с ним. "Вы зарегистрированы!" или нечто в этом роде. Так что на Laracasts, например, я использую именно этот пакет, когда вы зарегистрировались. У меня есть небольшое сообщение, которое говорит что вы вошли: %% flash('You are now logged in'); %% (16:00) Это чистый, быстрый, простой способ, и это намного проще, чем всегда добавлять %%with()%%: %% return redirect('articles')->with('flash_message', 'You are now logged in.'); %% Эти маленькие победы, когда вы делаете ваш код чуть чище и чуть короче, действительно имеют большой эффект на конечный результат. Хорошо, так что теперь вы освоили искусство сообщений-вспышек.