[Laravel] 16 - DB: Eloquent

前言


1、大纲

写后端API,与数据库打交道无疑是很重要的角色。php

PHP数据库操做:从MySQL原生API到PDOhtml

PHP数据库操做:使用ORMmysql

Ref: [PHP] 07 - Json, XML and MySQLlaravel

 

 

2、细节

SQL 教程sql

 

 

3、初识 Eloquent ORM

Eloquent ORM是Laravel框架使用的ORM。Laravel 的 Eloquent ORM 提供了更优雅的ActiveRecord 实现来和数据库的互动。每一个数据库表对应一个模型文件。数据库

Goto: Eloquent: 入门【2.完整复习版本】后端

From: Eloquent ORM笔记【1.基础篇】api

新增
# 新建了一条 id, name
$user = new User; $user->name = 'John'; $user->save(); $insertedId = $user->id;//从对象取得 id 属性值

使用模型的 Create 方法 class User extends Model { protected $guarded = ['id', 'account_id'];  //黑名单,不会被更新 } // 创建一个用户 $user = User::create(['name' => 'John']); // 以属性找用户 - 若没有则新增并取得新的实例... $user = User::firstOrCreate(['name' => 'John']); // 以属性找用户 - 若没有则创建新的实例... $user = User::firstOrNew(['name' => 'John']);


辨析
firstOrCreate:判断以后直接入库
firstOrNew :判断以后还要作其余业务流程,以后再入库
$student=Student::firstOrNew([ 'vip_name'=>'mmm']); 
$student->save();   # 就是须要再单独save一下

删除
$this->where($where)->delete(); 或者 $user = User::find(1); $user->delete();


更新
return $this->where($where)->update($data); 或者 $user = User::find(1); $user->update($data);


查找
//取出全部记录 - 能够遍历 $this->all()->toArray(); //取出一条数据 $one = $this->find('2'); return array( $one->id, $one->title, $one->content, ); //查找id=2的第一条数据 $this->where('id', 2)->first()->toArray(); //查找id>0的全部数据 $this->where('id', '>', '0')->get()->toArray();
  • For find(n), you retrieve a row based on the primary key which is 'n'.
  • For first(), you retrieve the first row among all rows that fit the where clauses.
  • For get()  , you retrieve all the rows that fit the where clauses. (Please note that loops are required to access all the rows or you will get some errors).
//降序排列 
$this->where('id', '>', '0')->orderBy('id', 'desc')->get()->toArray(); //降序排列,计数 
$this->where('id', '>', '0')->orderBy('id', 'desc')->count(); //从offset起始算起的limit条数据 
$this->where('id', '>', '0')->orderBy($order[0], $order[1])->skip($offset)->take($limit); //等同于
$this->where('id', '>', '0')->orderBy($order[0], $order[1])->offset($offset)->limit($limit);


条件类
//条件类 where('id', '>', '0') where('id', '>=', '0') where('id', '<', '0') where('id', '<=', '0') where('id', 'like', 'name%') whereIn($key, $array) whereNotIn($key, $array) whereBetween($key, $array) whereNotBetween($key, $array) orWhereIn($key, $array) orWhereNotIn($key, $array) orWhereBetween($key, $array) orWhereNotBetween($key, $array)


结果方法
//结果方法:Illuminate\Database\Query\Builder first()取第一个 get()取全部 all()取全部(无条件)


数学统计
//聚合方法 count() avg() sum() max() min()

 

 

  

Pure SQL


RDBMS 指关系型数据库管理系统,全称 Relational Database Management System。数组

(1). 登陆:mysql -u root -p 闭包

(2). phpMyAdmin建立数据库,并导入.sql文件。

(3). 支持中文:set names utf8;

 

详见:[MySQL] 01- Basic sql 

 

 

 

Eloquent: 入门


{tip} 因为 Eloquent 模型是查询构造器,所以你应当去阅读全部 查询构造器 中可用的方法。

 

1、模型

  • 生成模型、迁移文件
php artisan make:model User --migration php artisan make:model User -m
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;  # 全部的 Eloquent 模型都继承自这个 class Flight extends Model
{
    // 用它从  数据表中取回与保存信息
}flights

 

  • 默认经常使用四属性

[1] 表名

除非数据代表确地指定了其它名称,不然将使用类的「蛇形名称」、复数形式名称来做为数据表的名称。自定义对应表名:

protected $table = 'my_flights';

 

 [2] 主键

设每一个数据表都有一个叫作 id 的主键字段。你也能够定义一个 $primaryKey 属性来重写这个约定。

默认是递增;不然,必须在你的模型 public $incrementing=false

 

[3] 时间戳

默认状况下,Eloquent 会认为在你的数据库表有 created_at 和 updated_at 字段。

若是你不但愿让 Eloquent 来自动维护这两个字段,可在模型内将 $timestamps=false

决定了日期应如何在数据库中存储,以及当模型被序列化成数组或 JSON 格式 protected $dateFormat = 'U';

 

[4] 链接数据库 

默认状况下,全部的 Eloquent 模型会使用应用程序中默认的数据库链接设置。

若是你想为模型指定不一样的链接,可使用 protected $connection = 'connection-name'; 

 

[5] 经过模型获取结果

$flights = App\Flight::where('active', 1) ->orderBy('name', 'desc') ->take(10) ->get();

 

  • 模型建立与删除

详见:"3、初识 Eloquent ORM"

补充:软删除

模型上设置一个 deleted_at 属性并将其添加到数据库。若是模型有一个非空值 deleted_at,表明模型已经被软删除了。

[1] 设置字段

当模型被软删除时,它们并不会真的从数据库中被移除。而是会在模型上设置一个 deleted_at 属性并将其添加到数据库。

若是模型有一个非空值 deleted_at,表明模型已经被软删除了。

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class Flight extends Model
{
    use SoftDeletes;

    /**
     * 须要被转换成日期的属性。
* 添加  字段到你的  属性。 * * @var array
*/ protected $dates = ['deleted_at']; }deleted_at$dates

 

[2] 添加 deleted_at 字段到数据表 

Schema::table('flights', function ($table) { $table->softDeletes(); });

当查询有启用软删除的模型时,被软删除的模型将会自动从全部查询结果中排除。

 

[3] 查询 deleted_at 字段

确认指定的模型实例是否已经被软删除,可使用 trashed 方法:

if ($flight->trashed()) { // }

 

[4] 查询捎带上 '软删除‘ 集合

$flights = App\Flight::withTrashed() ->where('account_id', 1) ->get();

 

[5] 只查询 ‘软删除’ 集合

$flights = App\Flight::onlyTrashed() ->where('airline_id', 1) ->get();

 

[6] 恢复 '软删除'

$flight->restore(); App\Flight::withTrashed() ->where('airline_id', 1) ->restore();

 

[7] 永久地删除模型

// 强制删除单个模型实例...
$flight->forceDelete(); // 强制删除全部相关模型...
$flight->history()->forceDelete();

 

 

2、集合

Collection 类提供 多种辅助函数 来处理你的 Eloquent 结果。 

 

  • 遍历 Chunk & Cursor 

[Chunk]

It will "paginate" your query, this way you use less memory. (1) Uses less memory (2) It takes longer

public function getData() { Contact::chunk(1000, function ($contacts) { foreach ($contacts as $contact) { //rest of your code...
 } }); }

[Cursor]

You will use PHP Generators to search your query items one by one. (1) It takes less time (2) Uses more memory

public function getData() { foreach (Contact::cursor() as $contact) { //rest of your code...
 } }

 

  • 返回指定行
// 取回符合查询限制的第一个模型 ...
$flight  = App\Flight::where('active', 1)->first(); $flights = App\Flight::find([1, 2, 3]);

  

  • ‘未找到’ 处理
$model = App\Flight::findOrFail(1); $model = App\Flight::where('legs', '>', 100)->firstOrFail(); 
// 用法示范 Route
::get('/api/flights/{id}', function ($id) {
  return App\Flight::findOrFail($id);
});

 

  • 聚合函数

可使用 countsummax和其它 查询构造器 提供的 聚合函数

这些方法会返回适当的标量值,而不是一个完整的模型实例

$count = App\Flight::where('active', 1)->count(); $max   = App\Flight::where('active', 1)->max('price');

 

 

3、控制器

  • 添加一条记录

自动完成了例如对时间戳的记录。

<?php namespace App\Http\Controllers; use App\Flight; use Illuminate\Http\Request; use App\Http\Controllers\Controller; class FlightController extends Controller { /** * 建立一个新的航班实例。 * * @param Request $request * @return Response */
    public function store(Request $request) {
        $flight = new Flight;
$flight->name = $request->name; $flight->save(); } }

 

  • 更新 & 批量更新
$flight = App\Flight::find(1); $flight->name = 'New Flight Name'; $flight->save();

两个where并列条件,而后更新字段:delayed

App\Flight::where('active', 1) ->where('destination', 'San Diego') ->update(['delayed' => 1]);

{note} 当经过“Eloquent”批量更新时,savedupdated模型事件将不会被更新后的模型代替。这是由于批量更新时,模型历来没有被取回。

 

  • 批量赋值

注意批量赋值是有风险的,全部的 Eloquent 模型都针对批量赋值(Mass-Assignment)作了保护。

方案:$fillable 做为一个能够被批量赋值的属性「白名单」;$guarded 是「黑名单」,设置为空表明大门敞开。 

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    /**
     * 能够被批量赋值的属性。
* 使  模型的  属性能够被批量赋值 * * @var array */
protected $fillable = ['name']; }Flightname

赋值:

$flight = App\Flight::create(['name' => 'Flight 10']); $flight->fill(['name' => 'Flight 22']);

 

 

4、查询做用域

  • 编写 全局做用域

自定义全局做用域很简单,首先定义一个实现 Illuminate\Database\Eloquent\Scope 接口的类,该接口要求你实现一个方法:apply

<?php namespace App\Scopes; use Illuminate\Database\Eloquent\Scope; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Builder; class AgeScope implements Scope { /** * 应用做用域 * * @param \Illuminate\Database\Eloquent\Builder $builder * @param \Illuminate\Database\Eloquent\Model $model * @return void */
    public function apply(Builder $builder, Model $model) { return $builder->where('age', '>', 200); # select * from `users` where `age` > 200 } }

{tip} Laravel 没有规定你须要把这些类放置于哪一个文件夹,你能够自由在 app 文件夹下建立 Scopes 文件夹来存放。

 

  • 应用全局做用域
<?php

namespace App;

use App\Scopes\AgeScope;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * 数据模型的启动方法
     *
     * @return void
     */
    protected static function boot()                    # 须要重写给定模型的 boot 方法
    {
        parent::boot();
        static::addGlobalScope(new AgeScope);            # 并使用  方法
    }
}addGlobalScope

添加做用域后,若是使用 User::all() 查询则会生成以下SQL语句:select * from `users` where `age` > 200

 

  • 匿名的全局做用域

Eloquent 还容许咱们使用闭包定义全局做用域,这在实现简单做用域的时候特别有用,这样的话,咱们就不必定义一个单独的类。

<?php namespace App; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Builder; class User extends Model { /** * 数据模型的启动方法 * * @return void */
    protected static function boot() { parent::boot(); static::addGlobalScope('age', function(Builder $builder) { $builder->where('age', '>', 200); }); } }

 

  • 移除 全局做用域
User::withoutGlobalScope('age')->get(); User::withoutGlobalScope(AgeScope::class)->get(); // 移除多个
User::withoutGlobalScopes([FirstScope::class, SecondScope::class])->get();

  

  • 本地做用域

本地做用域容许咱们定义通用的约束集合以便在应用中复用。

例如,你可能常常须要获取最受欢迎的用户,要定义这样的一个做用域,只需在对应 Eloquent 模型方法前加上一个 scope 前缀,做用域老是返回查询构建器:

<?php namespace App; use Illuminate\Database\Eloquent\Model; class User extends Model { /** * 限制查询只包括受欢迎的用户。 * * @return \Illuminate\Database\Eloquent\Builder */
    public function scopePopular($query) { return $query->where('votes', '>', 100); } /** * 限制查询只包括活跃的用户。 * * @return \Illuminate\Database\Eloquent\Builder */
    public function scopeActive($query) { return $query->where('active', 1); } }

  

Then, 利用查询范围

一旦定义了范围,则能够在查询模型时调用范围方法。在进行方法调用时不须要加上 scope 前缀。你甚至能够链式调用不一样的范围,如:

$users = App\User::popular()->active()->orderBy('created_at')->get();

    

  • 动态范围

定义一个可接受参数的范围。

这时只需给你的范围加上额外的参数便可。范围参数应该被定义在 $query 参数以后:

<?php namespace App; use Illuminate\Database\Eloquent\Model; class User extends Model { /** * 限制查询只包括指定类型的用户。 * * @return \Illuminate\Database\Eloquent\Builder */
    public function scopeOfType($query, $type) { return $query->where('type', $type); } }

在范围调用时传递参数:

$users = App\User::ofType('admin')->get();

 

  

5、事件

  • 模型的事件映射

事件让你每当有特定的模型类在数据库保存或更新时,执行代码。

Eloquent 模型会触发许多事件,让你在模型的生命周期多个时间点进行监控:creatingcreatedupdatingupdatedsavingsaveddeletingdeletedrestoringrestored。

 

举例子:

当一个新模型被初次保存将会触发 creating 以及 created 事件

若是一个模型已经存在于数据库且调用了 save 方法,将会触发 updating 和 updated 事件

这两种状况下都会触发 saving 和 saved事件

<?php namespace App; use App\Events\UserSaved; use App\Events\UserDeleted; use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable { use Notifiable; /** * 模型的事件映射。 * * @var array */
    protected $events = [ 'saved'   => UserSaved::class,
        'deleted' => UserDeleted::class, ]; }

  

  • 观察者

若是你在一个给定的模型中监听许多事件,您可使用观察者将全部监听器变成一个类

观察者类里的方法名应该反映Eloquent想监听的事件。 每种方法接收 model 做为其惟一的参数。

Laravel不包括观察者默认目录,因此你能够建立任何你喜欢你的目录来存放:

<?php namespace App\Observers; use App\User; class UserObserver { /** * 监听用户建立的事件。 * * @param User $user * @return void */
    public function created(User $user) { //  } /** * 监听用户删除事件。 * * @param User $user * @return void */
    public function deleting(User $user) { //  } }

AppServiceProvider注册观察者

<?php namespace App\Providers; use App\User; use App\Observers\UserObserver; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { /** * 运行全部应用. * * @return void */
    public function boot() { User::observe(UserObserver::class); } /** * 注册服务提供. * * @return void */
    public function register() { //  } }

  

Ref: Laravel 数据库之:数据库请求构建器【往后继续补充】

相关文章
相关标签/搜索