“看情况”
对于我自己的项目,我倾向于使用某种类型的框架,其中包括一个抽象层。对于不适合框架的小型项目,我只是把SQL放在脚本中(因为它很小)。上次我在没有框架的情况下做了一个相当大的应用程序,我使用了PDO,因为它很容易支持预处理语句,等等。这是一个非常容易学习的抽象层。如果出于某种原因我选择不使用框架,我可能会再次使用它。
当从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
但还没有看到它在 3.
还有其他的模式吗?
如果你今天开始从零开始建立一个网站,你会选择哪一个?
澄清:本文不是关于DB抽象层(PDO、MDB2)。这里讨论的模式是在PDO或MDB2上构建的。
“看情况”
对于我自己的项目,我倾向于使用某种类型的框架,其中包括一个抽象层。对于不适合框架的小型项目,我只是把SQL放在脚本中(因为它很小)。上次我在没有框架的情况下做了一个相当大的应用程序,我使用了PDO,因为它很容易支持预处理语句,等等。这是一个非常容易学习的抽象层。如果出于某种原因我选择不使用框架,我可能会再次使用它。
使用MVC结构和数据库抽象层。通过这种方式,您可以在一个地方完全重做数据访问类的内部,同时保持公共接口不变。
贯穿整个代码的原始SQL几乎不可能扩展。
为了执行命令,我将使用函数来执行常用的SQL命令。然后可以使用这些函数生成更具体的函数,如get_users()
a)为你可能想要查询的每个查询创建一个函数,例如
db_select($opts)
其中$opts是一个带键的哈希数组:
['table_name', 'selection', 'condition', 'group_by', 'order_by', 'limit']
b)如果您大量使用SQL,我可能会想创建一个SQL命令构建器,它接受一个哈希数组并返回一个命令。喜欢的东西:
3.
上面提到的函数会在它们的实现中使用它,如果您需要一个完全随机的语句,那么您也会这样做,希望通过在所有地方重用命令构建器代码,整个事情将非常可靠。
如果你想要一个面向对象的方法,下面是我最近的方法。
我把东西分成两类,
首先,DatabaseTable类接受一个表名,即该表的键的字符串。其次,我创建了一个DatabaseObject类,它表示DatabaseTable中的一行。DatabaseObject有两个例程setFromRow和getAsRow。SetFromRow将从col=>值对的关联数组设置对象,而get as row将本质上序列化为col=>值对的对象。
当在表上调用select方法时,DatabaseTable使用setFromRow来生成databaseobject。相反,当它被告知更新或插入数据到其表中时,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)的管理分离开来。因此,用c++术语来说,我的DatabaseObject可以是plain-old-data。
当然,您可以更进一步,就像我所做的那样,通过创建表之间的关系,以及创建更多的选择方法等等。
我应该补充一点,将本质上的过程语言(SQL)与面向对象的语言集成起来并不容易,所以我知道我的方法有它的缺点,您可能会得到许多不同的答案,每个答案都有自己的缺点。