Laravel框架源码解析之模型Model原理与用法解析


Posted in PHP onMay 14, 2020

本文实例讲述了Laravel框架源码解析之模型Model原理与用法。分享给大家供大家参考,具体如下:

前言

提前预祝猿人们国庆快乐,吃好、喝好、玩好,我会在电视上看着你们。

根据单一责任开发原则来讲,在laravel的开发过程中每个表都应建立一个model对外服务和调用。类似于这样

namespace App\Models;
 
use Illuminate\Database\Eloquent\Model;
 
class User extends Model
{
 protected $table = 'users';
}

解析

Laravel的数据操作分两种

  • DB facade
  • Eloquent ORM

它们除了有各自的特色外,基本的数据操作都是通过 Illuminate\Database\Query\Builder 调用方法去完成整个SQL。你也可以帮Builder这个类作为整个SQL操作的基类。这个类涵盖了以下的操作方法(部分展示)

方法
public function select($columns = ['*'])
public function selectSub($query, $as)
public function selectRaw($expression, array $bindings = [])
public function fromSub($query, $as)
public function fromRaw($expression, $bindings = [])
public function addSelect($column)
public function distinct()
public function from($table)
public function join($table, $first, $operator = null, $second = null, $type = 'inner', $where = false)
public function joinWhere($table, $first, $operator, $second, $type = 'inner')
public function joinSub($query, $as, $first, $operator = null, $second = null, $type = 'inner', $where = false)
public function leftJoin($table, $first, $operator = null, $second = null)
public function where($column, $operator = null, $value = null, $boolean = 'and')
public function orWhere($column, $operator = null, $value = null)
public function whereRaw($sql, $bindings = [], $boolean = 'and')
public function whereIn($column, $values, $boolean = 'and', $not = false)
public function orWhereIn($column, $values)

可见有很多方法在中国laravel站或者官方文档上都没有体现,所以说就算要精通一款框架,不去看它的源码也是不行的。这个文件在你项目目录中的 vendor/laravel/framework/src/Illuminate/Database/Query 下,你可以自行去查看。

DB facade

正常情况下你可能会这样写一个操作

DB::table('user')->get();

这个操作首先经过laravel的门面指向文件,不过它并不在 app.php 中,而是通过内核直接加载,它在

Illuminate\Foundation\Application -> registerCoreContainerAliases()

被注册。门面直接调用 Illuminate\Database\DatabaseManager 类。

