eden/mysql

Eden MySQL 搜索、集合、模型 ORM 组件

4.0.1 2015-10-13 05:38 UTC

This package is auto-updated.

Last update: 2024-09-13 20:48:51 UTC


README

Build Status

====

安装

composer install eden/mysql

====

启用 Eden

以下文档使用 eden() 作为示例参考。启用此功能需要额外的步骤,如本节所述,如果您使用以下方式访问此包,则不需要这些步骤。

Eden\Mysql\Index::i();

当使用 composer 时,没有简单的方法可以直接访问包中的函数。作为替代方案,在您的代码中添加此常量将允许 eden() 在之后可用。

Eden::DECORATOR;

例如

Eden::DECORATOR;

eden()->inspect('Hello World');

====

简介

Eden 的 MySQL 对象堪称壮观!我们引入了搜索、集合和模型,将 ORM 提升到了全新的水平,适用于初学者和爱好者。在深入探讨这些高级主题之前,我们应该先了解一下可用的基本方法。首先,我们需要向数据库模型添加连接信息,如 图 1 所示。

图 1. 数据库连接信息

$database = eden('mysql', '[HOST]' ,'[DBNAME]', '[USER]', '[PASS]');    //instantiate

简单来说,我们首先实例化类,在上述图中给出主机、数据库名称、用户名和密码。没有其他要求,您可以直接开始使用方法。

注意 Eden 的 MySQL 对象仅在执行第一个查询时连接。这种策略称为懒加载。

====

基本查询

在非常低级别上,可以调用如图 2 所示的原始查询。

图 2. 原始查询

$database->query('SELECT * FROM user');  // returns results of raw queries

Eden 的 MySQL 对象使用 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列中,则更新该行。如果不存在,则插入。在Eden中删除数据也非常简单。

图7. 删除

$filter[] = array('user_id=%s', 1);
$database->deleteRows('user', $filter); // delete rows in 'user' table where user_id is 1

====

搜索

使用Eden的搜索对象构建复杂查询是一种更好的方法。一个概述示例可以在图8中找到。

图8. MySQL搜索

$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()。MySQL类中实际上没有名为filterByUserName()的方法。相反,当调用此函数时,它将解析方法名称并识别UserName是列名,并将其转换为addFilter('user_name=%s', 'Chris'),如图8所示。

addFilter()通常接受两个参数。第一个参数是过滤条件。如果您注意到我们的过滤示例在图8中使用了%s来分隔绑定值。您可以为每个过滤条件添加任意多的绑定值。后续参数需要按过滤条件中出现的顺序包含绑定值。

第二个被魔法激活的方法是sortByUserId('ASC')。MySQL类中实际上没有名为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. MySQL集合

//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. 数据库模型(扩展数组)

$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中,您可以保持数组不变,然后像图14中那样为每个表调用save()

图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('mysql', MYSQL_HOST, MYSQL_NAME, MYSQL_USER, MYSQL_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');

如果您查看我们的PostGreSQL或SQLite文档,您会发现它与这个文档相同,只是基本查询部分有一些小的变化。我们将所有SQL数据库对象规范化,使用完全相同的东西,以减少学习曲线。

====

#为Eden做出贡献

对《Eden》的贡献遵循GitHub工作流程。请在贡献之前阅读。

##设置您的机器以使用Eden仓库和您的分支

  1. 分叉仓库
  2. 在本地终端中启动,从您的分叉的v4分支创建一个新的分支,分支名称描述您的更改。可能的分支名称类型
    • bugfix
    • feature
    • improvement
  3. 进行您的更改。始终确保在所有提交中签署(git commit -s -m "提交信息")

##创建拉取请求

  1. 在创建拉取请求之前,请确保运行phpunit
  2. 将您的代码推送到您的远程分叉版本。
  3. 回到您在GitHub上的分叉版本,提交一个拉取请求。
  4. Eden开发者将审查您的代码,并在其被认为合适时将其合并。