Deprecated: htmlspecialchars(): Passing null to parameter #1 ($string) of type string is deprecated in /webData/hua/www.ascwh.com/var/Typecho/Feed.php on line 367
ASCWH - laravel 2019-09-08T06:33:00+08:00 Typecho https://ascwh.com/feed/atom/tag/laravel/ <![CDATA[Laravel firstOrCreate、firstOrNew、updateOrCreate 方法]]> https://ascwh.com/230.html 2019-09-08T06:33:00+08:00 2019-09-08T06:33:00+08:00 ASCWH https://www.ascwh.com u=1118389801,3971147958&fm=26&gp=0.jpg

在日常开发的过程中,经常会遇到判断一条记录是否存在、存在更新、不存在新建记录这种场景,在 Laravel 中提供了方法支持,那么下面就看下具体的方法;

使用时请注意版本,下面介绍的函数 firstOrCreate 和 firstOrNew 跟版本有很大的关系

firstOrCreate
firstOrCreate 方法将会使用指定的字段 => 值对,来尝试寻找数据库中的记录。如果在数据库中找不到,5.3 以下版本会使用属性来添加一条记录,5.3 及以上版本则将使用第一个参数中的属性以及可选的第二个参数中的属性插入记录

用法:

User::firstOrCreate(['name' => 'Lisi']);
User::firstOrCreate(['name' => 'Lisi'], ['age' => 20]); // 5.3及以上版本支持
查看源码:

小于 5.3 版本,只有一个参数

public function firstOrCreate(array $attributes)
{
    if (! is_null($instance = $this->where($attributes)->first())) {
        return $instance;
    }
    $instance = $this->model->newInstance($attributes);
    $instance->save();
    return $instance;
}

5.5 版本

public function firstOrCreate(array $attributes, array $values = [])
{
    // 判断是否存在,如果存在,返回实例
    if (! is_null($instance = $this->where($attributes)->first())) {
        return $instance;
    }

    // 不存在创建,此代码简化就是 $this->newModelInstance($attributes + $values)->save();
    return tap($this->newModelInstance($attributes + $values), function ($instance) {
        $instance->save();
    });
}

firstOrNew
会尝试使用指定的属性在数据库中寻找符合的纪录。如果未被找到,将会返回一个新的模型实例。请注意 firstOrnew 返回的模型还尚未保存到数据库。你需要通过手动调用 save 方法来保存它

用法:

