从PHP访问数据库的最佳方法是什么?
从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
除此之外,我还阅读了有关.NET中的LINQ的信息,但还没有看到它在PHP中的实现。
还有哪些其他模式?
如果我们今天开始从头开始构建网站,那么我们会选择哪个?
说明:这与数据库抽象层(PDO,MDB2)无关。这里讨论的模式是我们在PDO或者MDB2上构建的。
解决方案
回答
"这取决于"
对于我自己的项目,我倾向于使用某种框架,其中包括一个抽象层。对于不合适于框架的较小项目,我只是将SQL放在脚本中(因为它很小)。上一次我在没有框架的情况下执行大型应用程序时,我使用PDO来提供易于准备的语句支持等。这是一个易于学习的抽象层。如果由于某种原因我选择不使用框架,我可能会再次使用它。
回答
至少要使用PDO。它为大多数数据库平台提供了一个通用接口,使我们可以轻松切换数据库解决方案。
我喜欢使用像Proel这样的对象关系映射器(ORM):http://propel.phpdb.org/trac/
这将对象直接映射到不需要SQL的数据库模式。映射发生在XML文件中,查询通过Criteria对象发生。可以从数据库反向工程PHP类,或者从架构xml生成数据库。
有关一般ORM的更多信息,请参见http://en.wikipedia.org/wiki/Object-relational_mapping
回答
What other patterns are there?
ActiveRecord-我们可以在CakePHP中看到一个示例。
我认为,如果我们要构建一个小型应用程序,则它很大程度上取决于需求,这可能会更快地构建一个DIY数据库层。
如果我们要构建具有大量表和关系的大型应用程序,则使用CakePHP的ActiveRecord功能之类的方法可能会更快,更容易。
我还没有使用PEAR的抽象层,但它看起来也不错。 Zend在Zend框架中也有一个数据库库。
回答
使用MVC结构和数据库抽象层。这样一来,我们就可以在完全保持公共接口不变的情况下,完全修改数据访问类的内部结构。
整个代码中的原始SQL将几乎无法扩展。
回答
Apart from this I have also read about LINQ in .NET but have not seen it implemented in PHP.
像Linq这样的东西尚不能用PHP实现,因为该语言缺少必要的构造。已经创建了一种"假linq",但这仅使用字符串,而不是"真实" linq。即使是这样,它实际上也只是Linq与对象的对等,没有什么比Linq to SQL更好的了。
回答
我会从PEAR中选择MDB2数据库抽象层,它提供了一种很好的抽象方法来处理数据库。我建议这样做,因为它允许我们编写可移植的代码,而无需进行许多更改即可将它们移植到其他数据库服务器(对于基本脚本,只需更改connect调用就足够了)。它是旧数据库和元数据库抽象层的合并(错误修复仍支持数据库,但已被MDB2取代)。
它为不正确支持的数据库提供了诸如准备+执行仿真之类的功能,并允许我们使用占位符,这是避免SQL注入问题的好习惯。
它将与以下版本一起使用:mysql / mysqli,pgsql(PostgreSQL),oci8(Oracle),sqllite,msql,mssql(Microsoft SQL Server),sybase,informix,fbsql,ibase,odbc。
查看MDB2文档以了解其工作方式。
回答
为了执行命令,我将对常用的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')))
上面提到的函数将在其实现中使用此函数,如果我们需要一个完全随机的语句,也将使用它,希望通过在各处重用命令构建器代码,使整个过程变得牢不可破。
回答
我执行两级手工编码方法:
第一级是一组简单的功能:
- do_query(sql):返回(打开)结果对象。
- get_record(sql):返回第一条记录,查询已关闭。
- get_datum(sql):返回第一个记录的第一个字段(查询已关闭)
之后,我编写我的模型层,并为所有数据操作提供特定功能。通常是单个文件,每个概念对象都有节。参数绑定到抽象数据,而不绑定到SQL结构。所有的SQL都在这一层。
回答
如果我们想要一种面向对象的方法,这就是我最近的方法。
我将事情分为两类,
首先,DatabaseTable类采用一个表名,即该表的键的字符串。其次,我创建一个DatabaseObject类,该类代表DatabaseTable中的一行。 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)的管理分开。因此,用C ++术语来说,我的DatabaseObject可以是纯旧数据。
当然,通过创建表之间的关系以及创建更多选择方式等,我们可以走得更远。
我应该补充一点,将本质上是一种过程语言(SQL)与面向对象的语言集成起来并不容易,所以我知道我的方法有其缺点,我们可能会得到很多不同的答案,每一个都有各自的缺点。
回答
我们正在寻找的是对象关系模型(ORM)。有几个不同的地方:
- 推进
- 教义
如果ORM对于项目来说太多了,那么我们将退回到通用的DB接口(如PDO)并手动构建准备好的语句。
回答
我们可能还需要考虑使用CodeIgniter,这是一个不错的PHP MVC框架。它既有ActiveRecord实现,又有合理的数据库对象集(包括绑定变量)。我发现它的数据库类比默认的PHP MySQL API好得多,并且比PDO简单(肯定更容易安装)。
回答
只要将数据库架构更改(输入,过滤,验证,表单生成等)时需要更改代码的点减到最少,任何方法都是好的。
我想通过PDO,参数化SQL和抽象化返回的数据集的类(`:: getActiveUsers(),:: getUserPersonalData()等)来简化操作。
回答
阅读Lerdorf先生本人对PHP网站"添加结构"的看法。
www.oracle.com/technology/pub/articles/php_experts/rasmus_php.html
回答
这肯定取决于我们正在编写的Web应用程序的大小。我会赞成"教义"(如果使用得当的话)。如果这是一个很小的Quick-N-dirty项目,那么我们可能就可以摆脱使用PDO的麻烦了。