eden /sqlite
Eden SQLite搜索,集合,模型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/sqlite
====
介绍
Eden的 SQLite对象无与伦比!我们将ORM提升到了一个新的高度,包括搜索、集合和模型,旨在为初学者和爱好者提供支持。在我们深入探讨这些高级主题之前,我们首先应该了解可用的基本方法。首先,我们需要将数据库模型中的连接信息添加到我们的数据库模型中,如图1所示。
图1. 数据库连接信息
$database = eden('sqlite', '[SQL_FILE_PATH]'); //instantiate
简单来说,我们实例化类,给出服务器上数据库的文件路径。没有其他要求,您可以直接开始使用方法。
注意 Eden的SQLite对象仅在第一次查询时才会连接。这种策略称为懒加载。
====
基本查询
在非常低级别上,可以调用原始查询,如图2所示。
图2. 原始查询
$database->query('SELECT * FROM user'); // returns results of raw queries
Eden的 SQLite对象使用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. SQLite搜索
$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()
。SQLite类中实际上没有名为filterByUserName()
的方法。相反,当此函数被调用时,它将解析方法名称,并识别出UserName是列的名称,并将其转换为如图8所示的addFilter('user_name=%s', 'Chris')
。
addFilter()
通常接受两个参数。第一个参数是过滤器子句。如果您注意到的过滤器示例中的图8
,我们使用%s来分隔绑定的值。您可以根据需要为每个过滤器绑定任意数量的值。以下参数需要按过滤器子句中出现的顺序包含绑定值。
第二个被魔法支持的函数是sortByUserId('ASC')
。SQLite类中实际上没有名为sortByUserId('ASC')
的方法。相反,当此函数被调用时,它将解析方法名称,并识别出UserId是列的名称,并将其转换为如图8所示的addSort('user_id', 'ASC')
。
还有三种分页方法可供使用
分页方法
setRange(75)
setStart(25)
setPage(1)
如果您打算使用setPage(1)
,则首先调用setRange(75)
很重要,因为底层函数只是根据范围计算起始索引。另外两种在图8
中没有涵盖的方法是分组和设置其他表。
图9. 其他有用的方法
->setTable('user')
->setGroup('user_active')
获取结果
当您对查询满意时,您可以通过如图0所示的方式检索结果。
图10. 获取结果
->getTotal()
->getRows()
->getCollection()
图10
显示了三种获取结果的方式,第一种方式getTotal()
将检索总数,不考虑分页元素。getRows()
将简单地返回一个原始数组。getCollection()
将返回一个对象,其中包含结果以便进一步操作。
====
集合
集合与模型执行的功能完全相同,除了它操作多个模型而不是单个模型。集合可迭代,并可像数组一样访问。集合仅持有模型对象,因此如果您想使用自己的扩展模型,您需要调用setModel('Your_Model')
。
图11. SQLite集合
//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('sqlite', SQLITE_FILE)
//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或MySQL文档,您会发现它与这个文档几乎相同,只是基本查询部分有一些小的变化。我们将所有SQL数据库对象标准化,使用完全相同的东西,以降低学习曲线。
====
对Eden的贡献遵循GitHub工作流程。请在贡献之前阅读。
##使用Eden仓库和您的分支设置您的机器
- Fork仓库
- 在本地终端启动,从您的fork的
v4
分支创建一个新的分支,分支名称描述您的更改。可能的分支名称类型- bugfix
- feature
- improvement
- 进行您的更改。始终确保在所有提交上签出(git commit -s -m "提交信息")
##制作pull请求
- 在制作pull请求之前,请确保运行
phpunit
。 - 将您的代码推送到您远程的fork版本。
- 回到GitHub上的您fork的版本,并提交一个pull请求。
- Eden的开发者将审查您的代码,并在它被归类为合适时合并。