美文网首页
Lumen 数据库操作orm

Lumen 数据库操作orm

作者: cxscode | 来源:发表于2018-09-16 10:35 被阅读0次

    我大概遍历了一遍Illuminate\Database\Query\Builder类的大部分方法

    比较常用方法

    select 指定字段
    from 指定表
    join 关联表
    where 查询条件
    groupBy 分组
    having 查询条件
    orderBy 排序
    find 查询条件加查询
    value 值查询
    get 列查询
    paginate 分页查询
    pluck 字段查询,处理成数组
    count 个数查询
    insert 插入
    update 更新
    delete 删除
    chunk 回调方法处理查询结果
    each 回调方法处理查询结果
    with 对象关联查询
    whereHas 当绑定关系有数据的时候

    select
    设置查询字段

    Notice::select('title')->get();
    Notice::select(['title', 'content'])->get();
    

    selectRaw
    查询自定义内容

    Notice::selectRaw("count('id') as notice_count")->get();
    

    addSelect
    在其现有select子句中添加一列查询字段

    $query = DB::table('users')->select('name');
    $users = $query->addSelect('age')->get();
    

    distinct
    该distinct方法允许您强制查询返回不同的结果:

    $users = DB::table('users')->distinct()->get();
    

    from
    设置表名属性,table()方法也是通过这个方法设置

    DB::table('users')
                ->whereExists(function ($query) {
                    $query->select(DB::raw(1))
                          ->from('orders')
                          ->whereRaw('orders.user_id = users.id');
                })
                ->get();
    

    上面的查询其实就是with()方法的原理了,转成sql如下

    select * from users
    where exists (
        select 1 from orders where orders.user_id = users.id
    )
    

    join
    关联查询,join()方法最后还有两个参数,type和where, type是链表方式(inner,left,right,cross),where是关联条件(on,where)
    后面的一些join方法(joinWhere,leftJoin,leftJoinWhere,rightJoin,rightJoinWhere,crossJoin)的实现是通过传type和where调用join()来实现的

    $users = DB::table('users')
                ->join('contacts', 'users.id', '=', 'contacts.user_id')
                ->join('orders', 'users.id', '=', 'orders.user_id')
                ->select('users.*', 'contacts.phone', 'orders.price')
                ->get();
    

    cross join(笛卡尔积): mysql的交叉连接,数据分析和统计有时会用得上
    cross join相关:https://www.yiibai.com/mysql/cross-join.html

    joinWhere
    join的时候,$where参数的on值换成了where值, 外键关联换成条件

    $users = DB::table('users')
                ->joinWhere('contacts', 'contacts.type', '=', '1')
                ->join('orders', 'users.id', '=', 'orders.user_id')
                ->select('users.*', 'contacts.phone', 'orders.price')
                ->get();
    

    leftJoin
    join的时候,$type参数的inner值换成了left值, 左匹配

    $users = DB::table('users')
                ->leftJoin('posts', 'users.id', '=', 'posts.user_id')
                ->get();
    

    leftJoinWhere
    join的时候,
    type参数的inner值换成了left值, 左匹配where参数的on值换成了where值, 外键关联换成条件

    $users = DB::table('users')
                ->leftJoinWhere('posts', 'posts.type', '=', '1')
                ->get();
    

    rightJoin
    同理

    rightJoinWhere
    同理

    crossJoin
    同理

    where
    为了使用方便,where方法提供了多种传值方式, 最后有一个$boolean参数 默认and, 可传or

    $user = DB::table('users')->where('name', 'John')->first();
    $user = DB::table('users')->where('name', '=', 'John')->first();
    $user = DB::table('users')->where([['name', '=', 'John'], ['telephone', '=', '18812341234']])->first();
    echo $user->name;
    

    orWhere

    $users = DB::table('users')
                        ->where('votes', '>', 100)
                        ->orWhere('name', 'John')
                        ->get();
    

    groupBy
    可传数组或多个参数

    Notice::groupBy('title', 'id')->get();
    Notice::groupBy(['title', 'id'])->get();
    

    having
    存在

    Notice::having('title', '=', '2')->get();
    

    orHaving
    或存在

    Notice::having('title', '=', '2')->orHaving('title', '=', '1')->get();
    

    havingRaw
    存在,原生sql

    $orders = DB::table('orders')
        ->select('department', DB::raw('SUM(price) as total_sales'))
        ->groupBy('department')
        ->havingRaw('SUM(price) > ?', [2500])
        ->get();
    

    orHavingRaw
    或存在,原生sql

    $orders = DB::table('orders')
        ->select('department', DB::raw('SUM(price) as total_sales'))
        ->groupBy('department')
        ->orHavingRaw('SUM(price) > ?', [2500])
        ->get();
    

    orderBy
    orderBy只能多个拼接

    Notice::orderBy('title')->get();
    Notice::orderBy('title')->orderBy('content')->get();
    

    orderByDesc
    desc排序

    Notice::orderByDesc('title')->get();
    

    latest
    默认按create_at从大到小

    public function latest($column = 'created_at')
    {
        return $this->orderBy($column, 'desc');
    }
    

    oldest
    默认按create_at从小到大

    public function oldest($column = 'created_at')
    {
        return $this->orderBy($column, 'asc');
    }
    

    inRandomOrder
    随机排序法 可传参,传同样参数会得到同样的排列

    Notice::inRandomOrder()->get();
    Notice::inRandomOrder(1)->get();
    

    orderByRaw
    排序,原生sql

    Notice::orderByRaw('title, content')->get();
    

    find
    注:从源码上看find和findMary是通的,find第一个参数传数组时,会调用findMany方法

    Notice::find(1);
    Notice::find(1, ['title']);
    Notice::find([1,2], ['title']);
    

    value
    从查询的第一个结果中获取单个列的值

    Notice::where('title', 1)->value('title');
    

    get
    查询列,可指定查询项get(['title', 'content']),

    Notice::where('title', 1)->get();
    

    注:该特别注意的是get查询不到结果时返回的是一个空数组,不能直接用!判断

    paginate
    返回指定查询条数的数据,总条数,当前分页之类的

    DB::table('notice')->paginate();
    

    simplePaginate
    同上 返回参数有所删减,数据量较大的查询性能较高

    DB::table('notice')->simplePaginate ();
    

    cursor
    数据量大时,用cursor做遍历会节省很多内存

    DB::table('notice')->get();
    foreach (DB::table('notice')->cursor() as $notice){
            var_dump($notice);
    }
    

    chunkById
    分次查询,第一个参数是每次查的条数,默认根据id查,如果需定制可在第三个参数传

    $noticeArr = [];
    $notice = DB::table('notice')->chunkById(10, function($notices) use (&$noticeArr){
        $noticeArr[] = json_decode(json_encode($notices, 256), true);
    }, 'notice_id');
    var_dump($notice);
    var_dump($noticeArr);
    exit();
    

    该方法为分页查询,如果涉及更新,需慎用该方法

    pluck
    查询某一个字段,返回该只有该字段的数组集合,第二个参数为指定某个参数为键,返回键值对集合

    DB::table('roles')->pluck('title');
    DB::table('roles')->pluck('title', 'name');
    

    implode
    根据查询字段和符号分割

    DB::table('notice')->implode('title', ',');//titlea,title2,titlec
    

    exists
    判断查询记录是否存在

    DB::table('notice')->where('status', 1)->exists();//true
    DB::table('notice')->where('status', 'a')->exists();//false
    

    doesntExist
    同exists,返回结果和exists相反

    DB::table('notice')->where('status', 1)->exists();//false
    DB::table('notice')->where('status', 'a')->exists();//true
    

    count
    返回个数

    DB::table('notice')->where('status', 1)->count();
    

    min
    最小

    DB::table('notice')->min('notice_id');
    

    max
    最大

    DB::table('notice')->max('notice_id');
    

    sum
    总和

    DB::table('notice')->sum('notice_id');
    

    avg
    平均

    DB::table('notice')->avg('notice_id');
    

    average
    同avg

    DB::table('notice')->avg('notice_id');
    

    aggregate
    查询生成器还提供了各种聚合方法,如计数、max、min、avg和和。您可以在构造查询之后调用这些方法中的任何一种:

    DB::table('notice')->aggregate('sum', ['notice_id']);
    

    numericAggregate
    方法调用aggregate,将结果转数字

    DB::table('notice')->numericAggregate('sum', ['notice_id']);
    

    insert
    插入 返回布尔值

    Notice::insert(['title' => 'ad']);
    Notice::insert(['title' => 'ad', 'a' => 1]);
    

    insertGetId
    插入 返回id

    Notice::insertGetId(['title' => 'ad']);
    

    update
    更新 返回布尔值

    $notice = Notice::find(1);
    $notice->update(['title' => 'ad']);
    

    updateOrInsert
    更新或插入

    Notice::updateOrInsert(['title' => 'ad'], ['content' => 'adcd']);
    

    increment
    加,字符串会被转成0,然后加1

    Notice::increment('title');//该字段加1
    Notice::increment('title', 6);//该字段加6
    

    decrement
    加,字符串会被转成0,然后1

    Notice::decrement('title');//该字段减1
    Notice::decrement('title', 6);//该字段减6
    

    delete
    删除

    $notice = Notice::find(1);
    return $notice->delete();
    

    truncate
    如果希望截断整个表,该表将删除所有行,并将自动递增ID重置为零,则可以使用截断方法:

    DB::table('notice')->truncate();
    

    newQuery
    获取查询生成器的新实例。

    $query = (new Notice())->newQuery();
    return $query->find(1);
    

    raw
    若要创建原始表达式,可以使用Db::raw方法

    DB::table('notice')->select(DB::raw('count(*) as notice_count'))->get();
    

    __call
    当方法不存在时,抛异常

    public function __call($method, $parameters)
    {
        if (static::hasMacro($method)) {
            return $this->macroCall($method, $parameters);
        }
     
        if (Str::startsWith($method, 'where')) {
            return $this->dynamicWhere($method, $parameters);
        }
     
        $className = static::class;
     
        throw new BadMethodCallException("Call to undefined method {$className}::{$method}()");
    }
    

    --------------------------------------------分割线----------------------------------------------

    Illuminate\Database\Query\Builder 加载的代码块

    Illuminate\Database\Concerns\BuildsQueries

    chunk
    如果你需要处理成千上万个 Eloquent 结果,可以使用 chunk 命令。chunk 方法会获取一个“组块”的 Eloquent 模型,并将其填充到给定闭包进行处理。使用 chunk 方法能够在处理大量数据集合时能够有效减少内存消耗:

    $noticeRes = [
        'success' => 0,
        'fail' => 0,
    ];
    $notice = DB::table('notice')->orderBy('notice_id')->chunk(500, function ($notices) use (&$noticeRes) {
        foreach ($notices as $notice) {
            if($notice->status == 1){
                $noticeRes['success']++;
            }else{
                $noticeRes['fail']++;
            }
        }
    });
    var_dump($notice);
    var_dump($noticeRes);
    exit();
    

    each
    在分组时对每个项执行回调,查询结果为值(value),chunk方法需要循环,each方法内部做了循环

    $noticeRes = [
        'success' => 0,
        'fail' => 0,
    ];
    $notice = DB::table('notice')
        ->orderBy('id')
        ->each(function ($notice_value, $notice_key) use (&$noticeRes) {
        if($notice_value->status){
            $noticeRes['success']++;
        }else{
            $noticeRes['fail']++;
        }
    }, 500);
    var_dump($notice);
    var_dump($noticeRes);
    exit();
    

    --------------------------------------------分割线----------------------------------------------

    下面是Illuminate\Database\Eloquent\Builder类的大部分方法

    fromQuery
    应该只有复杂查询要写原生的时候才会用到

    Notice::fromQuery("select title from notice");
    Notice::fromQuery('select title from notice WHERE title = ?', [1]);
    

    findMany

    Notice::findMany([1,2], ['title']);
    Notice::findMany(1, ['title']);
    

    findOrFail
    这个查不到会直接抛出ModelNotFoundException异常,可以在App\Exceptions\Handler定制异常捕捉

    Notice::findOrFail(100);
    

    findOrNew
    这个查不到会通过newModelInstance方法新建一个模型对象

    Notice::findOrNew(100);
    

    firstOrNew
    这个查不到会通过newModelInstance方法新建一个模型对象,并把参数一(array)attributes {array}values 合为一个数组赋给模型

    Notice::firstOrNew(['title' => 14]);
    Notice::firstOrNew(['title' => 100], ['content' => 123]);
    

    newModelInstance
    这个方法在比较后,因为前面有用到,所以先讲下
    创建模型,根据传入的数组赋值

    Notice::newModelInstance(['title' => 100, 'content' => 123]);
    

    firstOrCreate
    查询或新建一条记录,第一个参数为查询条件,如果找不到,会把参数一(array)attributes {array}values 合为一个数组赋值,新建一条记录并返回模型

    Notice::firstOrCreate(['title' => 14], ['content' => 123]);
    

    updateOrCreate
    更新或新建一条记录,第一个参数为查询条件,找到则把第二个参数的值赋给查到的model,如果找不到,会先执行firstOrNew(attributes)方法,创建对象,然后把{array}values通过fill($values)赋值再执行save()保存

    Notice::UpdateOrCreate(['title' => 14], ['content' => 1234]);
    

    源码:

    /**
       * Create or update a record matching the attributes, and fill it with values.
       *
       * @param  array  $attributes
       * @param  array  $values
       * @return \Illuminate\Database\Eloquent\Model
       */
      public function updateOrCreate(array $attributes, array $values = [])
      {
          return tap($this->firstOrNew($attributes), function ($instance) use ($values) {
              $instance->fill($values)->save();
          });
      }
    

    注:tap是laravel内置的一个方法,简单实用 https://segmentfault.com/a/1190000008447747

    function tap($value, $callback)
    {
       $callback($value);
     
       return $value;
    }
    

    firstOrFail
    查到返回对象,否则抛ModelNotFoundException异常

    Notice::firstOrFail();
    Notice::where('title', 321)->firstOrFail();
    

    firstOr
    查询一条,不存在则执行自定义callback方法, firstOr(columns = ['*'], Closure callback = null)callback可以在参数一或参数二传,方法有对第一个参数做实现Closure类的判断

    $title = 1;
    return Notice::where('title', 100)->firstOr(function() use ($title) {
         return Notice::UpdateOrCreate(['title' => $title], ['content' => 1234]);
    });
    

    with
    表关联查询
    model

    class Notice{
        public function uploadRelation()
        {
            return $this->hasMany(UploadRelation::class, 'relation_id', 'id')
                ->where('relation_type', '=', UploadRelation::RELATION_TYPE_NOTICE)
                ->select('relation_type','relation_id', 'upload_id');
        }
     
    }
     
    class UploadRelation{
        public function upload()
        {
            return $this->hasOne(Upload::class, 'id', 'upload_id');
        }   
    }
    

    调用关联

    Notice::with('uploadRelation')->get();
    Notice::with('uploadRelation.upload')->get();       
     
    Notice::with([
            'uploadRelation' => function($query){
                $query->select('relation_id', 'upload_id');
            }
        ])->get();
     
    Notice::with([
            'uploadRelation' => function($query){
                $query->select('relation_id', 'upload_id')->with([
                    'upload' => function($query){
                        $query->select('id', 'path');
                    }
                ]);
            }
        ])->get();
    

    without
    用来注销绑定

    Notice::with('uploadRelation')->get();
    Notice::with('uploadRelation')->without('uploadRelation')->get();
    

    withCount
    只获取关联条数

    Notice::withCount('uploadRelation')->get();
    

    --------------------------------------------分割线----------------------------------------------

    Illuminate\Database\Query\Builder 加载的代码块

    Illuminate\Database\Eloquent\Concerns\QueriesRelationships

    whereHas
    当绑定关系有数据的时候

    Notice::whereHas('uploadRelation')->get();
    
    $status = 1;
    Notice::whereHas(
        'uploadRelation', function ($query) use ($status) {
        $query->where('status', $status);
    })->get();
    

    实用:
    数据库:查询生成器(Database: Query Builder):https://laravel.com/docs/5.6/queries
    Laravel API Builder:https://laravel.com/api/5.3/Illuminate/Database/Eloquent/Builder.html

    纯手写,转载请注明出处哈~~~

    相关文章

      网友评论

          本文标题:Lumen 数据库操作orm

          本文链接:https://www.haomeiwen.com/subject/cavxnftx.html