Lumen 数据库操作orm
我大概遍历了一遍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()方法最后还有两个参数,where, where是关联条件(on,where)
后面的一些join方法(joinWhere,leftJoin,leftJoinWhere,rightJoin,rightJoinWhere,crossJoin)的实现是通过传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的时候,
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)values 合为一个数组赋给模型
Notice::firstOrNew(['title' => 14]);
Notice::firstOrNew(['title' => 100], ['content' => 123]);
newModelInstance
这个方法在比较后,因为前面有用到,所以先讲下
创建模型,根据传入的数组赋值
Notice::newModelInstance(['title' => 100, 'content' => 123]);
firstOrCreate
查询或新建一条记录,第一个参数为查询条件,如果找不到,会把参数一(array)values 合为一个数组赋值,新建一条记录并返回模型
Notice::firstOrCreate(['title' => 14], ['content' => 123]);
updateOrCreate
更新或新建一条记录,第一个参数为查询条件,找到则把第二个参数的值赋给查到的model,如果找不到,会先执行firstOrNew(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
查询一条,不存在则执行自定义columns = ['*'], Closure 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