【问题标题】:What is the best way to access a database from PHP? [closed]从 PHP 访问数据库的最佳方法是什么? [关闭]
【发布时间】:2016-01-18 16:53:22
【问题描述】:

当从 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 构建的。

【问题讨论】:

    标签: php mysql database pear


    【解决方案1】:

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

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

    【讨论】:

    • Doctrine 的 +1,它是一个功能丰富的 ORM 层,“正常工作”。我最近在现有的遗留数据库上使用了它,印象非常深刻。
    【解决方案2】:

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

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

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

    查看MDB2 documentation 以了解其工作原理。

    【讨论】:

    • 由于这个东西自 2012 年以来就没有更新过,我认为是时候对这个答案投反对票了(这也是我们现在避免软件推荐的一个很好的例子)。
    • 我刚刚升级到 php7 并且 MDB2 停止工作,所以是的。 deceze 说了什么。去寻找最新最好的 PHP 数据库抽象包(哎呀,Perl 这些年来一直坚持使用 DBD,它仍然可以正常工作。)
    【解决方案3】:

    还有哪些其他模式?

    ActiveRecord -- 你可以在CakePHP 中看到一个这样的例子。

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

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

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

    【讨论】:

      【解决方案4】:

      这绝对取决于您编写的网络应用程序有多大。我会为Doctrine 竖起大拇指(如果使用得当)。如果它是一个非常小的 quick-n-dirty 项目,您可能会使用 PDO 来侥幸。

      【讨论】:

        【解决方案5】:

        “视情况而定”

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

        【讨论】:

          【解决方案6】:

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

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

          【讨论】:

            【解决方案7】:

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

            我把事情分成两个类,

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

            当在表上调用 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) 的东西与面向对象的东西结合起来并不容易,所以我知道我的方法有其缺点,你可能会得到很多不同的答案自己的缺点。

            【讨论】:

              【解决方案8】:

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

              【讨论】:

                【解决方案9】:

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

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

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

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

                【讨论】:

                  【解决方案10】:

                  为了执行命令,我会使用函数来执行常用的 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')))
                  

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

                  【讨论】:

                    【解决方案11】:

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

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

                    【讨论】:

                      【解决方案12】:

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

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

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

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

                      【讨论】:

                        【解决方案13】:

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

                        【讨论】:

                          【解决方案14】:

                          任何方法都是好的,只要在数据库架构发生变化时(输入、过滤、验证、表单生成等)尽量减少需要更改代码的点。

                          我喜欢使用 PDO参数化 SQL 来简化返回的数据集(::getActiveUsers()、@987654322 @ 等)。

                          【讨论】:

                            猜你喜欢
                            • 1970-01-01
                            • 1970-01-01
                            • 2013-11-29
                            • 1970-01-01
                            • 1970-01-01
                            • 2017-12-11
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            相关资源
                            最近更新 更多