• lumen model orm


    我尽量遍历写一遍IlluminateDatabaseQueryBuilder类的大部分方法

    select
    设置查询字段
    Notice::select('title')->get();
    Notice::select(['title', 'content'])->get();
    selectRaw
    查询自定义内容
    Notice::selectRaw("count('id') as notice_count")->get();
    addSelect 
    如果您已经有一个查询构建器实例,并且希望在其现有select子句中添加一列,则可以使用以下addSelect方法:
    $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
    )
    

    这里补充一下模型关联的方法

    hasOne
        public function user($class = User::class)
        {
            return $this->hasOne($class, 'id', 'user_id');
        }
    order表的user_id关联user表的id,一对一,$class 可以作为参数,当user子类model关联order子类model的时候,可以灵活重写
        public function user($class = User::class)
        {
            return $this->hasOne($class, 'id', 'user_id');
        }

       当你需要关联最后一条记录时

        public function order($class = Order::class)
        {
            return $this->hasOne($class, 'user_id', 'id')->orderBy('id', 'desc');
        }
    

     where之类的条件拼接也是可行的

        public function order($class = Order::class)
        {
            return $this->hasOne($class, 'user_id', 'id')->where('status', Order::STATUS_CREATE);
        }
    

      

    hasMany
        public function orders($class = Order::class)
        {
            return $this->hasMany($class, 'user_id', 'id');
        }
    

      user表的id关联order表的user_id,一对多

    belongsTo
        public function user($class = User::class)
        {
            return $this->belongsTo($class, 'user_id', 'id');
        }
    order表的user_id关联user表的id,一对一

    这里有人可能会问,这belongsTo和hasOne有啥区别
    网上是这样解释的

    hasOne(hasMany)使用在:外键在子关联对象中,如业务上user表在order表之上,在User模型使用hasOne关联order
    class User{
        public function order($class = Order::class)
        {
            return $this->hasOne($class, 'user_id', 'id');
        }  
    }
    

      

    belongsTo(belongsToMany)使用在:外键在父联对象中,如业务上order表在user表之下,在Order模型使用belongsTo关联user
    class Order{
        public function user($class = User::class)
        {
            return $this->belongsTo($class, 'user_id', 'id');
        }  
    }
    
    
    belongsToMany
        public function roles()
        {
            return $this->belongsToMany(
                CommonModelsRbacRole::class,
                'admin_has_roles',
                'admin_id',
                'role_id'
            );
        }
    

      管理员表admin,角色表role,中间表为admin_has_roles,admin表可以通过中间表查出对应的角色集合

    我们可以看出,这里的使用也印证了hasMany与belongsToMany的区别,belongsToMany是向上查询的,必有一张admin_has_roles的中间表进行关联

    这样描述可能有点抽象,我们可以假设上面的user和order的例子,

    当一个order指向多个user时(比如多人拼单,只是假设),我们不可能在user表加order_id,所以下级业务表order在关联上级业务表user时,必会有order_has_users之类的中间表,也会用到belongsToMany关联,而不是hasMany了(暂时没有更通俗的表述,有好的建议可以评论补充一下)

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

      

    orHavingRaw
    $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
    Notice::orderByDesc('title')->get();
    
    
    latest
    public function latest($column = 'created_at')
    {
        return $this->orderBy($column, 'desc');
    }
    
    
    oldest
    public function oldest($column = 'created_at')
    {
        return $this->orderBy($column, 'asc');
    }
    

      

    inRandomOrder
    随机排序法 可传参,传同样参数会得到同样的排列
    Notice::inRandomOrder()->get();
    Notice::inRandomOrder(1)->get();
    
    
    orderByRaw
    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 同上 返回参数有所删减,数据量较大的查询性能较高

    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
    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}()");
        }
    

      

    IlluminateDatabaseQueryBuilder 加载的代码块 
    IlluminateDatabaseConcernsBuildsQueries
    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();
    

      

    下面是IlluminateDatabaseEloquentBuilder类的大部分方法

    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异常,可以在AppExceptionsHandler定制异常捕捉
    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 IlluminateDatabaseEloquentModel
         */
        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();
    

      

    null

    ->whereNotNull('updated_at');
    ->whereNull('updated_at');
    

      

    实用:
    数据库:查询生成器(Database: Query Builder):https://laravel.com/docs/5.6/queries

    Laravel API Builder:https://laravel.com/api/5.3/Illuminate/Database/Eloquent/Builder.html

    高级Join方法
    如果join方法的约束条件比较复杂,可以使用闭包函数的方式指定
    
    DB::table('users')
       ->join('contacts', function ($join) {
           $join->on('users.id', '=', 'contacts.user_id')->orOn(...);
       })
       ->get();
    如果join约束中要使用列值与指定数组比较,则可以使用where和OrWhere方法
    
    DB::table('users')
       ->join('contacts', function ($join) {
           $join->on('users.id', '=', 'contacts.user_id')
                ->where('contacts.user_id', '>', 5);
       })
       ->get();
    

      

    高级join:https://segmentfault.com/a/1190000005792605

    转载自:

    Lumen 数据库操作orm:https://www.jianshu.com/p/492e1cb1eb28 

    Lumen 数据库操作orm之表关联hasOne(hasMany)和belongsTo(belongsToMany):https://www.jianshu.com/p/d11e5f84a699

  • 相关阅读:
    MS CRM 2011 C#中获取Web Resource
    MS CRM 2011 Form与Web Resource在JScript中的相互调用
    MS CRM 2011 JScript操作lookup control
    MS CRM 2011 导出Ribbon的定义
    MS CRM 2011 为64位Outlook安装Silverlight
    MS CRM 2011 JScript getValue 与 setValue方法
    MS CRM 2011 在JScript中同步和异步使用REST Endpoint
    C#实现全局快捷键(系统热键)响应(转)
    程序隐藏启动的C#实现经验
    WinForm程序启动时不显示主窗体
  • 原文地址:https://www.cnblogs.com/cxscode/p/8444457.html
Copyright © 2020-2023  润新知