Project-Flyer-9-Elegant-Flash-Messaging

跟随 Jeffrey Way 的视频学习,脑子不好,一些细节容易忘记,这里记录下来。相关视频在 laracasts.com
课程名称:Build “ProjectFlyer” With Me(09)

打开 Flyer 控制器 FlyerController.php

在 store 方法里我们打算添加一个提示信息,添加一个方法:

flash('Flyer successfully created!');

意味着,flash 方法可以返回一个模态窗,显示’Flyer successfully created!’,当然,现在这个方法并不存在,我们现在来实现它。

打开根目录的 composer.json,在 autoload 里添加:

"files":[
    "app/helpers.php"
]

这个 helpers.php 也是不存在的,我们创建它到 app 目录下,内容如下:

function flash($message)
{
}

搜索 sweet alert ,建议去 github 去搜索,找不到直接点这里:http://t4t5.github.io/sweetalert ,然后下载,解压,把 js 文件和 css 文件分别拷贝到 resource/assets/js/libs 和 resource/assets/css/libs 下。

打开根目录下的gulpfile.js,修改为:

elixir(function(mix) {
    mix.sass('app.scss')
        .scripts([
            'libs/sweetalert-dev.js'
        ], './public/js/libs.js')
        .styles([
            'libs/sweetalert.css'
        ], './public/css/libs.css')
});

然后在根目录下运行命令gulp,成功后会生成文件:public/css/libs.css 和 public/css/libs.js

打开模板文件 master.blade.php,在

<link rel="stylesheet" type="text/css" href="/css/app.css">

的上面加入一行:

<link rel="stylesheet" type="text/css" href="/css/libs.css">

在底部加入一行:

<script src="/js/libs.js"></script>

此时准备工作差不多了,试一下,在上面一行的下面加入下面的代码:

<script>
    swal({
        title: "Error!",   
        text: "hello world!",
        type: "info",   
        // confirmButtonText: "Cool" 
        timer: 2000,
        showConfirmButton: false
    });
</script>

成功显示 sweet alert 提示吧?添加文件 app/Http/Flash.php:

<?php
namespace App\Http;

class Flash
{
    public function message($message)
    {
        session()->flash('flash_message', $message);
    }
}

回到 FlyerController.php 的 store 方法继续编辑,我们刚添加了 Flash.php,现在可以在控制器里调用了,添加一个参数:

public function store(FlyerRequest $request, Flash $flash)

删除这一行:

$flash->message();

打开 helpers.php,修改 flash 方法为:

function flash($message)
{
    $flash = app('App\Http\Flash');
    return $flash->message($message);
}

我们现在新建一个模板 …/layouts/flash.blade.php,把 master.blade.php 里面的下面的脚本:

<script>
    swal({
        title: "Error!",   
        text: "hello world!",
        type: "info",   
        // confirmButtonText: "Cool" 
        timer: 2000,
        showConfirmButton: false
    });
</script>

剪切到刚新建的模板 flash.blade.php 里,然后在 master.blade.php 里添加 flash 模板的引用,让 master 模板整洁点。添加引用,必须添加到刚才剪切的位置才行:

@include('layouts.flash')

然后在 flash 里添加一个条件判断,把刚才剪切过去的代码包起来:

@if(session()->has('flash_message'))
    /* 这里是刚才剪切的代码 */
@endif

此时,我们试试,点击 create 页面的按钮,会报错,说调用了一个未定义的方法 flash(),这是因为需要重新加载 autoload 配置,去虚拟机的根目录里执行:

composer dump-autoload

刷新,这下就可以了。

下面,我们让错误信息来自会话信息,修改 flash.blade.php 的 text: 对应的内容为:

text: "{{ session('flash_message') }}",

刷新下 create 页面看看,应该会弹出 hello world 的模态框提示。

修改 app/Http/Flash.php:

public function message($title, $message)
{
    session()->flash('flash_message', [
        'title'     => $title,
        'message'   => $message
    ]);
}

修改 flash.blade.php 模板的 title 和 text 两行为:

title: "{{ session('flash_message.title') }}",   
text: "{{ session('flash_message.message') }}",

修改 Flyer 控制器的 create 方法里的 flash 方法为:

public function create()
{
    flash('Hello World', 'This is the message.');
    return view('flyers.create');
}

修改 helpers.php 为:

function flash($title, $message)
{
    $flash = app('App\Http\Flash');
    return $flash->message($title, $message);
}

此时,我们刷新 create 页面会发现,Flyer 控制器里写的方法参数内容决定了模态框的文字内容。好,至此,可以把 Flyer 控制器里的 create 改回原来的样子了,注释掉 create 方法的这一行:

flash('Hello World', 'This is the message.');

修改 Flyer 控制器的 store 方法为:

public function store(FlyerRequest $request)
{
    Flyer::create($request->all());
    flash('Success!', 'Your flyer has been create.');
    return redirect()->back();
}

测试 create 页面,输入内容提交下,如果返回成功信息的模态框证明我们之前的代码没问题了,继续下一步。

修改 flash.blade.php 模板,我们已经修改了它的 title 和 text,下面我们修改它的 info 为:

type: "{{ session('flash_message.notice') }}",

