BT

如何利用碎片时间提升技术认知与能力? 点击获取答案

arrayDB,全新而且简单的PHP ORM库

| 作者 Mustafa Dokumacı 关注 0 他的粉丝 ,译者 雷慈祥 关注 1 他的粉丝 发布于 2012年10月27日. 估计阅读时间: 16 分钟 | Google、Facebook、Pinterest、阿里、腾讯 等顶尖技术团队的上百个可供参考的架构实例!

我见过许多PHP ORM库。它们中大多数都要你为想保存在数据库里的每一项写一个类。无缘无故地继承这个、继承那个,而那些内容通常都是重复和反复无常的。

既然条目包含相似数据类型以及相似关系的字段,一个编写良好的类就可适用于所有情况。如果你需要一个库来简化这些事情,这就是我的方法。

arrayDB ORM库只包含5个类。你基本上只使用其中一个,而其余类则在内部使用,仅此而已。缓存及其与数据库之间的同步全是自动的,你无需对其进行跟踪。

要开始使用这个库,你只需简单地定义:

  • 你的数据模型(你需要保存哪几项,他们的字段以及字段间的关系)。
  • 你的MySQL连接方式。
  • 你的缓存配置。

定义数据模型

所有的数据模型定义被写成像这样的数组:

    $model=array(
        'user'=>array(
            'conf'=>array('len'=>7),
            'fields'=>array(
                'name'=>array('len'=>50)
            ),
            'has_many'=>array(
                'posts'=>array('type'=>'post', 
'foreign_name'=>'writer')
            ),
            'many_to_many'=>array(
                'liked_posts'=>array('type'=>'post', 
'foreign_name'=>'likers'),
            ),
            'self_ref'=>array('friends')
        ),

        'post'=>array(
            'conf'=>array('len'=>10),
            'fields'=>array(
                'text'=>array('len'=>200),
                'view_count'=>array('type'=>'numeric', 'len'=>5)
                // 默认的字段类型是text,这里将类型定义成numeric
            )
        )
    );

这里我们有两张表:用户和帖子。

用户有姓名,有些用户发帖子而有些用户关注帖子。帖子有文本内容,浏览量以及关注者。

用户还有其他许多用户作为好友。

使用这个模型,我们想通过$user['posts']获取用户发布的所有帖子,通过$post['writer']获取帖子的作者。这是一对多关系。

我们还想通过$user['liked_posts']获取用户关注过的帖子,通过$post['likers']获取帖子的关注者。这是多对多关系。

最后我们想通过$user['friends']获取用户的好友列表。这是自引用关系。

定义MySQL连接方式

定义MySQL连接方式也写成一个像这样的数组:

    $db_config=array(
        'hostname'=>'localhost', 'database'=>'social', 
'username'=>'root', 'password'=>''
    );

定义缓存配置

目前,我们有三种缓存类型实现:APC、Memcached以及普通文本文件。 要使用APC,这样的配置数组就够了:

    $cache_config=array('type'=>'apc');

要使用Memcached,你需要提供一些参数:

    $cache_config=array('type'=>'memcached', 'host'=>'127.0.0.1', 
'port'=>11211, 'timeout'=>1);

要使用普通文本文件,你需要创建一个可读可写的目录并提供其绝对路径:

    $cache_config=array('type'=>'file', 'path'=>'/tmp/my_project_cache')

还有一个可选参数“prefix”。如果给定,它将用作缓存的键名。

开始使用

现在是时候使用那些我们定义过的数据了。初始化该库,我们只需要这几行代码。

    DB::init($db_config);
    CACHE::init($cache_config);

    ADB::init($model);
    $adb=ADB::get_instance();

创建表

这项任务只需执行一次。我们告诉库去创建所需的数据库表。它就会负责完成关系等相关的复杂工作。

    $adb->create_tables();

我们只需在发布的时候执行该方法一次。如果在插入数据之后,调用该方法将导致数据丢失。

