利用 Composer 一步一步构建自己的 PHP 框架(四)——使用 ORM

2014-10-16   /   字数:2616   /   阅读数:73661   /   分类: PHP     

本教程示例代码见 https://github.com/johnlui/My-First-Framework-based-on-Composer


回顾

经过前三篇文章 基础准备 、 构建路由 和 设计 MVC ,我们已经得到了一个结构比较完整的 MVC 架构的 PHP 微框架,但是距离一个真正能够上手使用的框架还差一样东西: 数据库封装 ,本篇就将讲述如何集成一个 ORM Composer 包 。

本篇是本系列最后一篇,接下来我可能会以 让我们开了又开的 Composer 包 为系列标题分享一些体验和感悟,将主要发表在本站上。


正文

我们选择 Laravel 的 illuminate/database 作为我们的 ORM 包。我试用了几个著名的 ORM,发现还是 Laravel 的 Eloquent 好用!让我们开心的 ORM,开了又开! :-D

在本系列教程里,每一个 Composer 包都要满足以下基本要求:

  1. 原生依赖 Composer 进行管理

  2. 在好用的基础上尽量简单(比如我们那个超简单的路由包)

  3. 尽量新,用上 PHP 的新特性

说到 PHP 的新特性,有句题外话。 PHP5.3 引入了命名空间,这是规划在 PHP6 中的功能,所以 PHP5.3 在一定程度上其实就是 PHP6 ,PHP 的下一个版本是 PHP7 ,即将发布,主要贡献者是大名鼎鼎的 鸟哥 @Laruence 。另外本台前方记者(就是我)刚刚从微博发来报道,鸟哥正在放大招,制造传说中 PHP7 on JIT ,我大 PHP 的历史车轮是无法阻挡的哈哈哈!:-P

安装 illuminate/database

给 composer.json 增加一个 require 项:

"illuminate/database": "*"

运行 composer update ,等待安装完成。

使用 Eloquent

修改 public/index.php 为:

<?php

use Illuminate\Database\Capsule\Manager as Capsule;

// Autoload 自动载入

require '../vendor/autoload.php';

// Eloquent ORM

$capsule = new Capsule;

$capsule->addConnection(require '../config/database.php');

$capsule->bootEloquent();

// 路由配置

require '../config/routes.php';

新增 config/database.php (注意替换数据库密码):

<?php

return [

  'driver'    => 'mysql',

  'host'      => 'localhost',

  'database'  => 'mffc',

  'username'  => 'root',

  'password'  => 'password',

  'charset'   => 'utf8',

  'collation' => 'utf8_general_ci',

  'prefix'    => ''

  ];

修改 models/Article.php :

<?php

/**

* Article Model

*/

class Article extends Illuminate\Database\Eloquent\Model

{

  public $timestamps = false;

}

controllers/HomeController.php 无需改动。

刷新,页面依旧:

Image

恭喜你!Eloquent 使用成功!

Eloquent 更多用法

Eloquent 异常强大 ,可以说是 Laravel 中 最特别 、 最有价值 的部分。

像 HomeController 中调用的 Article::first() ,之前用了十几行代码,现在什么都不用干,继承一个类就行了。

Eloquent 更多用法参见:Eloquent ORM 中文文档

其他著名 ORM

还有很多著名的 ORM 和 Datamapping(数据库迁移等) 包,参见: ORM and Datamapping

ORM 能够大幅提高提高开发效率,Eloquent 真乃神器也!

虽然 web 届各语言阵营都在不断推出新的所谓 快速开发框架 ,终归还是越来越像 Rails 。Eloquent 在表面上几乎是最像 Rails 的 ORM 的了,但是跟 Rails 不能比啊,Ruby 的超强面向对象特性可不是盖的。Laravel 作者 Taylor Otwell 接受采访时曾表示,Eloquent 是整个 Laravel 中最难实现的部分。我在调试的时候也发现, MFFC/vendor/illuminate/database/Illuminate/Database/Eloquent/Model.php 这个文件有 3000 多行......


目前建造一个丰满的可以上手使用的 PHP 框架的工作就算是基本完成了,接下来我会继续完善 MFFC 框架,让她更加丰富、好用!