显然,目前我们的 flash_message 没有 notice 这个参数,我们添加这个参数。

去哪里修改呢,Flash.php,打开 app\Http\Flash.php 可以看到 flash_message 如何塞进 session,修改 flash_message 的参数,message 方法的内容如下:

session()->flash('flash_message', [
    'title'     => $title,
    'message'   => $message,
    'level'     => 'info'
]);

然后我们修改 Flyer 控制器里的 store 方法,由于我们的提交结果有多种可能所以应该有条件判断,所以最好写上几个情况的方法方便调用,打开 app\helpers.php,修改为:

function flash($title = null, $message = null)
{
    $flash = app('App\Http\Flash');
    if (func_num_args() == 0) {
        return $flash;
    }
    return $flash->message($title, $message);
}

设想控制器里的 store 方法应该是这样调用比较好:

flash()->success('Success!', 'Your flyer has been create.')

我们修改下 app\Http\Flash.php,新建一个方法 success:

public function success($title, $message)
{
    session()->flash('flash_message', [
        'title'     => $title,
        'message'   => $message,
        'level'     => 'success'
    ]); 
}

我们注意到,这里我们的第三个参数是 level,所以需要修改下 flash.blade.php,还记得模板里的第三个参数是 flash_message.notice,这里要修改下,修改为:

flash_message.level

记得小步前进,我们现在试试刚才的操作,是否已经奏效,修改 Flyer 控制器里的 create 方法为:

public function create()
{
    flash()->success('Hello World!', 'This is the message.');
    return view('flyers.create');
}

好,刷新下 create 页面看看,如果以上步骤都正确,应该可以看到有成功标示的模态框。下面接着添加错误时的方法。打开 app\Http\Flash.php,添加 error 方法:

public function error($title, $message)
{
    session()->flash('flash_message', [
        'title'     => $title,
        'message'   => $message,
        'level'     => 'error'
    ]); 
}

好,再试试错误方法是否能正确调用,修改 Flyer 控制器的 create 方法里的:

flash()->success('Hello World!', 'This is the message.');

为:

flash()->error('Hello World!', 'This is the message.');

刷新 create 页面,会显示包含错误的表示的模态框。

下面我们优化下 app\Http\Flash.php:

class Flash
{
    public function create($title, $message, $level)
    {
        session()->flash('flash_message', [
            'title'     => $title,
            'message'   => $message,
            'level'     => $level
        ]);
    }
    public function message($title, $message)
    {
        return $this->create($title, $message, 'info');
    }

    public function success($title, $message)
    {
        return $this->create($title, $message, 'success');
    }

    public function error($title, $message)
    {
        return $this->create($title, $message, 'error');
    }
}

好,测试下,分别修改 FlyerController 控制器里的 create 方法,分别调用 error,message, success 看是否成功,比如我们试试 success 是否能成功调用:

flash()->success('Hello World!', 'This is the message.');

以上都成功了,我们继续,打开 flash.blade.php,添加下面这段:

@if(session()->has('flash_message_overlay'))
<script>
swal({
title: "{{ session('flash_message_overlay.title') }}",
text: "{{ session('flash_message_overlay.message') }}",
type: "{{ session('flash_message_overlay.level') }}",
confirmButtonText: "Okey"
// timer: 2000,
// showConfirmButton: false
});
</script>
@endif

把 FlyerController 控制器里的 create 方法里的 falsh 调用改为:

flash()->overlay('Welcome Aboard', 'Thank you for signing up');

继续修改 app\Http\Flash.php,添加下面这段:

public function overlay($title, $message, $level = 'success')
{
    return $this->create($title, $message, $level, 'flash_message_overlay');
}

修改它的 create 方法为:

public function create($title, $message, $level, $key = 'flash_message')
{
    session()->flash($key, [
        'title'     => $title,
        'message'   => $message,
        'level'     => $level
    ]);
}

刷新下 create 页面看看,应该会显示有 Okey 按钮的成功提示。OK,把 message 方法名称改为 info
打开 app\helpers.php,修改 $flash 调用的 message 为 info(我们刚刚把 message 重命名为了 info),这个调用也可以是 success 或 error 方法。
删除 FlyerController 控制器的 create 方法里的 $flash 调用那行。把 store 方法修改为:

public function store(FlyerRequest $request)
{
    Flyer::create($request->all());
    flash()->success('Success!', 'Your flyer has been create.');
    return redirect()->back();
}

最后,总结下整个调用过程,首先,理解要session()->flash('foot','bar'),官方文档这么说:

Sometimes you may wish to store items in the session only for the next request. You may do so using the flash method. Method stored in the session using this method will only be available during the subsequent HTTP request, and then will be deleted. Flash data is primarily useful for short-lived status messages:

$request->session()->flash('status', 'Task was successful!');

App\helpers.php 里有个方法 flash(),当参数是0个的时候:
即就是以flash()->success('foo','bar');的方式调用时,直接返回 app\Http\Flash,返回的对象可以调用 app\Http\Flash.php 里的方法,比如 success 方法,此时 success 调用 create 方法,create 方法通过 session()->flash('foo','bar')来取值和存值。脚本又通过

{{session('foobar')}}

的方式获取必要的参数,从而实现了前台模态框数据的各种变化。

0%