• laravel5.5之模型操作数据库 — Eloquent ORM(实践)


    一、背景

            Laravel操作数据库有三种方式,一种是用DB类操作原生sql,一种是用构造器查询,还有一种是Laravel里独特的模型操作方式,即Eloquent ORM。前两种的操作方式可以参考:https://blog.csdn.net/zls986992484/article/details/52824962,这篇博文也有总结Eloquent ORM,只是为了总结学习,写篇博文进行学习记录,如果看那篇博文感觉还有疑惑,可以回来看看这篇。

    二、准备工作

            在Laravel里,有一个工具artisan,使用这个工具可以执行很多自动化操作,当然,操作的内容也就是创建文件和生成文件里的格式代码等,所以也可以根据需要手动创建对应的文件。本篇文章都是用artisan工具进行操作。

    1. 配置数据库信息(已配置好的自动忽略)

            操作前,找到根目录下的 .env 文件,配置好数据库连接信息。

    2.  配置模型管理

      为了方便文件统一管理,我们统一把模型文件放在/app/Models/文件夹下。

      注意:因为laravel5.5默认在app文件夹下有一个的User模型文件,如果有需要,可以再重新生成一个User模型文件在Models中,再更改一下/config/auth.php下的配置,更改如下:

        'providers' => [
            'users' => [
                'driver' => 'eloquent',
                'model' => AppModelsUser::class,    // 此处更改为AppModelsUser
            ],
     
            // 'users' => [
            //     'driver' => 'database',
            //     'table' => 'users',
            // ],
        ],

    3.  生成模型文件

      Windows系统下进入dos系统,跳转到项目根目录(linux直接跳转),执行以下命令在Models中生成一个User.php模型文件:

    php artisan make:model ModelsUser

      执行后的结果:

     4. 设置模型文件中的代码

    <?php
     
    namespace AppModels;
     
    use IlluminateDatabaseEloquentModel;
     
    class User extends Model
    {
        protected $table         = 'users';                        // 为模型指定表名
        protected $primaryKey    = 'id';                            // 默认情况下指定'id'作为表主键,也可以指定主键名
        protected $timestamps    = true;                             // 默认情况下,Eloquent 期望数据表中存在 created_at 和 updated_at 字段,设置false可以取消
        protected $dateFormat    = 'U';                             // 定制时间戳的格式
        protected $fillable      = ['name', 'sex', 'age','pwd'];    // 定义允许添加、更新的字段白名单,不设置则无法添加数据
        protected $guarded       = ['id'];                     // 定义不允许更新的字段黑名单
    }

    注意: 一般开发时,以上属性配置 $fillable 就行,如果有特殊需要,再配置其他属性就好。

    三、操作模型进行数据库操作

    1.  使用 artisan 工具创建user控制器,如下命令:

    php artisan make:controller Home/UserController

    在/app/Http/controllers/Home/文件夹下生成UserController.php:

     控制器打开有如下自动生成的代码:

    <?php
     
    namespace AppHttpControllersHome;
     
    use IlluminateHttpRequest;
    use AppHttpControllersController;
     
    class UserController extends Controller
    {
        //
    }

    2. 引入模型类

    use AppModelsUser;

    3. 使用 save方法 添加一条数据

    public function insert(Request $request)
    {
        // 获取数据
        $data = $request->validate([
            'name'  =>  'required',
            'pwd'   =>  'required',
            'sex'   =>  'required',
            'age'   =>  'required'
        ]);
        // 实例化模型
        $user = new User;
        $user->name = $data['name'];
        $user->pwd  = $data['pwd'];
        $user->sex  = $data['sex'];
        $user->age  = $data['age'];
        // 向数据库中插入一条记录,返回值为新增数据数组对象
        $result = $user->save(); 
    }

    4. 使用 create方法 添加一条数据

    public function insert(Request $request)
    {
        // 获取数据
        $data = $request->validate([
            'name'  =>  'required',
            'pwd'   =>  'required',
            'sex'   =>  'required',
            'age'   =>  'required'
        ]);
        // 向数据库中插入一条记录,返回值为新增数据数组对象
        return User::create($data);
     
        // 先判断当前插入数据是否存在,存在则查找存在的第一条数据返回,不存在则执行插入,返回新增
        return User::firstOrCreate($data);
    }

    PS:如果要批量添加数据,可以使用DB操作,如:

    DB::table('users')->insert([
        ['name'=>'test1', 'pwd'=>'123', 'sex'=>1, 'age'=>1],
        ['name'=>'test1', 'pwd'=>'123', 'sex'=>1, 'age'=>1],
        ['name'=>'test1', 'pwd'=>'123', 'sex'=>1, 'age'=>1],
        ['name'=>'test1', 'pwd'=>'123', 'sex'=>1, 'age'=>1]
    ]);

    注意:使用DB操作时,需要先引入 —— use DB;

    5. save 更新单条数据

    public function update(Request $request)
    {
        $data = $request->validate([
            'id' => 'required'
        ]);
     
        // 更新数据前需要先获取当前数据
        $user = User::find($data['id']);
     
        // 获取和设置要进行更新的数据
        $map = $request->except('id');
     
        if (empty($map)) {
            return '没有更新任何数据';
        }
     
        foreach ($map as $k => $v) {
            $user->$k = $v;
        }
     
        // 返回更新后的用户信息集合
        $result = $user->save();
    }

    6. update 更新指定ID条件的单条数据

    public function update()
    {
        User::where('id', 1)->update(['name' => 'update_name']);
    }

    7. update 限定where约束条件批量更新数据

    public function updateWhere()
    {
        User::where('sex', 2)->where('age','>',30)->update([
            'name' => 'update_name'
        ]);
    }

    8. 删除数据

    public function delete(Request $request)
    {
        // 删除指定id的数据
        $id = $request->input('id');
        $user = User::find($id);
        $user->delete(); 
     
        // destroy删除指定的单个或多个id的数据
        User::destroy(1);            //删除主键为1的记录
        User::destroy([1, 2, 3]);    //删除主键为1,2,3的记录
     
        // 根据条件批量删除数据
        $deletedRows = User::where('age', 445)->delete();
    }

    9. 查询所有数据

    public function all()
    {
        return User::all();
    }

    10.  查询指定ID的数据

    public function find($id)
    {
        // 普通查询
        return User::find($id);
     
        // 使用下面的查询方法未查到数据,则会抛出404错误
        return User::findOrFail($id);
    }

    11. 指定条件查询数据

    public function findwhere() 
    {
        // 指定条件查询第一条数据,返回一维数组对象
        return User::where(['sex'=>1, 'age'=>'21'])->first();
     
        //根据where查询符合条件第一条记录,没有则抛出404
        return User::where('age', '>', 21)->firstOrFail();
     
        // 指定条件查询全部数据,返回二维数组对象
        return User::where(['sex'=>1, 'age'=>'21'])->get();
    }

     11.1  按照指定排序方式查询数据

    public function findOrderBy() 
    {
        // 按照创建时间排序,返回第一条用户数据
        return User::orderBy('created_at', 'desc')->first();
    }

    12. 组合查询(获取前几条数据)

    public function findWhere()
    {
         return User::where('age','>',10)    // 年龄大于10
                    ->where(['sex'=>1])      // 性别为男
                    ->orderBy('age', 'desc') // 按照年龄大小逆向排序
                    ->take(5)                // 获取前面5条数据
                    ->get();
    }

    13. 统计查询

    public function count()
    {
        // 根据条件统计数量
        return User::where('sex', 1)->count();
     
        // 获取满足条件的最大年龄
        return User::where('sex', 1)->max('age');
    }

    14. 分页查询 

    /*
     *    获取数据分页
     *
     *    参数:
     *        1. $num :每页显示数量;
     *        2. $colum :查询指定字段;
     *        3. $pageName :分页名称,即上下页链接分页参数名称;
     *        4. $p :指定获取的页数   
     */
    public function paginate($num = 10, $colum = [*], $pageName = 'page', $p = 1)
    {
        return User::where('sex', 1)->orderBy('created_at', 'desc')->paginate($num, $colum, $pageName, $p);
    }
     
     
    // 返回数据样式
    {
       "total": 50,                                    // 数据总数量
       "per_page": 15,                                 // 每页显示数量
       "current_page": 1,                              // 当前页码
       "last_page": 4,                                 // 上一页码
       "first_page_url": "http://laravel.app?page=1",  // 首页链接
       "last_page_url": "http://laravel.app?page=4",   // 最后页链接
       "next_page_url": "http://laravel.app?page=2",   // 下一页链接
       "prev_page_url": null,                          // 上一页链接
       "path": "http://laravel.app",                   // 根地址
       "from": 1,                                      // 当前页数据来源页
       "to": 10,                                       // 当前页数据量
       "data":[                                        // 当前页数据数组
            {
                // Result Object
            },
            {
                // Result Object
            }
       ]
    }

    15. 分块查询

    问题背景:一个完整的项目经常会隔一段时间收集、处理大批量的数据,常常是对一整张表的数据处理,而我们直接的思路往往是直接获取所有数据,然后遍历每一条数据进行操作。如果数据量很小,这样处理没问题,但如果数据量很大(一般超过5K就算大批量数据了),每一次遍历进行的数据更新操作又多,那很有可能会遇到代码执行超时的问题,并且循环几万、几十万的数据操作时,很有可能会把服务器运行内存消耗完,那就直接down机了,更恐怖。

     解决思路:每次获取一段数据块再进行遍历操作,当前数据块儿处理完成,再获取第二部分数据块儿。这样每次循环都是一小块儿数据,一个块儿数据遍历结束后再重新获取数据进行遍历,就解决了上面的问题。
    (1)普通数据遍历和块查询遍历处理的区别代码演示 

    // 普通代码演示
    $users = User::all();
    foreach ($users as $user) {
      $user->update(['sex' => 1]);
    }
     
    // 按每次处理100条数据块的方式优化代码演示
    User::chunk(100, function ($users) {
      foreach ($users as $user) {
        $user->update(['sex' => 1]);
      }
    });

    (2)带条件的块查询遍历处理

    User::where('age', '>', '20')->chunk(100, function ($users) {
      foreach ($users as $user) {
        $user->update(['sex' => 1]);
      }
    });

     注意:如果是 “自更新” 的块查询处理,则会漏掉一半的数据,如下演示:

    User::where('sex', 0)->chunk(100, function ($users) {
      foreach ($users as $user) {
        $user->update(['sex' => 1]);
      }
    });

    说明:

    运行上面的代码,不会报错,执行的逻辑是找出性别未知(sex=0)的用户,一次操作100位未知性别用户,修改性别字段sex=1。

    逻辑很简单,但在这个过程中,当第一个数据库的数据被修改后,下一个数据块的数据将是在被修改后的数据中选出来的,这个时候数据变了,而page也加了1,所以执行结束后,只对数据中一半的数据进行了更新操作。

    如果没有明白的话,来看一下chunk的底层实现。

    还以上面的代码为例,假如一共有400条数据,数据被按照100条进行分块处理。

    page = 1:最开始的时候page为1,选取1-100条数据进行处理;

    page = 2:这时候前一百数据的 sex值全部为1,那么再次筛选的时候数据将从第101条开始(此时sex=0筛选出来的是除改修改后的剩下300条),如果此时page仍然等于1,则可以按照我们正常需求执行,但这个时候的page=2,那么处理的数据将是第200-300之间的数据。

    chunk函数如下:

    public function chunk($count, callable $callback)
    {
        $results = $this->forPage($page = 1, $count)->get();
     
        while (count($results) > 0) {
            // On each chunk result set, we will pass them to the callback and then let the
            // developer take care of everything within the callback, which allows us to
            // keep the memory low for spinning through large result sets for working.
            if (call_user_func($callback, $results) === false) {
                return false;
            }
     
            $page++;
     
            $results = $this->forPage($page, $count)->get();
        }
     
        return true;
    }

    参考:https://www.jianshu.com/p/5dafd0d6e69ahttps://laraveldaily.com/process-big-db-table-with-chunk-method/

    16. 软删除

    软删除并不是物理删除,只是在对应表中添加字段 "delete_at",在使用模型查找数据时,自动判断delete_at是否为空,如果不为空则判断为已被软删除,反之则说明未被删除。先执行以下配置:

     (1) 要使用软删除的模型能力,需要先在模型文件中引入软删除引擎,此处配置User模型作为参考:

    <?php
     
    namespace AppModels;
     
    use IlluminateDatabaseEloquentModel;
    use IlluminateDatabaseEloquentSoftDeletes;    // 引入软删除引擎
     
    class User extends Model
    {
        use SoftDeletes;                             // 调用软删除类
     
        protected $dates = ['deleted_at'];
     
        protected $fillable = [
            'name', 'email', 'password', 'image'
        ];
    }

    (2)使用迁移增加delete_at字段

    php artisan make:migration alter_users_table --table=users

    3)填充迁移文件

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

    (4)执行迁移文件

    php artisan migrate

    配置以上,则可以进行软删除相关操作,具体如下:

    (1)判断某条数据是否已被软删除

    $user = User::find(1);
     
    if ($user->trashed()) {    // 判断是否被软删除
          
    }

    2)强制查询所有数据(包括被软删除的数据)

    User::withTrashed()->where('sex', 1)->get();

    3)只查询被软删除的数据

    User::onlyTrashed()->where('sex', 1)->get();


    (4)恢复被软删除的数据

    $user = User::find(1);
    $user->restore();

     (5)批量恢复多个被软删除的数据

    User::withTrashed()->where('sex', 1)->restore();

    (6)强制删除指定数据

    $user = User::find(1);
    
    // 强制删除单个模型实例...
    $user->forceDelete();
    
    // 强制删除所有相关模型...
    $user->history()->forceDelete();


    ————————————————
    版权声明:本文为CSDN博主「追风2019」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/createNo_1/article/details/81141336

    -------------------------------------------------------------------自己项目-------------------------------------------------------------------------------

    layui接口

       public function json_list(Request $request)
        {
            $param = $request->all();//->paginate($num, $colum, $pageName, $p)
            $where = [];
            if(!empty($param['searchParams']['name'])){
                $name = $param['searchParams']['name']; ;
                $where[] = ['u.username','like',"$name%"];
            }
    //        DB::connection()->enableQueryLog();
            $data =  User::from('user as u')
                ->leftJoin('roles as r','r.id','=','u.roles_id')
                ->select('u.id','u.create_time','r.roles_name','u.username')
                ->where($where)
                ->orderBy('u.id', 'desc')
                ->paginate($param['size'],'*', $pageName = 'page',$param['page'])
                ->toArray();
    //        dump(DB::getQueryLog());
    //        dump($data);die;
    //        $count  =  count(User::all());
            return ['code'=>0,'msg'=>'成功','count'=>$data['total'],'data'=>$data['data']];
        }

     

    ------------------------------------------------------------前后端接口------------------------------------------------------------------------------------------------------------

        //动态管理初始化
        public function articleInit(Request $request)
        {
            $param = $request->all();//->paginate($num, $colum, $pageName, $p)
    
            $size = $param['pageParam']['PageSize'];//每一页数量
    
            $page =$param['pageParam']['currentPage'];//当前页码数
            $where = [];
            if(!empty($param['pageParam']['searchParam'])){
                $name = trim($param['pageParam']['searchParam']);
                $where[] = ['a.title','like',"$name%"];
            }
            if(!empty($param['category_id'])){
                $name = trim($param['category_id']);
                $where[] = ['a.category_id',$name];
            }
            if(!empty($param['school_id'])){
                $name = trim($param['school_id']);
                $where[] = ['a.school_id',$name];
            }
    //       DB::connection()->enableQueryLog();
            $data =  Article::from('article as a')
                ->leftJoin('category as c','c.id','=','a.category_id')
                ->select('a.id','a.create_time','a.image_url','a.title','a.desc','a.status','a.is_home_page','c.category_name')
                ->where($where)
                ->orderBy('a.id', 'desc')
                ->paginate($size,'*', $pageName = 'page',$page)
                ->toArray();
    //          dump(DB::getQueryLog());
            //count; //总数量
            //currentPage; //当前页码
            //PageSize; //每页条数
    
            return ['status'=>200,'msg'=>'成功','count'=>$data['total'],'currentPage'=>$data['current_page'],'PageSize'=>$data['per_page'],'data'=>$data['data']];
    
    
        }
     //分类管理初始化
        public function categoryList(Request $request)
        {
            $param = $request->all();
            $size = $param['size'];//每一页数量
            $page =$param['page'];//当前页码数
            $data = Category::orderBy("id",'desc')->select('id','category_name')->paginate($size,'*', $pageName = 'page',$page)->toArray();
            foreach ($data['data'] as $k => $v){
                $data['data'][$k]['cate_sum'] = Article::where('category_id',$v['id'])->count();
            }
            return ['status'=>200,'msg'=>'删除成功','data'=>$data['data'],'total'=>$data['total']];
    
        }
  • 相关阅读:
    【Windows】Windows server2008远程桌面只允许同时存在一个会话
    【go进阶】一个简单的go服务器实现
    【linux杂谈】查看centOS系统的版本号和内核号
    【linux杂谈】centos6和centos7中固定IP的方法
    Eclipse导入GitHub项目(转)
    国际锐评
    Spring Boot与分布式
    Spring Boot与分布式
    springboot 与任务
    废掉一个人最隐蔽的方式,是让他忙到没时间成长(转)
  • 原文地址:https://www.cnblogs.com/yehuisir/p/14849681.html
Copyright © 2020-2023  润新知