前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >基于独立的 Laravel Eloquent 组件编写 ORM 模型类

基于独立的 Laravel Eloquent 组件编写 ORM 模型类

作者头像
学院君
发布2020-08-27 12:06:53
1.9K0
发布2020-08-27 12:06:53
举报
文章被收录于专栏:学院君的专栏学院君的专栏

ORM 及其实现模式

接下来我们来看看如何实现 MVC 模式中的 M,即模型类。

模型类负责与数据库进行交互,这里的模型指的是数据表的模型,一个模型类对应一张数据表,数据表的字段会映射为模型类的属性,我们可以通过模型类提供的方法实现对应数据表记录的增删改查,这样一来,我们就将原来面向过程的数据库操作转化为面向对象风格的编程,将对数据表的 SQL 执行转化为对模型类的方法调用。

我们把这种对象与数据表的映射称之为对象关系映射(Object Relational Mapping),简称 ORM。ORM 两种最常见的实现方式是 Active Record 和 Data Mapper,Active Record 尤其流行,在很多框架中都能看到它的身影,比如 Laravel 框架使用的 Eloquent ORM 使用的就是 Active Record 模式,而 Symfony 框架使用的 Doctrine ORM 使用的则是 Data Mapper 模式。

两者的主要区别是:

  • 在 Active Record 模式中,模型类与数据表一一对应,一个模型实例对应一行数据表记录,操作模型实例等同于操作表记录;
  • 而在 Data Mapper 模式中,业务领域(Domain)和数据持久层是完全分离的,模型类操作与数据表更新之间通过 EntityManager 来维护,上层操作的模型类完全不需要和数据库有任何关联。

所以 Active Record 模式更加简单,容易上手,但是与数据库的直接关联使其性能和灵活性不及 Data Mapper 模式,但是相对的,Data Mapper 模式理解和实现起来更加复杂,不利于快速上手。

这里,我们选择使用更加简单的 Active Record 模式来实现 ORM 模型类,并且为了简化流程,我们直接基于 Laravel 框架的 Eloquent ORM 组件来编写,就不再重复造轮子了。

下载 Eloquent ORM 相关扩展包

Eloquent ORM 作为 Laravel 框架自带的 ORM 实现,还可以在 Laravel 框架之外作为独立的 ORM 组件使用。在我们这里的博客应用项目中,可以通过 Composer 在根目录下运行如下命令下载对应的 Eloquent ORM 扩展包:

代码语言:javascript
复制
composer require illuminate/database

为了能够正常使用 Eloquent 提供的模型事件功能,还可以下载 Laravel 提供的独立事件扩展包:

代码语言:javascript
复制
composer require illuminate/events

上述扩展包下载完成后,就可以在博客项目根目录下的 vendor 目录中看到对应的扩展包了:

进入 vendor/illuminate/database,可以通过阅读 README.md 文件查看如何使用独立的 Eloquent ORM 组件,接下来,我们将参照这个文档介绍来编写博客项目的模型类实现。

初始化数据库连接

首先我们在 app/bootstrap.php 中引入 Eloquent ORM 的 Capsule 类完成数据库连接初始化,在此之前,先在配置文件 config/app.php 中调整数据库连接配置符合 Eloquent 约定:

代码语言:javascript
复制
'mysql' => [
    'driver' => 'mysql',
    'host' => '127.0.0.1',
    'port' => 3306,
    'database' => 'blog',
    'username' => 'root',
    'password' => 'root',
    'charset' => 'utf8mb4',
    'collation' => 'utf8mb4_general_ci',
    'prefix'    => '',
]

然后在 bootstrap.php 中新增一个 initDatabase 方法基于 Capsule Manager 初始化数据库连接:

代码语言:javascript
复制
use Illuminate\Database\Capsule\Manager as Capsule;
use Illuminate\Events\Dispatcher;
use Illuminate\Container\Container as IlluminateContainer;

