eden / postgre
Eden PostGreSQL 搜索、集合、模型 ORM 组件
Requires
- php: >=5.4.1
- eden/array: 4.*
- eden/collection: 4.*
- eden/core: 4.*
- eden/model: 4.*
- eden/sql: 4.*
- eden/string: 4.*
README
====
安装
composer install eden/postgre
====
简介
Eden 的 PostGreSQL 对象绝对令人惊叹!我们让 ORM 升到了一个新的高度,包括搜索、集合和模型,适合初学者和爱好者。在我们深入这些高级主题之前,我们首先应该回顾一下可用的基本方法。首先,我们需要向图 1 中所示的数据库模型添加连接信息。
图 1. 数据库连接信息
$database = eden('postgre', '[HOST]' ,'[DBNAME]', '[USER]', '[PASS]'); //instantiate
简单来说,我们首先实例化类,在上面的图中提供主机、数据库名称、用户名和密码。没有其他要求,您可以直接开始使用方法。
注意 Eden 的 PostGreSQL 对象仅在执行第一次查询时连接。这种策略称为延迟加载。
基本查询
在非常低的级别,可以调用如图 2 所示的原始查询。
图 2. 原始查询
$database->query('SELECT * FROM user'); // returns results of raw queries
Eden 的 PostGreSQL 对象使用 PDO 与您的数据库通信。我们建议您绑定来自最终用户的输入变量。仍然在低级别,这可以在图 3 中实现。
图 3. 原始绑定
$query = 'SELECT * FROM user WHERE user_name LIKE :user_name AND user_active = :user_active';
$bind = array(':user_name' => '%'.$userName.'%', ':user_active' => 1);
$database->query($query, $bind); // returns results of raw queries
上图将 $query
设置为包含绑定占位符 :user_name
和 :user_active
的字符串。$bind
包含这些占位符的实际值,应在执行查询时替换这些值。我们鼓励这种方法,因为绑定值可以防止数据库注入。
注意:绑定变量必须以冒号(:)开头。
====
数据操作
如果您更喜欢使用 ORM 方法来保存数据,图 4 提供了几个如何实现此目的的方法示例。
图 4. 数据操作
$settings = array(
'user_name' => 'Chris'
'user_email' => 'myemail@mail.com');
$filter[] = array('user_id=%s', 1);
// inserts row into 'user' table
$database->insertRow('user', $settings);
// updates rows in 'user' table where user_id is
$database->updateRows('user', $settings, $filter);
// delete rows in 'user' table where user_id is 1
$database->deleteRows('user', $filter);
//updates data if there is a user_email with the value of anemail@gmail.com otherwise will insert
$database->setRow('user', 'user_email', 'anemail@gmail.com', $settings);
插入数据相当简单。我们包括了两种插入数据的方式。像 getRow() 一样,不需要担心绑定数据,因为 Eden 会为您做这件事。图 4 显示了提到的两种插入方式。
图 4. 两种插入方式
$settings = array('user_name' => 'Chris', 'user_email' => 'myemail@mail.com');
$database->insertRow('user', $settings); // inserts row into 'user' table
$settings = array();
$settings[] = array('user_name' => 'Chris', 'user_email' => 'myemail@mail.com');
$settings[] = array('user_name' => 'Dan', 'user_email' => 'myemail2@mail.com');
$settings[] = array('user_name' => 'Clark', 'user_email' => 'myemail3@mail.com');
$database->insertRows('user', $settings); // inserts multiple rows into 'user' table
显然,如果您只想插入一行,应该使用 insertRow()
。如果您想同时插入两行或多行,应使用 insertRows()
。该方法期望一个数组数组或数组表。
注意:使用 Eden 时,程序员中常见的错误之一是简单地使用
insertRows()
而不是insertRow()
。
注意:使用模型和集合,您实际上不必担心此方法,因为它在集合或模型对象的
save()
方法中已涵盖。我们将在本节后面介绍模型和集合。
更新与插入一样简单。
图 5. 更新
$settings = array('user_name' => 'Chris', 'user_email' => 'myemail@mail.com');
$filter[] = array('user_id=%s', 1);
$database->updateRows('user', $settings, $filter); // inserts row into 'user' table
一个常见的场景是当您需要插入一个不存在列值时,或者更新它时。我们添加了一个名为 setRow()
的额外方法,以简化重复的冗余代码。
图 6. 插入或更新
$settings = array('user_name' => 'Chris2', 'user_email' => 'myemail@mail.com');
$database->setRow('user', 'user_email', 'myemail@mail.com', $settings);
图 6 基本上表示,在用户表中,如果 myemail@mail.com
存在于 user_email
列中,则更新该行。如果不在此列中,则插入。
图 7. 删除
$filter[] = array('user_id=%s', 1);
$database->deleteRows('user', $filter); // delete rows in 'user' table where user_id is 1
====
搜索
使用 Eden 的搜索对象构建复杂查询的更好方法是。图 8 中可以找到概述示例。
图8. PostGreSQL搜索
$database
->search('user')
->setColumns('*')
->innerJoinOn('group', 'group_owner=user_id')
->leftJoinUsing('friends', 'user_id')
->filterByUserName('Chris')
->addFilter("user_last LIKE '%s%%'", 'Brown')
->sortByUserId('ASC')
->addSort('user_last', 'DESC')
->setRange(25)
->setStart(75)
->getRows();
在上面的图中,有几个方法被赋予了魔法,但我们将从头开始。首先,要实例化搜索对象,您只需调用search()
方法,传入表名作为参数。其次,我们调用setColumns()
。此调用是可选的,但如果使用,可以接受一个列数组或列的分隔列表,例如setColumns('user_id', 'user_name')
。接下来,innerJoinOn()
是我们接受连接的新方法。有八种方法专门用于不同类型的连接。
连接方法类型
innerJoinOn()
innerJoinUsing()
leftJoinOn()
leftJoinUsing()
rightJoinOn()
rightJoinUsing()
outerJoinOn()
outerJoinUsing()
无论您选择上述哪种方法,您都需要添加两个参数。第一个参数是要连接的表名,第二个参数是它们之间的关系。
第一个被魔法赋予的方法称为filterByUserName()
。在PostGreSQL类中并没有真正的filterByUserName()
方法。相反,当此函数被调用时,它将解析方法名称并识别出UserName是列名,并将其转换为addFilter('user_name=%s', 'Chris')
,如图8
所示。
addFilter()
通常接受两个参数。第一个参数是过滤器子句。如果您注意到我们在图8
中的过滤器示例中使用了%s来分隔绑定值。您可以根据需要为每个过滤器添加任意数量的绑定值。以下参数需要按过滤器子句中出现的顺序包含绑定值。
第二个被魔法赋予的方法是sortByUserId('ASC')
。在PostGreSQL类中没有真正的sortByUserId('ASC')
方法。相反,当此函数被调用时,它将解析方法名称并识别出UserId是列名,并将其转换为addSort('user_id', 'ASC')
,如图8
所示。
还有三种分页方法可供使用
分页方法
setRange(75)
setStart(25)
setPage(1)
如果您打算使用setPage(1)
,则首先调用setRange(75)
很重要,因为底层函数简单地根据范围计算起始索引。其他两个在图8
中没有涉及的方法是分组和将表设置为其他内容的能力。
图9. 其他有用的方法
->setTable('user')
->setGroup('user_active')
获取结果
当您对查询满意时,您可以像图0中描述的那样以3种方式检索结果。
图10. 检索结果
->getTotal()
->getRows()
->getCollection()
图10
显示了获取结果的三种方式,第一种方式getTotal()
将检索总数,不考虑分页元素。getRows()
将简单地返回一个原始数组。getCollection()
将返回一个对象,其中包含结果以便进一步操作。
====
集合
集合与模型执行完全相同的事情,除了它操作多个模型而不是单个模型。集合可以是可迭代的,也可以像数组一样访问。集合仅保留模型对象,因此如果您想使用自己的扩展模型,则需要调用setModel('Your_Model')
。
图11. PostGreSQL集合
//set user name for all rows
$collection->setUserName('Chris');
// set or get any abstract key for all rows
$collection->setAnyThing()
//collections are iterable
foreach($collection as $model) {
echo $model->getUserName().' ';
echo $model['user_email'];
}
//access as array
echo $collection[0]['user_name'];
//set as array
$collection[0]['user_email'] = 'my@email.com';
$collection->save('user', $database); //save to 'user' table in database
//only relavent columns will be saved
//for all rows
上述示例中没有涵盖的一些其他实用方法是日期格式化和将一个列复制到另一个列。图12
展示了我们如何进行这些操作。
图12. 实用方法
//formats a date column
$collection->formatTime('post_created', 'F d, y g:ia');
//for each row, copy the value of post_user to the user_id column
$collection->copy('post_user', 'user_id');
//remove the row with the index of 1, reindexes all the rows
$collection->cut(1);
//returns the number of rows
$collection->count();
//adds a new row
$collection->add(array('post_title' => 'Hi'));
//returns a table array (no objects)
$collection->get();
====
模型
在 Eden 中,我们成功地定义了一种松散的模型,它去除了传统ORM的限制性,并增加了可扩展性作为最终结果。首先,我们定义了一个通用且强大的模型类,它可以被扩展,但也可以直接使用。我们的模型类已经足够强大,可以解决很多用例,你可能不需要扩展它。我们对“松散定义”的概念进行了探讨,以下是我们的发现。
图 13. 数据库模型(扩展 Array)
$model->setUserName('Chris'); //set user name
$model->getUserEmail(); // returns user email
//$model->setAnyThing() // set or get any abstract key
echo $model['user_name']; //access as array
$model['user_email'] = 'my@email.com'; //set as array
echo $model->user_name; //access as object
$model->user_name = 'my@email.com'; //set as object
$model->save('user', $database); //save to 'user' table in database
//only relavent columns will be saved
因此,模型属性可以通过方法、对象或数组访问。我们留给你的选择。在我们的模型中,你可以在对象中添加额外的键值,即使它与目标数据库表无关。当你调用 save()
方法时,这时你需要指定你要保存到的表。这个方法非常强大,因为它会首先检查表中的列,然后与你的模型进行比较。它只会保存对象中具有匹配列名的列。最后,它将自动确定是否应该插入或更新该行。
一个常见的例子是当你有一个由连接数据组成的数组表。在 Eden 中,你可以保持那个数组不变,然后为每个表调用 save()
,如图 14 所示。
图 14. 两个表
$row = array(
'user_id' => 1,
'user_name' => 'Chris',
'user_email' => 'my@email.com',
'post_user' => 1,
'post_title' => 'My Post',
'post_detail' => 'This is my new article');
$db->model($row)->save('user')->save('post');
注意:你也可以保存到不同的数据库,如
save('post', $db2)
====
整合一切
所以一个常见的场景是从数据库检索数据,操作结果并将其发送回数据库。让我们看看 Eden 的搜索、集合和模型对象,看看我们如何实现这一点。
图 15. 最酷的事情!
//load database
eden('postgre', POSTGRE_HOST, POSTGRE_NAME, POSTGRE_USER, POSTGRE_PASS)
//search user table
->search('user')
//WHERE user_gender = $_get['gender']
->filterByUserGender($_GET['gender'])
//ORDER BY user_id
->sortByUserId('ASC')
//LIMIT 75, 25
->setStart(75)->setRange(25)
//get a collection object
->getCollection()
//sets all users to active
->setUserActive(1)
//Set a new column post_title
->setPostTitle('A '.$_GET['gender'].'\'s Post')
//Set a new column post_detail
->setPostDetail('Content is King')
//Copy the contents of user_id to a new column post_user
->copy('user_id', 'post_user')
//Set a new column post_created
->setPostCreated(time())
->formatTime('post_created', 'Y-m-d H:i:s')
//save to user table
->save('user')
//save to post table
->save('post');
如果你查看我们的 MySQL 或 SQLite 文档,你会发现它与这个文档几乎相同,只是基本查询部分有一些小的变化。我们将所有 SQL 数据库对象规范化为使用相同的东西,以减少学习曲线。
====
对 Eden 的贡献遵循 Github 工作流程。请在贡献之前阅读。
##使用 Eden 仓库和你的分支设置你的机器
- 分支仓库
- 在本地终端中启动,从你的分支的
v4
分支创建一个新分支,分支名称应描述你的更改。可能的分支名称类型- bugfix
- feature
- improvement
- 进行你的更改。始终确保对所有提交进行签名(git commit -s -m "提交信息")
##创建 pull requests
- 请在创建 pull request 之前确保运行
phpunit
。 - 将你的代码推送到你远程分支的版本。
- 回到 GitHub 上的你分支版本,提交 pull request。
- Eden 开发者将审查你的代码,并在它被分类为合适时合并。