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 相关文章推荐
Oracle Faq(Oracle的版本)
Oct 09 PHP
Get或Post提交值的非法数据处理
Oct 09 PHP
图片存储与浏览一例(Linux+Apache+PHP+MySQL)
Oct 09 PHP
PHP新手上路(三)
Oct 09 PHP
利用PHP制作简单的内容采集器的原理分析
Oct 01 PHP
PHP缓存技术的使用说明
Aug 06 PHP
ThinkPHP Mobile使用方法简明教程
Jun 18 PHP
php获取字符串中各个字符出现次数的方法
Feb 23 PHP
PHP中strnatcmp()函数“自然排序算法”进行字符串比较用法分析(对比strcmp函数)
Jan 07 PHP
PHP中header函数的用法及其注意事项详解
Jun 13 PHP
php用wangeditor3实现图片上传功能
Aug 22 PHP
PHP如何使用cURL实现Get和Post请求
Jul 11 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
php单例模式实现(对象只被创建一次)
2012/12/05 PHP
PHP实现今天是星期几的几种写法
2013/09/26 PHP
PHP中source #N问题的解决方法
2014/01/27 PHP
php抽象类使用要点与注意事项分析
2015/02/09 PHP
[原创]php正则删除img标签的方法示例
2017/05/27 PHP
JQUERY 浏览器判断实现函数
2009/08/20 Javascript
Jquery拖拽并简单保存的实现代码
2010/11/28 Javascript
js事件(Event)知识整理
2012/10/11 Javascript
Jquery实现侧边栏跟随滚动条固定(兼容IE6)
2014/04/02 Javascript
JavaScript使用RegExp进行正则匹配的方法
2015/07/11 Javascript
谈谈JavaScript自定义回调函数
2015/10/18 Javascript
深入理解JS addLoadEvent函数
2016/05/20 Javascript
Jquery组件easyUi实现手风琴(折叠面板)示例
2016/08/23 Javascript
jQuery的deferred对象使用详解
2016/09/25 Javascript
微信小程序开发之圆形菜单 仿建行圆形菜单实例
2016/12/12 Javascript
基于Vue实现timepicker
2017/04/25 Javascript
angular或者js怎么确定选中ul中的哪几个li
2017/08/16 Javascript
详解ES6 Fetch API HTTP请求实用指南
2018/11/14 Javascript
Python中replace方法实例分析
2014/08/20 Python
修改Python的pyxmpp2中的主循环使其提高性能
2015/04/24 Python
Django中模型Model添加JSON类型字段的方法
2015/06/17 Python
利用python获取当前日期前后N天或N月日期的方法示例
2017/07/30 Python
python 构造三维全零数组的方法
2018/11/12 Python
Python编程快速上手——疯狂填词程序实现方法分析
2020/02/29 Python
前端面试必备之html5的新特性
2017/09/05 HTML / CSS
HTML5新特性 多线程(Worker SharedWorker)
2017/04/24 HTML / CSS
北美主要的汽车零部件零售商:AutoShack.com
2019/02/23 全球购物
瑞典在互联网上最大的宠物商店:Animail
2020/10/31 全球购物
Linux面试经常问的文件系统操作命令
2015/11/05 面试题
信息专业大学生自我评价分享
2014/01/17 职场文书
班组拓展活动方案
2014/08/14 职场文书
公司经营目标责任书
2015/01/29 职场文书
回复函格式及范文
2015/07/14 职场文书
小学数学教师研修感悟
2015/11/18 职场文书
《暗黑破坏神2:重制版》本周进行第一轮A测 目前可官网进行申请报名
2021/04/07 其他游戏
python如何进行基准测试
2021/04/26 Python