zoukankan      html  css  js  c++  java
  • Laravel笔记--Eloquent 模型

    Eloquent 模型

    默认继承use IlluminateDatabaseEloquentModel类。

    数据表名称与模型名称约定:

    数据库的表名一般使用“蛇形命名法”命名。蛇形命名法要求单词小写,单词之间用_下划线连接,且名称是复数。

    与之对应的模型名称,则使用“帕斯卡法“命名,即单词头一字母都大写。

    如果不是按以上约定,则需指明对应的数据表:

    class Flight extends Model
    {
        /**
         * 与模型关联的数据表
         *
         * @var string
         */
        protected $table = 'myflights';
    }

    主键:

    模型默认数据表用id字段作主键,并且是递增整数类型。这些可以自定义:

    class Flight extends Model
    {
        /**
         * 与模型关联的数据表
         */
        protected $table = 'my_flights';
    
        protected $primaryKey='mid';  //自定义主键字段
        
        protected $keyType = 'string';  //自定义主键类型为字串
        
        public $incrementing = false;    //主键非自增型
    }

    时间截:

    模型默认存在created_at 和 updated_at两字段,可设定$timestamps不需两字段:

    class Flight extends Model
    {
        /**
         * 该模型是否被自动维护时间戳
         */
        public $timestamps = false;
    }

    $dateFormat属性可自定义时间截格式存储在数据表的格式:

    class Flight extends Model
    {
        /**
         * 模型的日期字段的存储格式
         */
        protected $dateFormat = 'U';
    }

    自定义时间截字段名:

    <?php
    
    class Flight extends Model
    {
        const CREATED_AT = 'creation_date';
        const UPDATED_AT = 'last_update';
    }

    自定义数据库连接:

    class Flight extends Model
    {
        /**
         * 此模型的连接名称。
         */
        protected $connection = 'connection-name';
    }

    模型查询:

    use AppFlight;
    
    $flights = AppFlight::all();   //查询所有数据
    
    foreach ($flights as $flight) {
        echo $flight->name;
    }
    
    $flights = AppFlight::where('active', 1)
                   ->orderBy('name', 'desc')
                   ->take(10)
                   ->get();             //有条件地查询数据

     all和get方法返回 IlluminateDatabaseEloquentCollection实例。

    如果查询大批量数据,可使用chunk,可节省内存:

    Flight::chunk(200, function ($flights) {
        foreach ($flights as $flight) {
            //
        }
    });

    或使用游标方法cursor大幅度减少内存的使用:

    foreach (Flight::where('foo', 'bar')->cursor() as $flight) {
        //
    }

    查询单条数据:

    // 通过主键取回一个模型...
    $flight = AppFlight::find(1);
    
    // 取回符合查询限制的第一个模型 ...
    $flight = AppFlight::where('active', 1)->first();
    
    //如果找不到模型则抛出异常
    //IlluminateDatabaseEloquentModelNotFoundException
    //自动返回 HTTP 404 响应给用户
    $model = AppFlight::where('legs', '>', 100)->firstOrFail();

    聚合查询:

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

    数据更新:

    save方法:需要先检索一次,再设置要更新的属性再执行save方法,同时updated_at也会自动更新。

    update方法:设置where条件,将更新字段以键值对传入update方法。该更新不会触发saved和updated模型事件。

    $flight = AppFlight::find(1);
    $flight->name = 'New Flight Name';
    $flight->save(); //查询一次后再更新
    
    
    AppFlight::where('active', 1)
              ->where('destination', 'San Diego')
              ->update(['delayed' => 1]); //设置条件后再批量更新

    插入数据:

    使用模型创建数据,需先设置$fillable或$guarded属性。两属性只能二选一。

    class Flight extends Model
    {
        /**
         * 可以被批量赋值的属性。
         * @var array
         */
        protected $fillable = ['name'];
    }
    
    class Flight extends Model
    {
        /**
         * 不可被批量赋值的属性。可定义为空数组,表示所有属性都可以赋值。
         * @var array
         */
        protected $guarded = ['price'];
    }

    插入数据的方法:

    $flight = AppFlight::create(['name' => 'Flight 10']); //添加新记录并返回已保存的模型实例
    
    $flight->fill(['name' => 'Flight 22']); //已有实例模型可使用fill方法
    // 通过 name 属性检索航班,当结果不存在时创建它...
    $flight = AppFlight::firstOrCreate(['name' => 'Flight 10']);
    
    // 通过 name 属性检索航班,当结果不存在的时候用 name 属性和 delayed 属性去创建它
    $flight = AppFlight::firstOrCreate(
        ['name' => 'Flight 10'], ['delayed' => 1]
    );
    
    // 通过 name 属性检索航班,当结果不存在时实例化...
    $flight = AppFlight::firstOrNew(['name' => 'Flight 10']);
    // 通过 name 属性检索航班,当结果不存在的时候用 name 属性和 delayed 属性实例化
    $flight = AppFlight::firstOrNew(
        ['name' => 'Flight 10'], ['delayed' => 1]
    );
    
    // 如果有从奥克兰飞往圣地亚哥的航班,将价格设为 99 美元
    // 如果不存在匹配的模型就创建一个
    $flight = AppFlight::updateOrCreate(
        ['departure' => 'Oakland', 'destination' => 'San Diego'],
        ['price' => 99]
    );

    firstOrCreate:如果查不到该数据,则根据第一参数和第二参数记录创建记录返回保存的模型;

    firstOrNew:如果查不到该数据,则根据第一参数和第二参数记录创建新模型,但并未保存数据,需要手动save才可以保存数据;

    updateOrCreate:根据第一参数作条件用更新第二参数数据,如果数据不存在则合并两参数创建记录返回保存的模型。

    删除模型:

    $flight = AppFlight::find(1);
    $flight->delete();  //通过查询所得的模型实例进行delete方法删除
    
    //通过主键删除一至多条数据:
    AppFlight::destroy(1);
    AppFlight::destroy([1, 2, 3]);
    AppFlight::destroy(1, 2, 3);
    
    //通过查询条件批量删除,并返回删除条数
    $deletedRows = AppFlight::where('active', 0)->delete();

    批量删除时,deleted和deleting模型事件不会被触发。

     软删除:

    数据表应设置deleted_at字段。模型内引用SoftDeletes trait,并设置deleted_at字段到$dates属性上。

    <?php
    
    namespace App;
    
    use IlluminateDatabaseEloquentModel;
    use IlluminateDatabaseEloquentSoftDeletes;
    
    class Flight extends Model
    {
        use SoftDeletes;
    
        /**
         * 需要被转换成日期的属性。
         * @var array
         */
        protected $dates = ['deleted_at']; 
    }

    设置了软删除的模型,在delete方法会设置deleted_at为当前日期和时间。查询软删除的模型会自动排除被软删除的模型。

    if ($flight->trashed()) {
        //检查该模型实例是否被软删除
    }
    
    $flights = AppFlight::withTrashed()  //能使用查询包含软删除的数据
                    ->where('account_id', 1)
                    ->get();
    
    $flights = AppFlight::onlyTrashed()  //只查询软删除的数据
                    ->where('airline_id', 1)
                    ->get();
    
    $flight->restore();  //恢复被软删除的模型
    
    AppFlight::withTrashed()   //批量恢复模型,不会触发任何模型事件
            ->where('airline_id', 1)
            ->restore();

    软删除模型使用强制删除:

    $flight->forceDelete();

    查询作用域:

    给模型添加查询约束。分全局和本地两种:

    全局--每个查询都自动加条件约束;

    本地--根据需要调用本地约束。

    全局作用域:

    首先需实现scope接口类.

    <?php
    
    namespace AppScopes;
    
    use IlluminateDatabaseEloquentScope;
    use IlluminateDatabaseEloquentModel;
    use IlluminateDatabaseEloquentBuilder;
    
    class AgeScope implements Scope
    {
        /**
         * 将范围应用于给定的 Eloquent 查询生成器
         *
         * @param  IlluminateDatabaseEloquentBuilder  $builder
         * @param  IlluminateDatabaseEloquentModel  $model
         * @return void
         */
        public function apply(Builder $builder, Model $model)
        {
            return $builder->where('age', '>', 200);
        }
    }

    如果全局作用域要将字段添加到查询的 select 语句中,则应该使用 addSelect 方法而不是 select,以免替换查询的现有select。

    应用全局作用域:

    在模型的boot方法使用addGlobalScope方法。

    <?php
    
    namespace App;
    
    use AppScopesAgeScope;
    use IlluminateDatabaseEloquentModel;
    
    class User extends Model
    {
        /**
         * 模型的「启动」方法
         *
         * @return void
         */
        protected static function boot()
        {
            parent::boot();
    
            static::addGlobalScope(new AgeScope);
        }
    }

    也可以使用闭包定义全局作用域,不必单独定义一个类:

    class User extends Model
    {
        /**
         * 模型的「启动」方法
         *
         * @return void
         */
        protected static function boot()
        {
            parent::boot();
    
            static::addGlobalScope('age', function(Builder $builder) {
                $builder->where('age', '>', 200);
            });
        }
    }

    删除全局作用域:

    User::withoutGlobalScope(AgeScope::class)->get();  //删除指定的作用域
    
    // 删除所有的全局作用域
    User::withoutGlobalScopes()->get();
    
    // 删除一些全局作用域
    User::withoutGlobalScopes([
        FirstScope::class, SecondScope::class
    ])->get();

    本地作用域:

    定义通用的约束在需要时使用。定义方法:在模型内定义scope前缀的方法。

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

    使用方法:

    $users = AppUser::popular()->active()->orderBy('created_at')->get();

    动态作用域:

    class User extends Model
    {
        /**
         * 限制查询只包括指定类型的用户。
         *
         * @return IlluminateDatabaseEloquentBuilder
         */
        public function scopeOfType($query, $type)
        {
            return $query->where('type', $type);
        }
    }
    
    //调用作用域时传参
    $users = AppUser::ofType('admin')->get();

    模型事件:

    retrieved --查询触发

    creatingcreated--创建触发

    updatingupdated--更新触发

    savingsaved--创建、更新触发

    deletingdeleted--删除触发

    restoringrestored--恢复触发

    事件指派相应的监控器:

    <?php
    
    namespace App;
    
    use AppEventsUserSaved;
    use AppEventsUserDeleted;
    use IlluminateNotificationsNotifiable;
    use IlluminateFoundationAuthUser as Authenticatable;
    
    class User extends Authenticatable
    {
        use Notifiable;
    
        /**
         * 模型的事件映射。
         *
         * @var array
         */
        protected $dispatchesEvents = [
            'saved' => UserSaved::class,   //触发saved事件,调用UserSaved监控器
            'deleted' => UserDeleted::class, //触发deleted事件,调用UserDeleted监控器
        ];
    }

    也可所有监听放在一个观察器类中:

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

    注册观察器:

    <?php
    
    namespace AppProviders;
    
    use AppUser;
    use AppObserversUserObserver;
    use IlluminateSupportServiceProvider;
    
    class AppServiceProvider extends ServiceProvider
    {
        /**
         * 运行所有应用.
         *
         * @return void
         */
        public function boot()
        {
            User::observe(UserObserver::class);
        }
    }
  • 相关阅读:
    在ASP.NET中把数据POST到其他页面
    在网页中使用javascript打开没有最大化、最小化和关闭按钮的窗口
    怎么找回被删并清空了回收站的文件
    域控制器的安装步骤二——把客户机加入到域
    升级和卸载域AD:实现域网络管理二
    不用设置BIOS,也能让光驱启动电脑!
    老版(旧版)封神榜片头,片尾曲
    域控制器的安装步骤一
    SEO面试试题
    如何将客户机添加到域?
  • 原文地址:https://www.cnblogs.com/xiwang6428/p/9228471.html
Copyright © 2011-2022 走看看