我尽量遍历写一遍Illuminate\Database\Query\Builder类的大部分方法

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(
\Common\Models\Rbac\Role::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}()");
}

  

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

  

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

lumen model orm的更多相关文章

  1. model ,orm,dao,service,持久层 ,mvc 这些名词在java中的概念?

    这些概念不针对某个特定的编程语言. view层:结合control层,显示前台页面. control层:业务模块流程控制,调用service层接口. service层:业务操作实现类,调用dao层接口 ...

  2. python Django 之 Model ORM inspectdb(数据库表反向生成)

    在前一篇我们说了,mybatis-generator反向生成代码. 这里我们开始说如何在django中反向生成mysql model代码. 我们在展示django ORM反向生成之前,我们先说一下怎么 ...

  3. Django之Model (ORM)

    传统操作数据库 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接数据库,并编写数据访问层代码 业务逻辑层去调用数据访问层 ...

  4. Python菜鸟之路:Django 路由、模板、Model(ORM)

    Django路由系统 Django的路由系统让Django可以根据URI进行匹配,进而发送至特定的函数去处理用户请求.有点类似nginx的location功能. Django的路由关系分为三种:普通关 ...

  5. Python Web框架篇:Django Model ORM(对象关系映射)

    一,基本操作 用于实现面向对象编程语言里不同类型系统的数据之间的转换,换言之,就是用面向对象的方式去操作数据库的创建表以及增删改查等操作. 1.增(create , save): from app01 ...

  6. Django 之Model(ORM)

    app01.models.py中写类 python manage.py makemigrations python manage.py migrate python3 manage.py create ...

  7. python_way day18 html-day4, Django路由,(正则匹配页码,包含自开发分页功能), 模板, Model(jDango-ORM) : SQLite,数据库时间字段插入的方法

    python_way day18 html-day4 1.Django-路由系统   - 自开发分页功能 2.模板语言:之母板的使用 3.SQLite:model(jDango-ORM) 数据库时间字 ...

  8. tornado with MySQL, torndb, django model, SQLAlchemy ==> JSON dumped

    现在,我们用torndo做web开发框架,用他内部机制来处理HTTP请求.传说中的非阻塞式服务. 整来整去,可谓之一波三折.可是,无论怎么样,算是被我做成功了. 在tornado服务上,采用三种数据库 ...

  9. Go项目中beego的orm使用和gorm的使用

    按照beego官方文档练习ORM的使用,model创建完始终没找到办法创建表,于是使用gorm翻译文档和官方文档进行了练习,使用起来还是比较简单. 安装: 方法一:Terminal打开,go get ...

随机推荐

  1. parallax corrected cubemap

    https://community.arm.com/graphics/b/blog/posts/reflections-based-on-local-cubemaps-in-unity https:/ ...

  2. 一起來玩鳥 Starling Framework(9)Particle

    最後,來看看Starling裡一個很炫的功能:Particle.Particle屬於extension,所以要另外下載檔案:Starling-Extension-Particle-System.下載之 ...

  3. 【千纸诗书】—— PHP/MySQL二手书网站后台开发之功能实现

    前言:前一篇温习了网站开发需要掌握的基础知识,这一篇重点梳理一下各个功能模块的[详细设计与实现].项目github地址:https://github.com/66Web/php_book_store, ...

  4. Android基础新手教程——4.1.3 Activity登堂入室

    Android基础新手教程--4.1.3 Activity登堂入室 标签(空格分隔): Android基础新手教程 本节引言: 好的,在学习了两节的Activity后相信大家已经知道怎样去使用Acti ...

  5. java压缩 GZIP进行简单压缩,ZIP进行多文件保存

    java压缩  GZIP进行简单压缩,ZIP进行多文件保存 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGlhbmdydWkxOTg4/font/5a6 ...

  6. 倍福TwinCAT(贝福Beckhoff)基础教程7.1 TwinCAT如何简单执行NC功能块 TC2

    TC2的程序是在TC3的基础上稍作调整,只说明不同点,请先看TC3的. TC2中的一个原本是AXIS_REF类型变量被拆成了两个(PLCTONC_AXLESTRUCT和NCTOPLC_AXLESTRU ...

  7. 使用Google-Authenticator加强serverSSH登录

    对于须要特殊加密的人群,我这里给出对应的方法来进行谷歌式加密. 过程例如以下: 准备: 首先在你的手机上准备好client(自己百度下载) 接下来依照命令做: date 查看系统时间       da ...

  8. win10系统怎样手动安装cab更新补丁

    win10系统怎样手动安装cab更新补丁 1. 把所有补丁放进一个文件夹 例如 C:\UPDATE2. 以管理员运行命令提示符 3. 输入以下命令後按 Enterdism /online /add-p ...

  9. mpvue + iview 实现跨平台开发(App,Wap,微信小程序)

    1.安装 vue-cli 脚手架 npm install --g vue-cli 2.创建项目 vue init mpvue/mpvue-quickstart test-wxapp cd test-w ...

  10. C指针解析 ------ 运算符&和*

    本文是自己学习所做笔记,欢迎转载,但请注明出处:http://blog.csdn.net/jesson20121020 & 是取地址运算符.* 叫做指针运算符或间接运算符.&a 的运算 ...