Laravel 之 Cookie 使用

Laravel 的 Cookie 用起来蛮优雅的,但还是踩了不少坑,主要是不熟悉框架所致 ?。其实本质还是在使用全局变量 $_COOKIE ,由于原生的使用方式不够友好,因此既然选择了框架,就充分利用其提供的友好封装层。

先来一个最简单的示例:

public function setCookie()
{
    return response('Hello Cookie')->cookie('test', '123', 60);
}

public function getCookie()
{
    echo request()->cookie('test');
}

首先我们要明确 Cookie 是存储在浏览器端的(也就是用户端),所以它就必须依附于具体某个请求和响应。而 Session 是存储在服务端的,它不需要依附在某个请求或者响应头中。

所以我们在使用 Cookie 的时候,就必须配合 Request 和 Response。

获取 Cookie

Laravel 给我们提供了灵活的获取 Cookie 的方式,具体喜欢哪一种按个人喜好来吧~

  1. 通过调用 Illuminate\Http\Request 实例对象的 cookie 方法获取
    $value = $request->cookie('key');
    $value = request()->cookie('key');
  2. 通过 Cookie Facade 方式
    use Illuminate\Support\Facades\Cookie;
    // ...
    $value = Cookie::get('key');

其实第二种方式获取 Cookie 值也是通过第一种方式调用的,我们可以在 Illuminate\Support\Facades\Cookie 类中的 get() 方法中看到:

public static function get($key = null, $default = null)
{
    return static::$app['request']->cookie($key, $default);
}

设置 Cookie

我们在需要设置 Cookie 的请求方法中,通过 Response 的 cookie() 方法进行设置:

$value = response('Hello Cookie')->cookie('key', 'value', 60);
$value = response('Hello Cookie')->withCookie('key', 'value', 60);

上面两种方式均可,第一种方式其实就是调用了第二种方式(有时候选择多了反而增加记忆成本 ?)。

还有一种使用 helper 函数。。。

function cookie($name = null, $value = null, $minutes = 0, $path = null, $domain = null, $secure = false, $httpOnly = true, $raw = false, $sameSite = null) {}

推荐还是使用第一种方式,因为可以正确的理解 Cookie 的设置方式。

删除 Cookie

开篇也说过 Cookie 是保存在客户端的,所以删除的操作其实服务端是没权限去做的,那么这里所谓删除其实就是使 Cookie 失效。Laravel 提供了友好的 API 供我们调用,感谢 Laravel ?~

use Illuminate\Support\Facades\Cookie;
// ...
Cookie::forget('key');

细心你会发现这个类中没有这个静态方法,和 Cookie::forever('key', 'value') 一样,这些好用的 API 是 Illuminate\Cookie\CookieJar 这个类提供的(这个类是通过 ServiceProvider 在 Illuminate\Foundation\Application 类中注册,然后在 /bootstrap/app.php 实例化,详细的读源码~)

public function forget($name, $path = null, $domain = null)
{
    return $this->make($name, null, -2628000, $path, $domain);
}

我们可以看到其实就是将 Cookie 的有效期(Expires/Max-Age)设置成过去时即可。

更细心的你会发现光是这一句并没有什么卵用啊 ?,别忘了我们要把更改后的 Cookie 加入到响应头中,这样客户端才会修改 Cookie 值(说到这里其实本质还是在设置 Cookie 而已 ?)。

use Illuminate\Support\Facades\Cookie;
// ...
public function demo()
{
    $cookie = Cookie::forget('key');

    return response('xxx')->cookie($cookie);
}

明文 Cookie

很多时候 Cookie 是需要被前端童鞋使用的,但是默认情况下 Laravel 在响应头中添加的 Cookie 信息是加密过的,类似 eyJpdiI6IjRwOFMyTkl2aGs2TGt4OUcxYXRNXC9BPT0iLCJ2YWx1ZSI6IkpHN0Fqb0ZSaDFxVHE0OHdFRXdXMHc9PSIsIm1hYyI6Ijc2MTljZDVmZDI1Mjg5MTk3NTBlZGM0MzUxMjUyZjQ5MzcxOGE1MWU4Y2ViZTBlYTY5YWRjZjNkZjUwNzNkMDEifQ%3D%3D ,这种时候就得将那些需要 明文 传输的 Cookie 加入到 白名单 中去:

/app/Http/Middleware/EncryptCookies.php 中的 $except 数组中将其加入,

protected $except = [
    'key'
];

小结

其实 Laravel 的 Cookie 还有不少好用的方法,比如 Cookie::has('key') 判断在请求头中是否存在某个 Cookie。多去看看框架源码,惊喜彩蛋 ? 总是让你那么开心 ?!

本作品采用《CC 协议》,转载必须注明作者和本文链接
公众号:编程之谜
本帖由系统于 5年前 自动加精
imxfly
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 9
imxfly

@xuanjiang1985

return response()->view('home')->cookie($cookie);
5年前 评论

这种方式怎么把cookie带去客户端

return redirect('/home/foo');

return view('home');
5年前 评论
imxfly

@xuanjiang1985

return response()->view('home')->cookie($cookie);
5年前 评论
ruke

view()函数返回的也是个response,感觉操作应该是一样的

5年前 评论

用辅助函数response()调用cookie 创建报错
Method Illuminate\Routing\ResponseFactory::cookie does not exist.
是我的辅助函数有毒吗。。

5年前 评论
imxfly

@ericdemon 这是内置方法,要么就是你重写了这个辅助函数,要么你调用有问题= =

5年前 评论

@风子切 现在可以了,好像 如果response()第一个参数content不加的话就会报错。。 但是我response()->json($data)->cookie('key' , 'value' , 60)就好了 :joy:

5年前 评论

怎么判断cookie 是否禁用

4年前 评论

要是前台想夺取cookie值, 直接cookie('键名')这样吗?

4年前 评论

有个问题,我的api的response需要设置cookie,但这个cookie不止一个,该如何写呢?

3年前 评论
0Robert0 3年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!