以后可能会有 模板引擎、表单验证、发送邮件、权限体系管理、异步队列、视频音频处理(乱入:-D) 等内容,敬请关注还未出世的 让我们开了又开的 Composer 包 系列文章。

谢谢大家的阅读和陪伴!再见!

该项目已经演化成为一个成熟的轻量优雅的 PHP 框架 Pinatra。https://github.com/Pinatra/Pinatra

新文章:利用 Composer 完善自己的 PHP 框架系列

WRITTEN BY

avatar

评论:

兔子
2020-06-19 15:25
想问一下,独立使用Eloquent怎么注册观察者呢?
User::observe(UserObserver::class);貌似不可以
User::updated(function ($user){log(‘updated’);});也不行
protected $dispatchesEvents = [
        'saved' => UserSaved::class,
        'deleted' => UserDeleted::class,
    ];
也不行,通通不会执行
貌似是因为
protected static function registerModelEvent($event, $callback)
    {
        if (isset(static::$dispatcher)) {
            $name = static::class;

            static::$dispatcher->listen("eloquent.{$event}: {$name}", $callback);
        }
    }
但static::$dispatcher从哪来呢,我在官方文档里也没有看到
JohnLui
2020-06-19 15:36
@兔子:观察者依赖 Laravel 核心架构,Dispatch 也只是 Symfony 提供的一个标准化协议,如果想使用观察者,建议直接用 Laravel
兔子
2020-06-19 17:13
@JohnLui:大佬回复真快!!!
1、那您的pinatra现在也是不能做到数据监听吗?
2、如果我坚持这么做那么改写Eloquent的成本或许又太大了
3、既然Eloquent是基于doctrine/dbal实现,那我直接用doctrine/orm是不是也是一个解决方案,毕竟很多微服务不需要整个框架,能访问数据库就可以了(但原生PDO又略简单了),我看了doctrine/orm的文档,应该都没有特殊的外部依赖
JohnLui
2020-06-19 18:55
@兔子:不是改写 Eloquent,是要改造你的框架,最终就会搞出一个 Laravel 来。
Eloquent 不是基于 doctrine 的,这个信息你是从哪里看的.....
兔子
2020-06-19 20:08
@JohnLui:抱歉,我忘记哪里看的了,或许是我看到有依赖就自己臆想的。。。我会加以改正的
另外,我知道我前面为什么没效果了
        $id=UserModel::insertGetId(['name'=>'兔子']);  //无效
        $user=UserModel::find($id);  //有效
        $user->name='小兔子';        
        $user->update();                   //有效

        UserModel::where('id','=',$id)->update(['name'=>'小白兔']);  //无效
        
大概的规律就是除了查询,所有操作都需要实例化模型对象后,里面已经存在数据,操作才有效,但insert比较特别
    1、UserModel::insert($values);
    2、$userModel=new UserModel();$userModel->insert($values);
两者都不行
笑的很甜丶
2019-08-30 16:57
个人觉得laravel的配置放在.env文件中是一个比较前卫的做法。希望博主也能采纳,不过像我这样的人建议多了,那恭喜博主你重新带着我们搭建了一遍laravel。哈哈
小龙
2019-02-17 21:59
多数据库怎么办??
小龙
2018-05-11 16:49
多谢老大,但这个怎么读写分离呢??  Eloquent 怎么读写分离
秃子Sir
2018-02-26 15:00
博主,我用illuminate/database的,我那个模型名字是User 但是它默认去找users表,因为我数据库中的表叫user,所以找不到。您遇到过吗,谢谢。
JohnLui
2018-02-26 15:04
@秃子Sir:可以手动指定表名。
秃子Sir
2018-02-26 15:12
@JohnLui:嗯嗯。博主,我是大学生可能有些知识还很匮乏,这个问题解决了,我比较好奇一个问题哈,就是lavaral中的illuminate/database,是lavaral框架的人自己写的,还是他们集成过来的,还有用不用深究这个illuminate/database啥的,还有就是能不能给我个qq和微信联系方式,有时间好好请教你。
秃子Sir
2018-04-10 16:51
@JohnLui:博主,
怎么解决自动加载的那个类,使用命名空间的问题啊,就是您讲的这个例子,自动加载的类,没有命名空间,那如何才能支持命名空间呢。
lee
2017-04-25 16:51
Fatal error: Uncaught Error: Class 'Illuminate\Database\Capsule\Manager' not found in G:\Lee\phpstudy\laravel\public\index.php:4 Stack trace: #0 {main} thrown in G:\Lee\phpstudy\laravel\public\index.php on line 4


   这是啥错误啊  大佬