使用记录

我们手头拥有这个$adb实例。我们将通过它来获取所有数据。

创建记录

我们提供表名和由字段名称及数据组成的键值对数组来创建一条记录。

    $uid1=$adb->create('user', array('name'=>'John'));
    $uid2=$adb->create('user', array('name'=>'Marry'));

    $pid1=$adb->create('post', array(
        'writer'=>$uid1,
        'text'=>'What a wonderful world!'
    ));

    $pid2=$adb->create('post', array(
        'writer'=>$uid2,
        'text'=>'Life is beautiful!'
    ));

创建多对多关系

第一个参数是表名。第二个参数是被关联记录的局部名称。第三个参数是记录的ID,第三个参数是被关联记录的ID。

    $adb->relate('user', 'friends', $uid1, $uid2);

    $adb->relate('user', 'liked_posts', $uid1, $pid1); // 关注自己的帖子 :)
    $adb->relate('user', 'liked_posts', $uid1, $pid2);

    $adb->relate('user', 'liked_posts', $uid2, $pid1);

列举数据

我们可在一个简单的循环中列举所有写过帖子的用户以及帖子的关注者:

    foreach ($adb->id_list('user') as $uid) {
        // load user
        $user=$adb->load('user', $uid);
        echo '<h1>' . $user['name'] . '</h1>' . "\n";

        echo '<h2>Posts: </h2>' . "\n";
        echo '<ul>' . "\n";

        foreach ($user['posts'] as $pid) {
                //load post of user
                $post=$adb->load('post', $pid);
                $likers=array();

                foreach ($post['likers'] as $lid) {
                    // load liker of post
                    $liker=$adb->load('user', $lid);
                    $likers[]=$liker['name'];
                }
                $likers=(count($likers)) ? '<br />' . implode(', ', 
$likers) . ' liked.' : '';
                echo '<li>' . $post['text'] . ' ' . $likers . '</li>' . 
"\n";
            }

            echo '</ul>' . "\n";
        }

更新记录

我们能够像下面这样更新任意一个记录:

    $user1=$adb->load('user', $uid1);
    $user1['name']='Jack';
    // 无需调用任何保存方法,保存以及缓存的同步更新全是自动的。