public function registerCoreContainerAliases()
{
  foreach ([
   ...
   'encrypter'   => [\Illuminate\Encryption\Encrypter::class, \Illuminate\Contracts\Encryption\Encrypter::class],
   'db'     => [\Illuminate\Database\DatabaseManager::class],
   'db.connection'  => [\Illuminate\Database\Connection::class, \Illuminate\Database\ConnectionInterface::class],
   'events'    => [\Illuminate\Events\Dispatcher::class, \Illuminate\Contracts\Events\Dispatcher::class],
   'files'    => [\Illuminate\Filesystem\Filesystem::class],
   ....
  )
}

Illuminate\Database\DatabaseManager 内并没有太多的代码,大多都是处理数据库链接。当你使用 DB::table()时,会通过

public function __call($method, $parameters)
{
 return $this->connection()->$method(...$parameters);
}

转发,调用的是 Illuminate\Database\Connection ,用户处理 table() 方法,随后会通过 table() 方法指向 Illuminate\Database\Query 类,开头我们讲过这个类了,这里就不多说了,随后就是各种sql的拼接->执行sql->结束战斗

Laravel框架源码解析之模型Model原理与用法解析

Eloquent ORM

Eloquent ORM 与DB facade 类似,首先每个 Eloquent ORM 都需要继承父类 Illuminate\Database\Eloquent\Model
你大概会这样写

User::find(1)

父类是不存在这个方法的,它会通过

public static function __callStatic($method, $parameters)
{
 return (new static)->$method(...$parameters);
}

去转发请求调用。同理

User::get()

则是通过

public function __call($method, $parameters)
{
 if (in_array($method, ['increment', 'decrement'])) {
  return $this->$method(...$parameters);
 }
  
 return $this->newQuery()->$method(...$parameters);
}

去调用,这个方法最终以 new Builder() 而告终,

public function newEloquentBuilder($query)
{
 return new Builder($query);
}

最后我们到了 Illuminate\Database\Eloquent\Builder 文件下,这个类中涵盖了ORM的基本操作,例如find , findOrFail 等等。如果你在代码用到了get方法,抱歉,这里没有,它依旧会通过__call 方法将你的请求转发到 Illuminate\Database\Query\Builder 类中

$this->query->{$method}(...$parameters);

至此就完成了整个数据操作。

Laravel框架源码解析之模型Model原理与用法解析

希望本文所述对大家基于Laravel框架的PHP程序设计有所帮助。

PHP 相关文章推荐
PHP+MySQL5.0中文乱码解决方法
Nov 20 PHP
php 中的4种标记风格介绍
May 10 PHP
PHP数据库调用类调用实例(详细注释)
Jul 12 PHP
Apache服务器无法使用的解决方法
May 08 PHP
PHP获取当前日期所在星期(月份)的开始日期与结束日期(实现代码)
Jun 18 PHP
慎用preg_replace危险的/e修饰符(一句话后门常用)
Jun 19 PHP
php中cookie的使用方法
Mar 29 PHP
php中rename函数用法分析
Nov 15 PHP
PHP中Memcache操作类及用法实例
Dec 12 PHP
PHP获取客户端及服务器端IP的封装类
Jul 21 PHP
PHP 中常量的知识整理
Apr 14 PHP
微信公众号开发之获取位置信息php代码
Jun 13 PHP
Laravel框架源码解析之入口文件原理分析
May 14 #PHP
Laravel框架源码解析之反射的使用详解
May 14 #PHP
PHP 数组操作详解【遍历、指针、函数等】
May 13 #PHP
ThinkPHP5 框架引入 Go AOP,PHP AOP编程项目详解
May 12 #PHP
php中用unset销毁变量并释放内存
May 10 #PHP
php屏蔽错误及提示的方法
May 10 #PHP
php判断数组是否为空的实例方法
May 10 #PHP
You might like
打造计数器DIY三步曲(中)
2006/10/09 PHP
PHP 输出缓存详解
2009/06/20 PHP
PHP Ajax JavaScript Json获取天气信息实现代码
2016/08/17 PHP
php类的自动加载操作实例详解
2016/09/28 PHP
JavaScript使用cookie
2007/02/02 Javascript
阻止JavaScript事件冒泡传递(cancelBubble 、stopPropagation)
2007/05/08 Javascript
javascript网页关闭时提醒效果脚本
2008/10/22 Javascript
JS 获取滚动条高度示例代码
2013/10/24 Javascript
iScroll中事件点击触发两次解决方案
2015/03/11 Javascript
js仿百度登录页实现拖动窗口效果
2016/03/11 Javascript
Node.js中使用jQuery的做法
2016/08/17 Javascript
浅析JavaScript动画模拟拖拽原理
2016/12/09 Javascript
概述jQuery中的ajax方法
2016/12/16 Javascript
教你一步步用jQyery实现轮播器
2016/12/18 Javascript
深入理解JavaScript中的预解析
2017/01/04 Javascript
详解JS中的attribute属性
2017/04/25 Javascript
vue中本地静态图片路径写法
2018/03/06 Javascript
es6新特性之 class 基本用法解析
2018/05/05 Javascript
Vue引入jquery实现平滑滚动到指定位置
2018/05/09 jQuery
vue项目中使用Svg的方法
2018/10/24 Javascript
vue中实现Monaco Editor自定义提示功能
2019/07/05 Javascript
vue循环数组改变点击文字的颜色
2019/10/14 Javascript
[59:48]DOTA2-DPC中国联赛 正赛 VG vs Magma BO3 第一场 1月26日
2021/03/11 DOTA
github配置使用指南
2014/11/18 Python
python安装与使用redis的方法
2016/04/19 Python
python 字符串的驻留机制及优缺点
2020/06/19 Python
详解python 内存优化
2020/08/17 Python
SKECHERS官方旗舰店:美国舒适运动休闲品牌
2017/12/22 全球购物
小学生评语大全
2014/04/18 职场文书
干部选拔任用方案
2014/05/26 职场文书
小学标准化建设汇报材料
2014/08/16 职场文书
法人单位授权委托书范文
2014/10/06 职场文书
2015年保育员个人工作总结
2015/05/13 职场文书
2016年小学“我们的节日·中秋节”活动总结
2016/04/05 职场文书
Python Parser的用法
2021/05/12 Python
Python 详解通过Scrapy框架实现爬取CSDN全站热榜标题热词流程
2021/11/11 Python