8

从 PHP 访问 MySQL 数据库时,似乎有几种方法:

Sprinkle the code with raw SQL-statements
Use the VO-pattern from Java (e.g. DB_DataObjects from PEAR)
DIY and write a script that auto-generates one PHP class per database 

除此之外,我还阅读过LINQ in .NET但没有看到它在PHP.

还有哪些其他模式中实现?

如果您今天从头开始构建网站,您会选择哪一个?

澄清:这与 DB 抽象层(PDO、MDB2)无关。这里讨论的模式是基于 PDO 或 MDB2 构建的。

4

14 回答 14

6

您正在寻找的是对象关系模型 (ORM)。有几个不同的:

如果 ORM 对您的项目来说太多了,那么您只需退回到像 PDO 这样的通用数据库接口并手动构建准备好的语句。

于 2008-09-16T14:10:47.107 回答
5

我会从 PEAR 中选择MDB2 数据库抽象层——它提供了一种很好的抽象方法来处理数据库。我推荐它,因为它允许您编写可移植的代码,无需太多更改即可移植到不同的数据库服务器(对于基本脚本,只需更改连接调用可能就足够了)。它是旧 DB 和 Metabase 抽象层的合并(错误修复仍然支持 DB,但已被 MDB2 取代)。

它为不正确支持它的数据库提供了准备 + 执行模拟等功能,并允许您使用占位符,这是避免 SQL 注入问题的好习惯。

它将适用于:mysql / mysqli、pgsql (PostgreSQL)、oci8 (Oracle)、sqllite、msql、mssql (Microsoft SQL Server)、sybase、informix、fbsql、ibase、odbc。

查看MDB2 文档以了解它是如何工作的。

于 2008-09-16T10:49:40.350 回答
2

还有哪些其他模式?

ActiveRecord——你可以在CakePHP中看到一个例子。

我认为这在很大程度上取决于您的需求——如果您正在构建一个小型应用程序,那么构建一个 DIY 数据库层可能会更快。

如果您正在构建一个包含大量表和关系的大型应用程序,那么使用像 CakePHP 的 ActiveRecord 功能之类的东西可能会更快更容易。

我还没有使用 PEAR 的抽象层,但它看起来也不错。Zend 在Zend 框架中也有一个数据库库。

于 2008-09-16T10:43:19.070 回答
2

这绝对取决于您正在编写的网络应用程序有多大。我会为Doctrine竖起大拇指(如果使用得当)。如果这是一个非常小的快速-n-dirty 项目,您可能只需使用PDO就可以了。

于 2008-09-16T20:48:42.250 回答
1

“这取决于”

对于我自己的项目,我倾向于使用某种框架,其中包括一个抽象层。对于不适合框架的小型项目,我只是将 SQL 放在脚本中(因为它很小)。上次我在没有框架的情况下做一个相当大的应用程序时,我使用了 PDO,因为它提供了易于准备的语句支持等。它是一个非常容易学习的抽象层。如果出于某种原因我选择不使用框架,我可能会再次使用它。

于 2008-09-16T10:41:52.910 回答
1

除此之外,我还阅读了 .NET 中的 LINQ,但还没有看到它在 PHP 中实现。

像 Linq 这样的东西还不能在 PHP 中实现,因为该语言缺乏必要的结构。已经创建了一种“假 linq” ,但这只是使用字符串而不是“真正的”linq。即使是这样,它实际上也只是 Linq to objects 的等价物,没有任何东西像 Linq to SQL 一样。

于 2008-09-16T10:47:21.557 回答
1

如果你想要一种面向对象的方法,这就是我最近的方法。

我把事情分成两个类,

首先,DatabaseTable 类 - 接受一个表名,一个作为该表键的字符串。其次,我创建了一个代表 DatabaseTable 中一行的 DatabaseObject 类。DatabaseObject 有两个例程 setFromRow 和 getAsRow。SetFromRow 将从 col=>value 对的关联数组中设置对象,并且 get as row 本质上会将对象序列化为 col=>value 对。

当在表上调用 select 方法时,DatabaseTable 使用 setFromRow 来制造 DatabaseObjects。相反,当它被告知更新或插入数据到其表中时,DatabsaeTable 将使用 getAsRow 序列化 DatabaseObject。

