是否有更好、更“标准”的方式在 PHP 中执行 SQL 查询而不使用框架?

Posted

技术标签:

【中文标题】是否有更好、更“标准”的方式在 PHP 中执行 SQL 查询而不使用框架?【英文标题】:Is there a better, more "Standard" way to perform SQL queries in PHP without using a framework? 【发布时间】:2009-11-06 04:14:34 【问题描述】:

长期以来,我一直在我的 php 中使用以下基本的 SQL 查询格式:

$sql = "SELECT * FROM `user-data` WHERE `id` = '".$id."' LIMIT 1;";
$fn = mysql_fetch_assoc(mysql_query($sql));

虽然这可以完美运行,但对于较长的代码,它可能会变得非常混乱,并且每次我这样做时,我内心深处的某些东西都会对字符串连接感到畏缩。尽管如此,它仍然有效,我几乎在所有地方都使用它,没有出现重大问题。 (这是一个平淡无奇的例子,我不够密集,无法将用户数据直接传递到 SQL 字符串中而不先转义,等等。)

我想做的是更面向对象的事情,但我不确定最好的方法是什么。最好能够 sql->insert($values [, $where, $extra]);或类似的东西,使用 PHP 的自然关联数组类型以更简化的方式传递查询字符串。不够灵活?是的。更具可读性?哎呀,是的,而且更难产生“无声”的语法错误。

社区对此有何看法?对于您正在从事的项目,您发现哪些方法最有效地解决了这个问题?

这并不重要,但我个人不会做比 SELECT、INSERT 和 UPDATE 复杂得多的操作,偶尔会嵌套子查询,但这主要是因为我的 SQL 风格不做存储过程。

【问题讨论】:

虽然我很清楚肯定存在解决这个问题的框架,但我试图避免这些答案。我想知道如何从一个普通的 PHP 安装开始,重点检查实现它的底层代码。 【参考方案1】:

PDO 是一个很好的、可靠的、安全的解决方案,许多框架都以此为基础。如果你要从底层做起,PDO 是一个坚实的基础。

【讨论】:

这当然是一个我不知道的有趣功能。 ^_^ 漂亮。【参考方案2】:

也许使用 PHP 的字符串变量替换至少会让你更开心一点:

$sql = "SELECT * FROM `user-data` WHERE `id` = '$id' LIMIT 1;";

【讨论】:

必须小心这一点,因为需要适当的转义,否则您最终会使另一个网站容易受到 SQL 注入的攻击 当然可以,但不比原帖差。【参考方案3】:

有MDB_QueryTool我没试过。

恕我直言Zend_DB 真的很酷,zend 框架允许你只使用你感兴趣的部分,所以如果你不想要完整的框架,你可能想看看它。

我喜欢 Zend_DB 中的表选择语法

$userRowset = $user->fetchAll( $user->select()
 ->where('name LIKE ?', $name . '%')
 ->order('id ASC')
 ->limit(10) 
);

您可以轻松查看所涉及的所有标准和表格,因此我发现执行普通 SQL 更好。只有一个警告 Zend_DB 并不能处理所有的 SQL,所以有时你不得不编写简单的 SQL,但这真的很少见。

【讨论】:

【参考方案4】:

Doctrine 是一个 ORM 包裹在 PDO 周围。

【讨论】:

【参考方案5】:

教义再投一票。不要在 PDO 上浪费时间。我怎么强调都不过分。去一个orm。忘记浪费时间编写 CRUD 方法、自定义缓存逻辑,以及担心过早的优化,例如库导致的“开销”。诸如“select * from app_users”之类的散乱语句及其相关的丑陋的 heredocs 所产生的开销是不值得的。

如果你需要回退到 sql,你可以。另外 90% 的时间你都处于幸福状态。

http://www.doctrine-project.org/

【讨论】:

