laravel框架笔记

113 阅读1分钟
  1. 本地作用域
    1. 很多情况下,我们在数据查找是有一部分条件会被重复且大量使用
    2. 而这个条件,可能只是在这个模型对应的数据包使用,别的表并不使用
    3. 那么这种情况,可以使用本地作用域的方式,将常用的SQL封装起来;
    4. 比如:用户模块中,我们大量查询性别为男,且其他条件的SQL

$users = User::where('gender', '女')

        ->where('price','>','90')

        ->get();

PS: 我们可以将性别为男这个片段,封装成一个单独的方法,然后统一在这个模型下调用:

//App\Http\Models;

//本地作用域,搜索自动添加为"男"的条件

//语法:scope开头,后面名称尽可能包含语义

public function scopeGenderMale($query){

      $query->where('gender', '女');

}

//当然,如果赶紧单词太长,直接gm()也行

$users = User::genderMale()

            ->where('price', '>', 90)

            ->get();

e. 上面的方法比较死板,适合简单粗暴,如果想要灵活多变,支持传递参数

//参数可以是1个或多个

$users = User::gender('女', 0)

            ->where('price','>',90)

            ->get();

//参数2和3,接受控制器传递过来的1,2

public function scopeGender(query, query, value, $value2 = 1){

      query>where(gender, query->where('gender', value)->where('status', $value2);

}

  1. 全局作用域

a. 全局作用域,顾名思义就是在任意地方都可以有效的封装条件:

b. 比如有个需求,不管在哪里操作,总是显示status为1的用户

c. 首先在app目录下创建一个用于全局作用域的目录:Scopes:

d. 创建一个用于设置status为1的全局作用域的类,它需要实现scope接口

namespace App\Scopes;

//这里引用代码自动生成

use Illuminate\Database\Eloquent\Builder;

use Illuminate\Database\Eloquent\Model;

use Illuminate\Database\Eloquent\Scope;

class StatusScope implements Scope{

    public function apply(Builder builder, Model builder, Model model){

        $builder->where('status', 1);

    }

}

e. 此时,还不能实现全局,因为需要在模型设置开关,让其富有灵活性:

//启用全局作用域,如果发现路径报错,那就在模型代码开头添加:use App\Scopes\StatusScope;

protected static function booted(){

        parent::booted();

        static::addGlobalScope(new StatusScope());

 }

Ps: 而在控制器端,并不需要做任何设置,即可自动添加status=1的条件

f. 当然,如果这个全局只是针对某个模块,并不需要创建一个全局类,直接闭包即可:

//这里如果不在模型中添加:use Illuminate\Database\Eloquent\Builder;这段也有可能会报错,报错点在下面的第一行

static::addGlobalScope('status', function(Builder $builder){

      $builder->where('status',0);

});

Ps: 注意Builder引入的文件和全局类引入的文件一致,如果引入别的同名类会报错;

g. 如果某个查询,并不需要这个全局条件,可以单独移出掉:

//取消名称为status的全局

$users = User::withoutGlobalScope('status')->get();

//取消全局类的条件,这个老壁灯如果使用不了的话那就是没用引入类use App\Scopes\StatusScope;

$users = User::withoutGlobalScope(StatusScope::class)->get();

PS:还有withoutGlobalScopes([])方法,传递参数取消多个全局