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 相关文章推荐
模拟SQLSERVER的两个函数:dateadd(),datediff()
Oct 09 PHP
默默简单的写了一个模板引擎
Jan 02 PHP
海河写的 Discuz论坛帖子调用js的php代码
Aug 23 PHP
php whois查询API制作方法
Jun 23 PHP
smarty中js的调用方法示例
Oct 27 PHP
php强制运行广告的方法
Dec 01 PHP
Zend Framework动作助手Redirector用法实例详解
Mar 05 PHP
PHP接口并发测试的方法(推荐)
Dec 15 PHP
PHP静态成员变量和非静态成员变量详解
Feb 14 PHP
PHPTree――php快速生成无限级分类
Mar 30 PHP
php + ajax 实现的写入数据库操作简单示例
May 16 PHP
linux mint下安装phpstorm2020包括JDK部分的教程详解
Sep 17 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文件上传实例详解!!!
2007/01/02 PHP
PHP 递归效率分析
2009/11/24 PHP
PHP读取文件内容后清空文件示例代码
2014/03/18 PHP
从刷票了解获得客户端IP的方法
2015/09/21 PHP
PHP CURL或file_get_contents获取网页标题的代码及两者效率的稳定性问题
2015/11/30 PHP
Laravel 之url参数,获取路由参数的例子
2019/10/21 PHP
PHP 数组操作详解【遍历、指针、函数等】
2020/05/13 PHP
phpstudy2020搭建站点的实现示例
2020/10/30 PHP
JavaScript数组函数unshift、shift、pop、push使用实例
2014/08/27 Javascript
JS实现横向与竖向两个选项卡Tab联动的方法
2015/09/27 Javascript
javascript DIV实现跟随鼠标移动
2020/03/19 Javascript
prototype与__proto__区别详细介绍
2017/01/09 Javascript
如何在vue中使用ts的示例代码
2018/02/28 Javascript
js闭包学习心得总结
2018/04/17 Javascript
vue左右侧联动滚动的实现代码
2018/06/06 Javascript
详解JS转换数值函数Number()、parseInt()、parseFloat()
2018/08/24 Javascript
使用Sonarqube扫描Javascript代码的示例
2018/12/26 Javascript
微信 jssdk 签名错误invalid signature的解决方法
2019/01/14 Javascript
Vue-CLI 3.X 部署项目至生产服务器的方法
2019/03/22 Javascript
在 Vue 中使用 JSX 及使用它的原因浅析
2020/02/10 Javascript
详解React 条件渲染
2020/07/08 Javascript
[02:23]2016国际邀请赛中国区预选赛wings晋级之路
2016/06/29 DOTA
pymongo为mongodb数据库添加索引的方法
2015/05/11 Python
python寻找list中最大值、最小值并返回其所在位置的方法
2018/06/27 Python
Python使用正则表达式分割字符串的实现方法
2019/07/16 Python
在Django下测试与调试REST API的方法详解
2019/08/29 Python
python发qq消息轰炸虐狗好友思路详解(完整代码)
2020/02/15 Python
浅谈Python 钉钉报警必备知识系统讲解
2020/08/17 Python
基于Html5实现的react拖拽排序组件示例
2018/08/13 HTML / CSS
Agoda台湾官网:国内外订房2折起
2018/03/20 全球购物
Regatta官网:英国最受欢迎的户外服装和鞋类品牌
2019/05/01 全球购物
怎样声明子类
2013/07/02 面试题
美术师范毕业生自荐信
2013/11/16 职场文书
师范学院美术系毕业生自我鉴定
2014/01/29 职场文书
夜不归宿检讨书
2014/02/25 职场文书
Windows server 2003卸载和安装IIS的图文教程
2022/07/15 Servers