taozi
2017-03-15 14:22
请问楼主,如果同时要操作两套数据库怎么解决呢?谢谢
豆豆
2016-11-22 12:07
加上了ORM  , 好像分页不能用
十一
2016-08-27 17:59
orm有了  laravel 的 view 能够单独出来么?
ikodota
2016-07-05 10:53
eloquent 如何使用 master-slaver?
Li
2016-06-03 11:58
博主 单独使用这个包怎么用事务?Laravel中是继承自DB门面的,这包里方法吗
Li
2016-06-03 16:18
@Li:$capsule = new Capsule();
....
$aaa = $capsule->getConnection()->getPdo();

$aaa->beginTransaction();

可以这样开启事务,$capsule这个最好是实例化在一个公用方法中
小龙
2018-05-11 17:03
@Li:是啊,事务兄弟怎么弄?
skylar
2019-04-11 05:13
@小龙:https://github.com/illuminate/database

hi,你好,我也遇到了这个问题,查到这个地方,最后解决了。如果你还需要的。:)
wenco
2019-09-30 09:47
@skylar:所以这个仓库哪里说了关于事务的东西了?
拉风的男人
2016-02-26 22:09
Fatal error: Call to a member function connection() on null in /Users/admin/www/test/vendor/illuminate/database/Eloquent/Model.php on line 3277 这是什么原因导致的呢
summer
2017-12-11 15:52
@拉风的男人:要在路由前面引入Eloquent
例如:
$capsule = new Capsule;
$capsule->addConnection(require dirname(__FILE__).'/config/database.php');
$capsule->bootEloquent();
//路由配置
require 'config/routes.php';
laoyao
2015-12-28 01:13
膜拜
kufrog
2015-11-27 10:35

请教下博主:这个ORM操作数据库和Zend、THINKPHP之类框架的insert select等方法操作差不多,感觉还略繁琐先预赋值后save creat,性能方面差别大?
du5307
2015-09-05 22:29
按着lz的教程做了一遍,真心点赞~灰常感谢~~现在开始下一个系列~
黑板擦
2015-07-13 17:14
为什么要在表后面加s呢
efans
2015-07-08 18:29
请教下,单独使用这个orm的话,如何使用数据库事务?
use Illuminate\Support\Facades\DB;
...
DB::beginTransaction();
...
DB::commit();
这样居然不行,报错
Call to a member function beginTransaction() on a non-object in vendor/illuminate/support/Illuminate/Support/Facades/Facade.php on line 205
skylar
2019-04-11 05:12
@efans:https://github.com/illuminate/database

