В Laravel лучший способ передавать различные типы флеш-сообщений в сеансе

47

Я делаю свое первое приложение в Laravel и пытаюсь разгадать флеш-сообщения сессии. Насколько я знаю в своем управлении контроллером, я могу установить флеш-сообщение, перейдя

Redirect::to('users/login')->with('message', 'Thanks for registering!'); //is this actually OK?

В случае перенаправления на другой маршрут или

Session::flash('message', 'This is a message!'); 

В моем шаблоне базового лезвия я имел бы:

@if(Session::has('message'))
<p class="alert alert-info">{{ Session::get('message') }}</p>
@endif

Как вы могли заметить, я использую Bootstrap 3 в своем приложении и хотел бы использовать различные классы сообщений: alert-info, alert-warning, alert-danger и т.д.

Предполагая, что в моем контроллере я знаю, какое сообщение я устанавливаю, какой лучший способ передать и отобразить его в представлении? Должен ли я установить отдельное сообщение в сеансе для каждого типа (например, Session::flash('message_danger', 'This is a nasty message! Something wrong.');)? Тогда мне понадобится отдельный оператор if для каждого сообщения в моем шаблоне клинка.

Любые советы приветствуются.

Теги:
session
laravel-4

10 ответов

89
Лучший ответ

Одним из решений было бы запустить в сеанс две переменные:

  • Само сообщение
  • "Класс" вашего оповещения

например:

Session::flash('message', 'This is a message!'); 
Session::flash('alert-class', 'alert-danger'); 

Тогда, на ваш взгляд:

@if(Session::has('message'))
<p class="alert {{ Session::get('alert-class', 'alert-info') }}">{{ Session::get('message') }}</p>
@endif

Примечание. Я поместил значение по умолчанию в Session::get(). таким образом вам нужно только переопределить его, если предупреждение должно быть чем-то иным, чем класс alert-info.

(это быстрый пример и непроверенный:))

  • 2
    Интересно, что я не знал о параметре по умолчанию для Session::get() который очень пригодится.
  • 1
    Как и большинство решений для флеш-сообщений, это касается только одного сообщения. Очень часто необходимо иметь возможность отправлять кучу сообщений, каждое из которых может иметь различную серьезность, и отображать их все.
Показать ещё 3 комментария
25

На ваш взгляд:

<div class="flash-message">
  @foreach (['danger', 'warning', 'success', 'info'] as $msg)
    @if(Session::has('alert-' . $msg))
    <p class="alert alert-{{ $msg }}">{{ Session::get('alert-' . $msg) }}</p>
    @endif
  @endforeach
</div>

Затем установите в контроллере флэш-сообщение:

Session::flash('alert-danger', 'danger');
Session::flash('alert-warning', 'warning');
Session::flash('alert-success', 'success');
Session::flash('alert-info', 'info');
20

Мой путь - всегда перенаправлять:: назад() или перенаправить:: в():

Redirect::back()->with('message', 'error|There was an error...');

Redirect::back()->with('message', 'message|Record updated.');

Redirect::to('/')->with('message', 'success|Record updated.');

У меня есть вспомогательная функция, чтобы заставить ее работать для меня, обычно это в отдельной службе:

function displayAlert()
{
      if (Session::has('message'))
      {
         list($type, $message) = explode('|', Session::get('message'));

         $type = $type == 'error' : 'danger';
         $type = $type == 'message' : 'info';

         return sprintf('<div class="alert alert-%s">%s</div>', $type, message);
      }

      return '';
}

И в моем представлении или макете я просто делаю

{{ displayAlert() }}
  • 0
    Отличное решение! Просто хочу сказать, что в вашем закрывающем классе div есть опечатка, где "отсутствует" (я не могу отредактировать его, поскольку мое редактирование должно содержать не менее 6 символов ...).
  • 4
    Это просто замечательно, но как это работает? $type = $type == 'error' : 'danger';
Показать ещё 1 комментарий
6

Просто вернитесь с "флагом", который вы хотите обработать, без использования каких-либо дополнительных функций пользователя. Контроллер:

return \Redirect::back()->withSuccess( 'Message you want show in View' );

Обратите внимание, что я использовал флаг "Успех".

Вид:

@if( Session::has( 'success' ))
     {{ Session::get( 'success' ) }}
@elseif( Session::has( 'warning' ))
     {{ Session::get( 'warning' ) }} <!-- here to 'withWarning()' -->
@endif

Да, это действительно работает!

  • 0
    В вашем ответе масса опечаток, но ваш подход работает отлично.
5

Вы можете создавать несколько сообщений и с разными типами. Выполните следующие шаги:

  • Создайте файл: "app/Components/FlashMessages.php"
namespace App\Components;

trait FlashMessages
{
  protected static function message($level = 'info', $message = null)
  {
      if (session()->has('messages')) {
          $messages = session()->pull('messages');
      }

      $messages[] = $message = ['level' => $level, 'message' => $message];

      session()->flash('messages', $messages);

      return $message;
  }

  protected static function messages()
  {
      return self::hasMessages() ? session()->pull('messages') : [];
  }

  protected static function hasMessages()
  {
      return session()->has('messages');
  }

  protected static function success($message)
  {
      return self::message('success', $message);
  }

  protected static function info($message)
  {
      return self::message('info', $message);
  }

  protected static function warning($message)
  {
      return self::message('warning', $message);
  }

  protected static function danger($message)
  {
      return self::message('danger', $message);
  }
}
  1. На вашем базовом контроллере "app/Http/Controllers/Controller.php".
namespace App\Http\Controllers;

use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Auth\Access\AuthorizesResources;