function initDatabase(Container $container)
{
    $capsule = new Capsule();
    $dbConfig = $container->resolve('app.store');
    $capsule->addConnection($dbConfig['drivers'][$dbConfig['default']]);
    $capsule->setEventDispatcher(new Dispatcher(new IlluminateContainer));
    $capsule->setAsGlobal();
    $capsule->bootEloquent();
}

并设置事件分发器,启动 Eloquent 模型类全局可用(为了编写 Eloquent 模型类,如果只是使用 Laravel 提供的数据库查询构建器功能,则不需要这些操作)。最后不要忘了在 bootApp 方法中调用这个方法:

代码语言:javascript
复制
function bootApp(Container $container)
{
    ...
    initDatabase($container);
    return $container;
}

基于 Eloquent 基类编写模型类

在应用启动阶段完成以上初始化操作后,就可以基于 Eloquent ORM 编写模型类了,目前博客项目包含了两张数据表 —— postsalbums

我们可以分别为其编写模型类 Post

代码语言:javascript
复制
<?php
namespace App\Model;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    public $timestamps = false;

    public function album()
    {
        return $this->belongsTo(Album::class);
    }
}

Album

代码语言:javascript
复制
<?php
namespace App\Model;

use Illuminate\Database\Eloquent\Model;

class Album extends Model
{
    public $timestamps = false;

    public function posts()
    {
        return $this->hasMany(Post::class);
    }
}

这两个模型类分别存放在 app/model 目录下的 Post.phpAlbum.php 中,它们继承了 Eloquent ORM 的模型类基类 Model,这样就可以使用 Eloquent 模型类支持的属性和方法。

这里,我们通过设置 $timestamps 属性为 false 表示禁用 Eloquent 模型类自动维护时间字段机制。然后在 Post 类中通过 album() 方法定义某个 Post 模型实例归属于 Album 模型实例(通过 album_id 字段),而在 Album 类中通过 posts() 方法定义一个 Album 模型实例可能包含多个 Post 模型实例(一对多关联),这种关联关系与数据表记录的关联关系对应,具体细节可以参考 Eloquent 官方文档,这里不详细展开了。

重构博客项目数据库操作代码

编写好模型类之后,我们来重构博客项目中之前的数据库交互代码,改为通过模型类获取:

代码语言:javascript
复制
class HomeController extends Controller
{
    public function index()
    {
        $albums = Album::all()->toArray();
        ...
    }
}

class AlbumController extends Controller
{
    public function list()
    {
        ...
        $album = Album::with('posts')->findOrFail($id)->toArray();
        $posts = $album['posts'];
        ...
    }
}

class PostController extends Controller
{
    public function show()
    {
        ...
        $post = Post::with('album')->findOrFail($id)->toArray();
        ...
        $album = $post['album'];
        ...
    }
}

这里的模型类方法和关联查询都可以在 Eloquent 官方文档查询到,这里不详细介绍了,需要注意的是,我们之前在视图模板中都是通过关联数组获取数据库查询结果,这里为了避免重构视图层代码,直接在查询结果上调用 toArray 方法将其转化为数组格式。

完成以上重构后,运行 composer dump-auto 更新自动加载文件,让新增命名空间与目录路径映射关系生效,访问博客应用,首页、专辑页、文章页显示正常,表明代码重构成功。

注:本篇教程源码可以在 Github 获取:https://github.com/nonfu/master-laravel-code/tree/v0.9/practice/blog

小结

至此,我们就完成了 MVC 模式在博客应用中的落地,下篇教程,我们将探索如何通过现代工程化的方式管理前端资源和依赖,我们将引入 NPM、Webpack、Laravel Mix、jQuery 和 Bootstrap,并基于这些工具和框架替换博客应用主题。

(全文完)

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-08-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 极客书房 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ORM 及其实现模式
  • 下载 Eloquent ORM 相关扩展包
  • 初始化数据库连接
  • 基于 Eloquent 基类编写模型类
  • 重构博客项目数据库操作代码
  • 小结
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档