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执行zip与rar解压缩方法实现代码
Dec 05 PHP
基于PHP 面向对象之成员方法详解
May 04 PHP
PHP连接MSSQL2008/2005数据库(SQLSRV)配置实例
Oct 22 PHP
PHP文件上传判断file是否己选择上传文件的方法
Nov 10 PHP
ThinkPHP采用原生query实现关联查询left join实例
Dec 02 PHP
php使用gzip压缩传输js和css文件的方法
Jul 29 PHP
Thinkphp无限级分类代码
Nov 11 PHP
详解PHP匿名函数与注意事项
Mar 29 PHP
thinkphp Apache配置重启Apache1 restart 出错解决办法
Feb 15 PHP
Laravel学习基础之migrate的使用教程
Oct 11 PHP
swoole_process实现进程池的方法示例
Oct 29 PHP
ThinkPHP6.0如何利用自定义验证规则规范的实现登陆
Dec 16 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
phpmyadmin config.inc.php配置示例
2013/08/27 PHP
用php简单实现加减乘除计算器
2014/01/06 PHP
yii2.0使用Plupload实现带缩放功能的多图上传
2015/12/22 PHP
PHP编程实现多维数组按照某个键值排序的方法小结【2种方法】
2017/04/27 PHP
Laravel 实现Controller向blade前台模板赋值的四种方式小结
2019/10/22 PHP
PHP 实现重载
2021/03/09 PHP
jquery ui dialog ie8出现滚动条的解决方法
2010/12/06 Javascript
jquery三个关闭弹出层的小示例
2013/11/05 Javascript
javascript将数字转换整数金额大写的方法
2015/01/27 Javascript
JS数组合并push与concat区别分析
2015/12/17 Javascript
浅析JavaScript声明变量
2015/12/21 Javascript
CKEditor无法验证的解决方案(js验证+jQuery Validate验证)
2016/05/09 Javascript
jQuery ajax全局函数处理session过期后的ajax跳转问题
2016/06/03 Javascript
setTimeout学习小结
2017/02/08 Javascript
H5手机端多文件上传预览插件
2017/04/21 Javascript
js 获取html5的data属性实现方法
2017/07/28 Javascript
vue-cli脚手架引入图片的几种方法总结
2018/03/13 Javascript
elementUI vue this.$confirm 和el-dialog 弹出框 移动 示例demo
2019/07/03 Javascript
详解vue-video-player使用心得(兼容m3u8)
2019/08/23 Javascript
如何利用JavaScript编写更好的条件语句详解
2020/08/10 Javascript
vue设置全局访问接口API地址操作
2020/08/14 Javascript
Python3 Random模块代码详解
2017/12/04 Python
python使用pil库实现图片合成实例代码
2018/01/20 Python
Tensorflow 利用tf.contrib.learn建立输入函数的方法
2018/02/08 Python
在python中实现强制关闭线程的示例
2019/01/22 Python
Python 3.6打包成EXE可执行程序的实现
2019/10/18 Python
Python读取YAML文件过程详解
2019/12/30 Python
Python 实现使用空值进行赋值 None
2020/03/12 Python
Python爬虫实例——scrapy框架爬取拉勾网招聘信息
2020/07/14 Python
为你的html5网页添加音效示例
2014/04/03 HTML / CSS
HTML文本属性&颜色控制属性的实现
2019/12/17 HTML / CSS
皮姆斯勒语言学习:Pimsleur Language Programs
2018/06/30 全球购物
linux面试题参考答案(6)
2016/06/23 面试题
《阳光》教学反思
2014/02/23 职场文书
信息服务专业毕业生求职信
2014/03/02 职场文书
“四风”问题对照检查材料思想汇报
2014/09/16 职场文书