在Laravel中,传递不同类型的会话闪存消息的最佳方法是什么?

159

我正在使用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-infoalert-warningalert-danger 等。

假设在我的控制器中,我知道我设置了什么类型的消息,那么将其传递并在视图中显示的最佳方式是什么?我应该为每种类型分别在会话中设置单独的消息(例如,Session::flash('message_danger', 'This is a nasty message! Something's wrong.');)吗?然后,在我的Blade模板中,我需要一个单独的 if 语句来处理每个消息。

欢迎任何建议。


https://itsolutionstuff.com/post/laravel-5-implement-flash-messages-with-exampleexample.html 对我很有帮助。 - Ryan
20个回答

273

一种解决方案是将两个变量闪存到会话中:

  1. 消息本身
  2. 您警报的“类别”

例如:

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类以外的其他情况下才覆盖它。 (这是一个快速示例,未经测试 :))

3
有趣,我不知道 Session::get() 有默认参数,这对我来说非常方便。 - Nick Coad
2
就像大多数闪存消息解决方案一样,它只处理一个消息。因此,经常需要能够发送一系列的消息,每个消息可能具有不同的严重程度,并将它们全部显示出来。 - Jason
2
这是我们在项目中使用的内容:https://gist.github.com/YavorK/7aa6e839dbe93e8854e4b033e31836a4 - Hop hop
1
这太适得其反了...为什么每个人都在点赞呢? - Goowik
33
如果不提供更有效的解决方案却说某事是低效的,反而会适得其反。 - SupaMonkey

59

在您看来:

<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');

51

我的方式是始终使用 Redirect::back() 或 Redirect::to():

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

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

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

我有一个帮助函数可以让它为我工作,通常这个函数在一个独立的服务中:

use Illuminate\Support\Facades\Session;

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() }}

4
这太棒了,但是这个$type = $type == 'error' : 'danger';是如何工作的呢? - Prabhakaran
1
你把辅助函数放在单独的 Helper 类中吗? - utdev
应该是 {!! displayAlert() !!} - Pouya

25
您可以创建多个不同类型的消息。 请按照以下步骤操作:
  1. 创建文件: "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);
  }
}
  • 在你的基础控制器 "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
    
  • 关于“app/Providers/AppServiceProvider.php”中的“boot()”方法:
  • 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>
    
    您只需在页面上希望显示消息的位置包含消息模板即可。
  • 在您的控制器中,您可以简单地执行以下操作来推送闪存消息:
  • 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.');
      }
    
      ...
    
    希望这能帮到你。

    不错。实际上需要找到 Laravel 中多条消息的解决方案。 - Čamo

    18

    仅需返回想要处理的“flag”,而无需使用任何其他用户函数。

    控制器:

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

    请注意,我使用了“Success”标志。

    视图:

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

    是的,它真的有效!


    你的回答中有很多错别字,但是你的方法非常有效。 - Bat Lanyard

    7

    另一种解决方案是创建一个辅助类。 如何在此处创建辅助类

    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
    

    5
    我不确定我是否会推荐这种方法,因为它把HTML从视图中移到了代码中。 - Nick Coad

    5

    我不是很喜欢提供的解决方案(例如:多个变量,helper类和循环遍历“可能存在的变量”)。以下是一种解决方案,它使用数组而不是两个单独的变量。如果您希望处理多个错误,则也可以轻松扩展它,但为了简单起见,我将其保留为一个flash消息:

    使用数组重定向并显示flash消息:

        return redirect('/admin/permissions')->with('flash_message', ['success','Updated Successfully','Permission "'. $permission->name .'" updated successfully!']);
    

    根据数组内容输出:

    @if(Session::has('flash_message'))
        <script type="text/javascript">
            jQuery(document).ready(function(){
                bootstrapNotify('{{session('flash_message')[0]}}','{{session('flash_message')[1]}}','{{session('flash_message')[2]}}');
            });
        </script>
    @endif
    

    由于您可能有自己的通知方法/插件,因此以下内容与之无关 - 但为了清晰起见 - bootstrapNotify只是为了从http://bootstrap-notify.remabledesigns.com/启动bootstrap-notify:

    function bootstrapNotify(type,title = 'Notification',message) {
        switch (type) {
            case 'success':
                icon = "la-check-circle";
                break;
            case 'danger':
                icon = "la-times-circle";
                break;
            case 'warning':
                icon = "la-exclamation-circle";
        }
    
        $.notify({message: message, title : title, icon : "icon la "+ icon}, {type: type,allow_dismiss: true,newest_on_top: false,mouse_over: true,showProgressbar: false,spacing: 10,timer: 4000,placement: {from: "top",align: "right"},offset: {x: 30,y: 30},delay: 1000,z_index: 10000,animate: {enter: "animated bounce",exit: "animated fadeOut"}});
    }
    

    5

    在控制器中:

    Redirect::to('/path')->with('message', 'your message'); 
    

    或者

    Session::flash('message', 'your message'); 
    

    在Blade中按照您所需的模式显示消息:
    @if(Session::has('message'))
        <div class="alert alert-className">
            {{session('message')}}
        </div>
    @endif
    

    你如何传递 className? - Boss COTIGA
    简单且适用于Laravel 10。 - Strabek

    5
    只需在会话中发送一个数组而不是字符串,例如:
    Session::flash('message', ['text'=>'this is a danger message','type'=>'danger']);
    
    @if(Session::has('message'))
        <div class="alert alert-{{session('message')['type']}}">
            {{session('message')['text']}}
        </div>
    @endif
    

    4
    你可以使用Laravel宏。
    您可以在app/helpers中创建macros.php,并将其包含在routes.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
    

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接