问题 在PHP中设计通用数据库接口
我正在为PHP中的Web项目创建一个小框架,所以我不必为每个新网站反复做基础工作。创建第二个CakePHP或Codeigniter并不是我的目标,我也不打算用任何可用的框架构建我的网站,因为我更喜欢使用我自己创建的东西。
当涉及核心结构,请求处理等部分时,我在设计和编码框架方面没有任何问题,但是我已经陷入了为我的模块设计数据库接口的困难。
我已经考虑过使用MVC模式,但发现对于我这个相当小的项目来说这会有点过分。
所以我面临的确切问题是我的框架模块(viewCustomers
可能是一个模块,例如)应该与数据库进行交互。
将SQL直接混合到PHP代码中(仍然)是一个好主意吗? (将是“老路”: mysql_query( 'SELECT firstname, lastname(.....)
)?
我怎样才能抽象出如下的查询?
SELECT firstname, lastname FROM customers WHERE id=X
MySQL的“助手”功能会不会像
$this->db->customers->getBy( 'id', $x );
是个好主意?
我不太确定,因为它们在处理更复杂的查询时会变得毫无用处,例如上面几乎无关紧要的查询。
10556
2018-03-17 18:46
起源
答案:
如果你需要速度,那么使用原始查询(但你应该真的使用PDO 准备好的查询)。
如果你想要更多的OOP,你可以 - 如你所知 - 用帮助器设计它。
有一次,我设计了类似的东西,它有以下概念:
- 数据库连接/处理程序类(处理到不同数据库和不同服务器的多连接,如MySQL,Oracle等);
- 每个动作的类(即SELECT,DELETE等);
- 过滤类(例如RangeFilter);
代码看起来像这样:
$select = new Select('field1', 'field2', );
$result = $select->from('myTable')
->addFilter(SQLFilter::RangeFilter, 'field2')
->match(array(1, 3, 5))
->unmatch(array(15, 34))
->fetchAll();
这是一个如何构建它的简单示例。
您可以更进一步实现表关系的自动处理,字段类型检查(使用表上的内省),表和字段别名支持等。
这似乎是一项漫长而艰苦的工作,但实际上,制作所有这些功能(≈1个月)并不会花费你那么多时间。
3
2018-03-28 09:14
我相信您只想从您的模块访问您的数据库。我会避免直接从代码中使用mysql_query。相反,使用抽象的数据库访问的简单模型将是简单和直接的。
例如,您可以使用以下代码获得类似models / Customers.php的文件:
<?php
class Customers {
public function getById($id) {
$sql = "SELECT first_name, last_name FROM customers WHERE id='$id'";
$res = $DB::getRow($sql);
return ($res);
}
}
我假设某种数据库助手已经实例化并可用作$ DB。 这里 是一个使用PDO的简单的。
现在,您应该在模块中包含它并使用以下方法:
<?php
include_once "models/Customers.php";
$customers = new Customers();
$theCustomer = $customers->getById(intval($_REQUEST['cust_id']));
echo "Hello " . $theCustomer['first_name']
干杯。
6
2018-03-22 17:47
你看过了吗? http://www.doctrine-project.org/ 或其他php orm框架(想到zend_db)?
5
2018-03-17 18:50
三个提示:
- 使用存储过程(这样你可以将php与db分开)
- 使用PDO /库MySQLi 准备好的陈述
CALL NEWS_LIST(?, ?)
- 为数据库使用静态类。允许您在任何模块中访问它。
2
2018-03-17 18:50
原始SQL仍然是我的赢家,我喜欢控制我发送到服务器的内容(对于索引使用,复杂的JOIN子句等情况),所以我通常远离辅助函数。
您应该使用已经提供了大量功能的PDO,如果这还不够,您可以扩展它(可能使用您自己的功能,例如在实际查询数据库之前检查Memcached / APC上的命中)。您还可以扩展该类以实现您自己的SQL函数,如:
function getUser($user_id) {
return $this->query("SELECT * FROM users WHERE id = " . (int) $user_id);
}
当然,从模型中你仍然可以发送:
$this->db->query("SELECT * FROM users WHERE id = " . (int) $user_id);
并得到相同的结果。这些函数应仅仅作为一种捷径,扩展类不应该包含在框架中,因为它将依赖于站点。
MVC模式很适合这个,因为您只能将数据库用作驱动程序,然后您的模型可以将数据转换为您需要的数据。创建一个简单的MVC结构并不难,它会在以后为您带来好处。
1
2018-03-17 18:56
你听起来像我。你见过吗? http://github.com/Xeoncross/micromvc 和一个文件ORM http://github.com/Xeoncross/database?挖掘我的代码,我想你会找到你想要的东西。
解决方案是使用某些查询的完整原始功能 - 同时仍然允许ORM和查询构建器(如codeigniter的AR)用于其他事情。
两者都很好。
1
2018-03-27 19:14
不是我知道确定的答案(我认为它也不存在),但我想我可以分享我在这里的内容。我使用自己的db'框架',轻量级(当前约1000行)并且易于使用。我的主要目标是简化sql的使用,而不是从程序员(我:)中“隐藏”它。一些例子:
// row() is 'query' + 'fetch' in one
$user = $db->row("select * from users where id=25");
// the same, injection safe
$user = $db->row("select * from users where id=?", $_GET['id']);
// ? placeholders are smart
$someUsers = $db->rows("select * from users where id IN(?)", array(1, 2, 10));
// ...and even smarter
$data = array('name' => 'Joe', 'age' => 50);
$id = 222;
$db->exec("update users set ?a where id=?", $data, $id);
// 'advanced' fetch functions
$topNames = $db->vlist("select name from users order by name limit 10");
$arrayOfIds = $db->nlist("select id from users where age > 90");
// table() returns a Table Gateway
$db->table('users')->delete('where id=?', 25);
// yes, this is safe
$db->table('users')->insert($_POST);
// find() returns a Row Gateway object
$db->table('users')
->find('where name=?', 'Joe')
->set('status', 'confirmed')
->save();
1
2018-03-27 23:08