`User::firstOrNew(['name' => 'Lisi']); // 5.4 以下版本

User::firstOrNew(['name' => 'Lisi'], ['age' => 20]);     // 5.4及以上版本支持

查看源码:

小于 5.4 版本,只有一个参数

public function firstOrNew(array $attributes)
{
    if (! is_null($instance = $this->where($attributes)->first())) {
        return $instance;
    }
    return $this->model->newInstance($attributes);
}

5.5 版本

public function firstOrNew(array $attributes, array $values = [])
{
    if (! is_null($instance = $this->where($attributes)->first())) {
        return $instance;
    }
    return $this->newModelInstance($attributes + $values);
}

查看源码就更清楚 firstOrCreate 比 firstOrNew 多了 save 方法,两个方法都很实用,根据场景使用它。

updateOrCreate
更新数据,如果不存在则创建,这个函数就充分利用到了方法 firstOrNew,此函数版本之间变化不大

用法:

User::updateOrCreate(['name' => 'Lisi'], ['age' => 20]);
查看源码:

5.5 版本

public function updateOrCreate(array $attributes, array $values = [])
{
    return tap($this->firstOrNew($attributes), function ($instance) use ($values) {
        $instance->fill($values)->save();
    });
}

总结

firstOrCreate:判断之后直接入库
firstOrNew:判断之后还要做其他业务流程,之后再入库
updateOrCreate:更新数据,如果不存在则创建

]]>
<![CDATA[Laravel 6 LTS 正式发布:遵循语义化版本标准、前端脚手架独立为 Laravel UI]]> https://ascwh.com/228.html 2019-09-05T23:06:00+08:00 2019-09-05T23:06:00+08:00 ASCWH https://www.ascwh.com Laravel 6 已于近日正式发布,此版本也是最新的 LTS 版本。据介绍,从 Laravel 6 开始,Laravel 框架将会使用语义化版本。新特性还包括对 Laravel Vapor 的支持,改进授权响应,引入任务中间件和惰性集合,以及对子查询的改进等。除此之外,还有许多其他的细节优化。

072828_teA8_2720166.jpg

Laravel 6.0 是新的 LTS 版本
根据官方提供的发布计划,Laravel 6 的 bug 修复会持续至 2021 年 9 月 3 日,安全修复则持续至 2022 年 9 月 3 日。上一个 LTS 版本是两年前发布的 Laravel 5.5,其安全修复会持续至 2020 年 8 月 30 日。

语义化版本
Laravel 6 及未来更高版本均遵循语义化版本标准,也就是说 Laravel 的软件包会保持和 Laravel 一致的版本标准,但不会影响发布周期。

改进授权响应
在旧版本中,为终端用户提供有关授权的自定义错误消息十分困难。Laravel 6 引入了 Gate::inspect 方法来提供授权策略响应:

$response = Gate::inspect('view', $flight);

if ($response->allowed()) {
    // User is authorized to view the flight...
}

if ($response->denied()) {
    echo $response->message();
}

任务中间件
任务中间件(Job Middleware)支持在中间件中运行任务:

// Add a middleware method to a job class
public function middleware()
{
     return [new SomeMiddleware];
}

// Specify middleware when dispatching a job
SomeJob::dispatch()->through([new SomeMiddleware]);
此中间件可避免在任务的 handle() 方法中编写自定义逻辑,详情请查看 Job Middleware is Coming to Laravel 6。

惰性集合
惰性集合(Lazy Collections)用于处理大量的数据集合,包括 Eloquent 模型集合。Laravel 6 新增 Illuminate\Support\LazyCollection 类来处理大型数据集,它利用 PHP 的生成器降低了所需的内存。查看 Lazy Collections 文档以了解更多详细信息。

子查询功能增强
关于 Laravel 6 中的 Eloquent 子查询功能增强请点此查看详细信息。

Laravel UI
Laravel 5.x 版本提供的前端脚手架现已被提取到一个单独的 laravel/ui Composer 包中,开发者可实现 UI 脚手架与主框架的分离,并进行独立的版本迭代。

如果需要使用传统的 Bootstrap/Vue 脚手架,请运行以下命令:

composer require laravel/ui
php artisan ui vue --auth
]]>
<![CDATA[laravel 二维码生成(simplesoftwareio/simple-qrcode)]]> https://ascwh.com/223.html 2019-09-05T01:31:00+08:00 2019-09-05T01:31:00+08:00 ASCWH https://www.ascwh.com laravel 二维码生成(simplesoftwareio/simple-qrcode

composer require "simplesoftwareio/simple-qrcode"
使用:

use SimpleSoftwareIO\QrCode\Facades\QrCode;//引入

QrCode::format('png')->size(195)->margin(1)->merge('图标地址', .13)->generate('二维码内容','保存图片路径不选择直接输出');

点击查看官方文档

[gitwidget type='github' url='SimpleSoftwareIO/simple-qrcode']

]]>
<![CDATA[ Laravel 视图的{{ }},与 vue 的{{ }},相冲突…………]]> https://ascwh.com/194.html 2019-03-28T16:48:54+08:00 2019-03-28T16:48:54+08:00 ASCWH https://www.ascwh.com 今天在laravel的blade里 ,引入 第三方的js文件时,{{ }} 会与 vue.js"Mustache" 语法 {{ }},相冲突,会报错,不存在,

解决

vue中使用` @{{ }}`代替


]]>
<![CDATA[Laravel 之 Cookie 的使用]]> https://ascwh.com/183.html 2019-03-25T19:26:51+08:00 2019-03-25T19:26:51+08:00 ASCWH https://www.ascwh.com 手册内容

Cookies
从请求中获取 Cookie
Laravel 框架创建的每个 cookie 都会被加密并使用验证码进行签名,这意味着如果客户端更改了它们,便视为无效。若要从请求中获取 cookie 值,你可以在 Illuminate\Http\Request 实例上使用 cookie 方法:

$value = $request->cookie('name');

将 Cookies 附加到响应
你可以使用 cookie 方法将 cookie 附加到传出的 Illuminate\Http\Response 实例。你需要传递 Cookie 名称、值、以及有效期(分钟)到这个方法:

return response('Hello World')->cookie(
    'name', 'value', $minutes
);

cookie 方法还接受一些不太频繁使用的参数。通常,这些参数与 PHP 原生 setcookie 方法的参数具有相同的目的和意义:

return response('Hello World')->cookie(
    'name', 'value', $minutes, $path, $domain, $secure, $httpOnly
);

生成 Cookie 实例
如果你想要在一段时间以后生成一个可以给定 Symfony\Component\HttpFoundation\Cookie 的响应实例,你可以使用全局辅助函数 cookie。除非此 cookie 被附加到响应实例,否则不会发送回客户端:

$cookie = cookie('name', 'value', $minutes);

return response('Hello World')->cookie($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 的方式,具体喜欢哪一种按个人喜好来吧~

通过调用 Illuminate\Http\Request 实例对象的 cookie 方法获取

$value = $request->cookie('key');
$value = request()->cookie('key');

通过 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。多去看看框架源码,惊喜彩蛋 ? 总是让你那么开心 ?!

]]>
<![CDATA[Laravel This cache store does not support tagging.]]> https://ascwh.com/179.html 2019-02-19T15:24:04+08:00 2019-02-19T15:24:04+08:00 ASCWH https://www.ascwh.com 包里 有个地方用了 laravel 的cache,默认的cache是file

把.env 里的 CACHE_DRIVER 改成

CACHE_DRIVER=array

在执行下 OK了

]]>
<![CDATA[7 个非常有用却很少人知道的 Carbon 方法]]> https://ascwh.com/172.html 2018-12-28T02:18:21+08:00 2018-12-28T02:18:21+08:00 ASCWH https://www.ascwh.com 我们在很多时候使用 Carbon 来处理日期和时间,对吗?但是又有多少人完整的阅读过文档了解它有那些方法呢?除了众所周知的 now() 和 format() 方法,Carbon 还有很多其他有用的方法。下面我们一起来看看吧。

1. isX: True/False

有很多方法来判断 Carbon 对象是否是今天、周末、闰年等等,下面这些是官方文档列出来的:

<?php
$dt->isWeekday();
$dt->isWeekend();
$dt->isYesterday();
$dt->isToday();
$dt->isTomorrow();
$dt->isFuture();
$dt->isPast();
$dt->isLeapYear();
$dt->isSameDay(Carbon::now());

2. isBirthday

除了上面的列表,Carbon 还有一个方法来判断日期是否是某个人的生日。除了单开校验月和日外,你还可以这么做:

        $born                     = Carbon::createFromDate(1987, 4, 23);
        $noCake                 = Carbon::createFromDate(2014, 9, 26);
        $yesCake                = Carbon::createFromDate(2014, 4, 23);
        var_dump($born->isBirthday($noCake));              // bool(false)
        var_dump($born->isBirthday($yesCake));

3. StartOfX 和 EndOfX 列表

下面是 startOfX 系列和 endOfX 系列:

$dt = Carbon::create(2012, 1, 31, 12, 0, 0);
echo $dt->startOfDay();     // 2012-01-31 00:00:00
echo $dt->endOfDay();       // 2012-01-31 23:59:59
echo $dt->startOfMonth();   // 2012-01-01 00:00:00
echo $dt->endOfMonth();     // 2012-01-31 23:59:59
echo $dt->startOfYear();    // 2012-01-01 00:00:00
echo $dt->endOfYear();      // 2012-12-31 23:59:59
echo $dt->startOfDecade();  // 2010-01-01 00:00:00
echo $dt->endOfDecade();    // 2019-12-31 23:59:59
echo $dt->startOfCentury(); // 2000-01-01 00:00:00
echo $dt->endOfCentury();   // 2099-12-31 23:59:59
echo $dt->startOfWeek();    // 2012-01-30 00:00:00
echo $dt->endOfWeek();      // 2012-02-05 23:59:59

4. Today, Tomorrow, Yesterday

三个简单却非常有用的方法,不需要调用 now(),然后替换掉时分秒,然后增加或者减去天数:

$dt = Carbon::create(2012, 1, 31, 12, 0, 0);
echo $dt->startOfDay();     // 2012-01-31 00:00:00
echo $dt->endOfDay();       // 2012-01-31 23:59:59
echo $dt->startOfMonth();   // 2012-01-01 00:00:00
echo $dt->endOfMonth();     // 2012-01-31 23:59:59
echo $dt->startOfYear();    // 2012-01-01 00:00:00
echo $dt->endOfYear();      // 2012-12-31 23:59:59
echo $dt->startOfDecade();  // 2010-01-01 00:00:00
echo $dt->endOfDecade();    // 2019-12-31 23:59:59
echo $dt->startOfCentury(); // 2000-01-01 00:00:00
echo $dt->endOfCentury();   // 2099-12-31 23:59:59
echo $dt->startOfWeek();    // 2012-01-30 00:00:00
echo $dt->endOfWeek();      // 2012-02-05 23:59:59

5. DiffForHumans + 本地化

你可能用过这个叫做 diffForHumans() 的方法 – 它会以一个便于人们阅读的方法返回两个日期之间的不同:

echo Carbon::now()->subDays(5)->diffForHumans();  // 5 days ago
但是你知道它也可以本地化吗?只需要改变地点即可,如汉语:

Carbon::setLocale('zh');
echo Carbon::now()->addYear()->diffForHumans();  // 一年前

6. 改变 now() 为任意你想要的时间

$knownDate = Carbon::create(2001, 5, 21, 12);  // 创建测试日期
Carbon::setTestNow($knownDate);                     // set the mock 
echo Carbon::now();                                 // 2001-05-21 12:00:00

7. 星期常量

可以通过下面的常量来代替一周中的第几天:

var_dump(Carbon::SUNDAY);                          // int(0)
var_dump(Carbon::MONDAY);                          // int(1)
var_dump(Carbon::TUESDAY);                         // int(2)
var_dump(Carbon::WEDNESDAY);                       // int(3)
var_dump(Carbon::THURSDAY);                        // int(4)
var_dump(Carbon::FRIDAY);                          // int(5)
var_dump(Carbon::SATURDAY);                        // int(6)

上面提到的这些有用的方法你都了解吗?可以在留言种列出你觉得有用的方法。

]]>