尼克,我注意到您关于理解底层代码的评论。在编写自己的 sql 大约两周后,您将开始看到模式出现。不过,您可能仍然不愿意使用 ORM(“它比我需要的多得多!”),并开始编写自己的实用程序函数来捕捉这些新兴模式和习语。两周后,您将查看教义并意识到它会使您的公用事业陷入困境。你会看到它有很好的文档记录、单元测试和稳定。即使从教学的角度来看,orm 也是好的。如果您好奇,请查看数据库日志;) 只需要添加。如果您对制作应用程序感兴趣,Doctrine 就是您要走的路。如果您对编写自己的数据库框架感兴趣,那么您就需要 PDO。但这不是 Web 开发的有趣部分 :) Doctrine 已经做到了这一点,并且他们已经进行了几代人的学习,因此已经吸取了教训并进行了改进(Adodb、Pear、MDB2、Propel、Doctrine)。怎么强调都不为过:试试 ORM,尤其是因为它听起来像你以前没有过,然后流下喜悦的泪水。 Doctrine 运行 trought PDO。 Doctrine 可能适合大型项目,但是,如果他曾经将查询写为“$sql =”SELECT * FROM user-data WHERE id = '".$id."' LIMIT 1;";",我不要认为学习 Doctrine 值得付出代价。 如果这是您在 php 职业生涯中写过的唯一查询,那么是的,不要花时间学习学说。在应用程序开发的上下文中,您越早决定使用 orm,IMO 就越好。很多项目从小做起,做大做大,到那时重构一堆糟糕的 sql 并不好玩。即使在用户数据的情况下,当您想按名字、姓氏搜索时会发生什么。按不同标准排序?您的数据层不稳定且对架构更改不灵活。 我完全同意使用一个框架,并且我完全打算使用一个。但是,我最感兴趣的是所说的框架是如何工作的,以及主要的区别是什么。例如,到目前为止,我更喜欢 Zend_DB 框架的外观(就代码而言)。 Doctrine 看起来很强大,但学习起来也很复杂,尤其是因为我很少做比基本 SQL 命令更复杂的事情。 (我只使用了 很多 个。)【参考方案6】:

您可以使用mysqli 在您的 SQL 中编写小占位符然后填充它们。它应该比字符串连接更不容易受到 SQL 注入攻击。

$conn = new mysqli($server, $username, $password, $database);
$stmt = $conn->prepare('SELECT * FROM people WHERE age = ? AND name != ?');
$stmt->bind_param('is', 20, "Austin");

【讨论】:

【参考方案7】:

试试:

$stat2 = <<<SQL
SELECT *  from YOUR.DET_TABLE
WHERE ID = ?
ORDER BY ID, EFF_DT
SQL;
  $d_cur = $conn->prepare($stat2);
  $status   = $d_cur->execute(array($selected));

【讨论】:

【参考方案8】:

我一直想知道为什么我总是看到像这样更复杂的字符串构建形式: “文字字符串”。 $一个。 “更文字”,而不是“文字字符串 $a 更文字”,或者在你的情况下:

"SELECT * FROM `user-data` WHERE `id` = '".$id."' LIMIT 1;";

而不是这个:

"SELECT * FROM `user-data` WHERE `id` = '$id' LIMIT 1;";

对于更复杂的表达式,我喜欢使用sprintf(但我是长期的c程序员):

$sql = sprintf("SELECT * FROM `user-data` WHERE `id` = '%s' LIMIT 1", $id);

也可以这样写:

$sql = sprintf("
    SELECT * 
       FROM `user-data` 
    WHERE `id` = '%s' 
        LIMIT 1", 
    $id);

这种情况下买的不多,但是当字符串中嵌入了多个变量时,就更容易管理了。

【讨论】:

以上是关于是否有更好、更“标准”的方式在 PHP 中执行 SQL 查询而不使用框架?的主要内容,如果未能解决你的问题,请参考以下文章

PHP:strftime()、date() 或 DateTime,哪个更好?

使用 PHP 库的标准方法是啥?

Symfony 中的 REQUEST 是不是比“标准”PHP 中的更安全?

如何在PHP中的SELECT语句中执行子查询?

更好的PHP错误处理

PHP CURL api 是不是比使用流进行 HTTP/HTTPS 访问更干净/更快/更好?