如果我们需要一次更新多个字段,这是另一种方法:

    $post1=$adb->load('post', $pid1);
    $post1->update(array('writer'=>$uid2, 'text'=>'Not a wonderful 
world!'));

删除关联

这和创建关联一样:

    $adb->unrelate('user', 'friends', $uid1, $uid2);
    $adb->unrelate('user', 'liked_posts', $uid1, $pid1);

删除记录

我们可以删除记录,同时保存或删除与该记录相关联的数据。

    $adb->delete('user', $uid1);
    // 用户删掉了,帖子成为匿名的了。

    $adb->delete('user', $uid1, true);
    // 用户以及用户的帖子都删掉了。

查询更多

作为示例,我想获得最受关注的5篇帖子。如下是我们所有要做的:

    foreach ($adb->id_list('post', false, 'likers DESC', 5) as $pid) {
        $post=$adb->load('post', $pid);
        // 可对帖子做任何操作
    }

抑或是我们想要获取用户被关注次数超过5次的所有帖子,我们可以执行以下操作:

    $user=$adb->load('user', $uid1);
    foreach ($user->id_list('post', 'view_count>5') as $pid) {
        $post=$adb->load('post', $pid);
        // 可对帖子做任何操作
    }

主要目标

对于单独的帖子页面,我们的代码将会是这么简单:

    $post=$adb->load('post', $pid1);
    $writer=$adb->load('user', $post['writer']);

    echo $writer['name'] . ' wrote' . "<br />\n";
    echo $post['text'] . "<br />\n";

    $post['view_count']++;
    // 是的,增大浏览量就是这么简单

这些代码里有任何查询或者缓存逻辑吗?没有,主要目标是保持简单。

市面上有很多著名的替代产品。他们文档完备,支持得也更好。该库不是他们中的一员,它目前还不是一部状态良好的机器。在我看来,这是最简单且容易上手的方法。如果ORM库的目的是为了让编码人员不用关心数据库逻辑,这个库是其他新兴库中最自信的一个。jQuery是最简单的javascript框架,也因此成了标准。所以,易于使用的PHP ORM库也有这样的机会。

这个库的下载地址:[arrayDB github]

欢迎提出意见和建议。

关于作者

Mustafa Dokumaci是一位来自土耳其伊斯坦布尔的软件工程师。他的专业是环境工程和会计学,但他目前就职于sporcum.com和hipsin.com。Mustafa拥有六年的PHP、MySQL、Apache、Nginx、Python、CodeIgniter、Magento等的使用经验。
 

 

查看英文原文arrayDB, a New and Easy PHP ORM


感谢侯伯薇对本文的审校。

给InfoQ中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家通过新浪微博(@InfoQ)或者腾讯微博(@InfoQ)关注我们,并与我们的编辑和其他读者朋友交流。

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

不怎么样 by yi yang

读了下代码,完全没什么看头,看到前头那坨配置就没胃口,这种文章完全是降了infoQ的档次哈

不能光说不练,放个我写的datamapper实现:
github.com/yeaha/Lysine2/blob/master/src/datama...

Re: 不怎么样 by 雷 慈祥

如果有翻译的问题?还请指正
关于库的问题,也可直接在github上和原作者讨教或pk,呵呵。

Re: 不怎么样 by yi yang

没说清楚,不是指您的翻译质量,是说这篇文章本身的内容
英语太差,没法跟老外pk,只能在中文站发发感叹而已,:)

定义数据模型太繁琐 by 钱 浩

用POJO多方便。。。。没必要自己设计一套蹩脚的映射规则

一直觉得php 的 Array生成map写法没有Ruby的美感 by a ilangg

Ruby的是:=>,简洁美观。php的到处是array()

这个框架只简化了数组的重复操作 by Wang Qunqiang

有很多问题需要考虑, 持久化的性能,占用的内存大小, 这些方面在未读过代码之前,仅做怀疑。

Re: 不怎么样 by Wang Qunqiang

这。。。。 yi yang 好谦虚

Re: 不怎么样 by yi yang

这玩意太勾引我的吐槽欲望了
当时看了文章就去github读代码,读完就回头来吐了一句槽
木有测试用例、只支持mysql、只支持单个库、设计毫无亮点、对象之间严重耦合无法替换、代无注释,等等...
这要是个人自娱自乐,小范围秀一下也无伤大雅
放出来见人至少注释该简单写几句吧

Re: 不怎么样 by Wang Qunqiang

lol, 或许下次我自己放我的代码会注意的。

Re: 一直觉得php 的 Array生成map写法没有Ruby的美感 by 李 惟

萝卜白菜各有所爱,ruby不一定是最简洁的

谁能告诉我什么是arrayDB ORM库? by 李 惟

谁能告诉我什么是arrayDB ORM库?没接触过,做什么用的?

Re: 不怎么样 by 李 惟

你这个有什么用?求教。Lysine2是做什么的?

Re: 不怎么样 by yi yang

Lysine是我自写自用的框架而已,因为没文档、没测试用例、没几个典型的example,所以它很好用这种话我就不能到处乱说。

Re: 不怎么样 by yong leo

你写的Lysine2是个啥玩意儿?

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

14 讨论

登陆InfoQ,与你最关心的话题互动。


找回密码....

Follow

关注你最喜爱的话题和作者

快速浏览网站内你所感兴趣话题的精选内容。

Like

内容自由定制

选择想要阅读的主题和喜爱的作者定制自己的新闻源。

Notifications

获取更新

设置通知机制以获取内容更新对您而言是否重要

BT