hi,我也在做这个处理,刚好看到了这个问题的处理。如果还需要的话!~
aha
2015-07-01 12:08
楼主可以用doctrine2来讲讲嘛?
龙圆
2015-05-04 16:56
博主 请问 我执行composer update 怎么就是不行呢?
[Composer\Downloader\TransportException]
The "http://pkg.phpcomposer.com/repo/packagist/p/noahbuscher/macaw.json" file could not be downloaded: failed to open stream: HTTP request failed!
JohnLui
2015-05-04 17:39
@龙圆:中国镜像不稳定
bruce
2015-08-05 13:20
@JohnLui:自从用了日本镜像 稳如狗 不爱国的可以用
roy
2015-04-19 22:49
请教博主:请问rails这么强大,先进,为什么还会出来那么多模仿rails的PHP框架,直接都用rails不就好了吗?模仿的那么累,那么辛苦还是没有rails强大好用。
JohnLui
2015-04-19 22:56
@roy:Rails 强大,但是也有大规模工程化的致命弱点:难于部署、特性过于强大导致极易内存泄露、官方实现质量较差、性能极差导致无法承载大量用户。Rails 走到了“功能强大”的极端。
anxing
2015-01-08 13:53
不知道支持Mongodb 等ODM数据不
JohnLui
2015-01-08 14:29
@anxing:Eloquent 目前支持 MySQL、Postgres、SQL Server、和 SQLite 这四种数据库。需要支持 Mongodb 的话,可以自己找个包接上去用啊~~
Mradxz
2014-12-12 10:54
写的太好了,我照着你的方法 自己弄了个框架
但是 有个疑问就是 orm 这部分 怎么调用 sqlite 和其他类型的数据库呢
我把配置文件 改成了 laravel 里 sqlite 的部分
但是 Call to a member function getConnection() on a non-object 报错
JohnLui
2014-12-12 11:04
@Mradxz:Eloquent 是支持 SQLite 的,目测配置文件出错?注意 config 文件夹下的配置文件被 config/local 文件夹下的配置文件覆盖的问题。
Deben
2014-11-03 23:07
Hi John
请问这个 php 的版本是什么呢?
我照着教程的步骤,会出现错误:
```
Warning: preg_match(): Compilation failed: unmatched parentheses at offset 5 in C:\Users\Deben\Documents\www-myfw\vendor\codingbean\macaw\Macaw.php on line 117
```
并且上一步的路由设置也一定要加 "/" 才行,我的环境是 wamp5,请问你这个 php 是什么版本的呢?
JohnLui
2014-11-04 10:21
@Deben:composer.json 里面写了最低 5.4,低于这个版本composer应该会报错的。
woodstig3
2015-08-18 20:20
@Deben:@Deben Hi,
你的这个问题解决了吗?我也有这个问题,我的PHP是5.6.2版本的。
你好
2015-12-08 16:23
@woodstig3:这个问题解决了吗,亲。
yuanchao
2014-10-29 10:05
您好,我的问题又来了,我在 update 的时候提示
Fatal error: Allowed memory size of 536870912 bytes exhausted (tried to allocate 32 bytes) in phar:///Applications/MAMP/htdocs/composer/composer.phar/src/Composer/DependencyResolver/RuleWatchNode.php on line 40

好像是运行内存不足,但是我在 php.ini 里面,已经给 memory_limit 设置为 1024 了

我的json 文件为
{
  "require": {
      "codingbean/macaw": "dev-master",
      "illuminate/database": "*"
  },
  "autoload": {
    "classmap": [
      "app/controllers",
      "app/models"
    ]
  },
  "repositories": [
        { "packagist": false },
        {
            "type": "composer",
            "url": "http://218.244.132.204/proxy/packagist"
        }
    ]
}

请麻烦帮忙看一下,继续看您的文章学习 ,谢谢
JohnLui
2014-10-29 12:23
@yuanchao:参考这个帖子:http://phphub.org/topics/180
而且你改的php.ini不一定对,看这里:http://segmentfault.com/q/1010000000729459/a-1020000000729473
yuanchao
2014-10-29 14:31
@JohnLui:嗯,经检查,我的php.ini 是设置正确了的,主要的原因是在于,我是通过 composer 下载的 composer.phar ,
然后我通过 curl -O http://getcomposer.org/composer.phar  下载的 这个的时候,一切正常,而且我通过curl 下载的有 1m 多,而在中文网下载的只有 几百 kb ,可能和这个有关系吧,现在使用正常了,谢谢您
JohnLui
2014-10-29 16:11
@yuanchao:不客气。
qqqqq
2016-03-30 18:36
@JohnLui:不错!可惜不理解1
yuanchao
2014-10-27 22:32
再次打扰了,请问,你是如何寻找这些 composer 包的呢?比如这个 ORM ,我想用yii 框架里面的,但是我不知道该怎么样去找,麻烦指点下,谢谢
JohnLui
2014-10-27 23:01
@yuanchao:Yii 应该没有单独放出。著名 PHP 包:https://github.com/ziadoz/awesome-php
ShyBoy
2014-10-27 12:36
看了博主的利用composer搭建框架的教程再学laravel就简单多了。自己也试着用laravel搭建一个博客
逗熊
2014-10-16 17:04
我擦、写的太好了、、让我这没听过composer的渣渣顿时心惊肉跳了、、感谢博主的文章,希望多更新,多帮我等渣渣涨工资啊、、、

发表评论:

© 2011-2024 岁寒  |  Powered by Emlog