通常发生的事情是从 DatabaseObject 继承他们自己的特定对象,定义 setFromRow 和 getAsRow,并且 DatabaseTable 被告知要实例化的 DatabaseObject 的名称。

所以你最终写的代码是这样的

$dbTable = new DatabaseTable('tableName', 'uniqueid', 'InstanceType')
// dbTable manufactures an InstanceType for our use based on the select below
$dbRow = $dbTable->selectUsingId(15); 
print_r($dbRow);  // Dumps the InstanceTypeObject

这将我的应用程序中的数据表示(DatabaseObject)与数据库表(DatabaseTable)的管理分开。所以我的 DatabaseObject 在 C++ 术语中可以是普通的旧数据。

当然,您可以像我一样走得更远,通过创建表之间的关系,创建更多的选择方式等。

我应该补充一点,将本质上是一种过程语言(SQL)的东西与面向对象的东西结合起来并不容易,所以我知道我的方法有其缺点,你可能会得到很多不同的答案,每个答案都有自己的缺点。

于 2008-09-16T13:50:22.007 回答
1

您可能还想考虑使用CodeIgniter,这是一个不错的 PHP 小型 MVC 框架。它有一个 ActiveRecord 实现和一组合理的数据库对象(包括绑定变量)。我发现它的 DB 类比默认的 PHP MySQL API 好得多,并且比 PDO 简单一点(当然更容易安装)。

于 2008-09-16T17:27:45.963 回答
0

至少,使用 PDO。它为大多数数据库平台提供了一个通用接口,如果您愿意,可以更轻松地切换数据库解决方案。

我喜欢使用对象关系映射器(ORM),比如推进: http: //propel.phpdb.org/trac/

这会将您的对象直接映射到数据库模式 - 不需要 SQL。映射发生在 XML 文件中,查询发生在 Criteria 对象中。可以从数据库对 PHP 类进行逆向工程,或者从模式 xml 生成数据库。

有关 ORM 的更多信息,请参阅http://en.wikipedia.org/wiki/Object-relational_mapping

于 2008-09-16T10:41:59.243 回答
0

使用 MVC 结构和数据库抽象层。通过这种方式,您可以在一个地方完全修改数据访问类的内部结构,同时保持公共接口不变。

整个代码中的原始 SQL 几乎无法扩展。

于 2008-09-16T10:45:19.800 回答
0

为了执行命令,我会使用函数来执行常用的 SQL 命令。然后可以使用这些函数来制作更具体的东西,例如 get_users()

a)为您可能想要进行的每个查询创建一个函数,例如

db_select($opts)

其中 $opts 是一个带有键的哈希数组:

['table_name', 'selection', 'condition', 'group_by', 'order_by', 'limit']

b) 如果你大量使用 SQL,我可能会想创建一个 SQL 命令生成器,它接受一个哈希数组并返回一个命令。就像是:

db_builder(array('select'=>array('customers','from'=>'bar','where'=>'foo=10')))

上面提到的函数将在它们的实现中使用它,如果你需要一个完全随机的语句,你也会如此,并且希望通过在任何地方重用命令构建器代码,整个事情都会坚如磐石。

于 2008-09-16T10:54:24.473 回答
0

我做了一个两级手工编码的方法:

第一级是一组简单的函数:

  • do_query(sql):返回(打开的)结果对象。
  • get_record(sql):返回第一条记录,查询关闭。
  • get_datum(sql):返回第一条记录的第一个字段(查询关闭)

之后,我编写了我的模型层,其中包含所有数据操作的特定功能。通常是一个文件,其中包含每个概念对象的部分。参数与抽象数据相关联,而不是与 SQL 结构相关联。所有的 SQL 都在这一层。

于 2008-09-16T11:12:13.540 回答
0

任何方式都是好的,只要您在数据库架构更改(输入、过滤、验证、表单生成等)时需要更改代码的点最小化。

我喜欢使用PDO参数化 SQL和抽象返回的数据集的::getActiveUsers()(等::getUserPersonalData())保持简单。

于 2008-09-16T18:53:19.097 回答
0

你可以使用像 Doctrine 这样的 ORM。

于 2013-08-31T07:41:46.997 回答