use App\Components\FlashMessages;

class Controller extends BaseController
{
    use AuthorizesRequests, AuthorizesResources, DispatchesJobs, ValidatesRequests;

    use FlashMessages;
}

Это сделает признак FlashMessages доступным для всех контроллеров, расширяющих этот класс.

  1. Создайте шаблон клипа для наших сообщений: "views/partials/messages.blade.php"
@if (count($messages))
<div class="row">
  <div class="col-md-12">
  @foreach ($messages as $message)
      <div class="alert alert-{{ $message['level'] }}">{!! $message['message'] !!}</div>
  @endforeach
  </div>
</div>
@endif
  1. В "boot()" методе "app/Providers/AppServiceProvider.php":
namespace App\Providers;

use Illuminate\Support\ServiceProvider; 

use App\Components\FlashMessages;

class AppServiceProvider extends ServiceProvider
{
  use FlashMessages;

    public function boot()
    {
        view()->composer('partials.messages', function ($view) {

          $messages = self::messages();

          return $view->with('messages', $messages);
      });
    }

    ...
}

Это сделает переменную $messages доступной для шаблона "views/partials/message.blade.php" всякий раз, когда она вызывается.

  1. В вашем шаблоне включите наш шаблон сообщений - "views/partials/messages.blade.php"
<div class="row">
  <p>Page title goes here</p>
</div>

@include ('partials.messages')

<div class="row">
  <div class="col-md-12">
      Page content goes here
  </div>
</div>

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

  1. На вашем контроллере вы можете просто сделать это, чтобы нажимать флэш-сообщения:
use App\Components\FlashMessages;

class ProductsController {

  use FlashMessages;

  public function store(Request $request)
  {
      self::message('info', 'Just a plain message.');
      self::message('success', 'Item has been added.');
      self::message('warning', 'Service is currently under maintenance.');
      self::message('danger', 'An unknown error occured.');

      //or

      self::info('Just a plain message.');
      self::success('Item has been added.');
      self::warning('Service is currently under maintenance.');
      self::danger('An unknown error occured.');
  }

  ...

Надеюсь, он вам поможет.

5

Если вы работаете с Laravel 5, проверьте этот пакет на laracasts:

https://github.com/laracasts/flash

  • 0
    спасибо, я думаю, что это лучшее решение :)
4

Другим решением было бы создать вспомогательный класс Как создать классы-помощники здесь

class Helper{
     public static function format_message($message,$type)
    {
         return '<p class="alert alert-'.$type.'">'.$message.'</p>'
    }
}

Тогда вы можете это сделать.

Redirect::to('users/login')->with('message', Helper::format_message('A bla blah occured','error'));

или

Redirect::to('users/login')->with('message', Helper::format_message('Thanks for registering!','info'));

и на ваш взгляд

@if(Session::has('message'))
    {{Session::get('message')}}
@endif
  • 4
    Я не знаю, рекомендую ли я такой подход, так как он выводит HTML из вида в код.
2

Для моего приложения я создал вспомогательную функцию:

function message( $message , $status = 'success', $redirectPath = null )
{
     $redirectPath = $redirectPath == null ? back() : redirect( $redirectPath );

     return $redirectPath->with([
         'message'   =>  $message,
         'status'    =>  $status,
    ]);
}

макет сообщения, "main.layouts.message":

@if($status)
   <div class="center-block affix alert alert-{{$status}}">
     <i class="fa fa-{{ $status == 'success' ? 'check' : $status}}"></i>
     <span>
        {{ $message }}
     </span>
   </div>
@endif

и импортировать все, где показывать сообщение:

@include('main.layouts.message', [
    'status'    =>  session('status'),
    'message'   =>  session('message'),
])
1

Вы можете использовать макросы Laravel.

Вы можете создать macros.php в app/helpers и включить его route.php.

если вы хотите поместить свои макросы в файл класса, вы можете посмотреть этот учебник: http://chrishayes.ca/blog/code/laravel-4-object-oriented-form-html-macros-classes-service-provider

HTML::macro('alert', function($class='alert-danger', $value="",$show=false)
{

    $display = $show ? 'display:block' : 'display:none';

    return
        '<div class="alert '.$class.'" style="'.$display.'">
            <button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
            <strong><i class="fa fa-times"></i></strong>'.$value.'
        </div>';
});

В вашем контроллере:

Session::flash('message', 'This is so dangerous!'); 
Session::flash('alert', 'alert-danger');

В вашем представлении

@if(Session::has('message') && Session::has('alert') )
  {{HTML::alert($class=Session::get('alert'), $value=Session::get('message'), $show=true)}}
@endif
0

Я обычно делаю это

в моей функции store() я поставлю предупреждение об успешном завершении.

\Session::flash('flash_message','Office successfully updated.');

в моей функции destroy(), я хотел покрасить предупреждение red, чтобы уведомить, что его удаленный

\Session::flash('flash_message_delete','Office successfully deleted.');

Обратите внимание: мы создаем два предупреждения с разными именами флэш.

И, на мой взгляд, я добавлю условие, когда в нужное время будет называться конкретное предупреждение

@if(Session::has('flash_message'))
    <div class="alert alert-success"><span class="glyphicon glyphicon-ok"></span><em> {!! session('flash_message') !!}</em></div>
@endif
@if(Session::has('flash_message_delete'))
    <div class="alert alert-danger"><span class="glyphicon glyphicon-ok"></span><em> {!! session('flash_message_delete') !!}</em></div>
@endif

Здесь вы можете найти различные флэш-сообщения stlyes Flash-сообщения в Laravel 5

Ещё вопросы

Сообщество Overcoder
Наверх
Меню