我有以下代码:
$result = $conn->query($sql)->fetch(PDO::FETCH_COLUMN);
$myArray = explode(',', $result);
$sql = ("SELECT username,status,location FROM Users WHERE username IN ('" . implode("','",$myArray) . "') AND status > 0 ORDER BY username");
$data = $conn->query($sql)->fetchAll(PDO::FETCH_OBJ);
print_r ($data);
FYI $结果为“kk,bb”
输出如下:
Array ( [0] => stdClass Object ( [username] => bb [status] => 1 [location] => ) [1] => stdClass Object ( [username] => kk [status] => 1 [location] => ) )
但我真的只想看到一个二维数组,而不是在每个项目前面说stdClass对象。我尝试了不同类型的提取,但这是我唯一可以工作的方法。我知道有一些将对象转换为数组的函数,但是如果在粘贴的代码中存在这样的事情,我应该尝试这样做。
我希望有人可以提前帮助!
答案 0 :(得分:3)
您使用PDO::FETCH_OBJECT
请求了对象。如果要作为数组获取,请使用另一种获取类型:
$data = $conn->query($sql)->fetchAll(PDO::FETCH_ASSOC);
或
$data = $conn->query($sql)->fetchAll(PDO::FETCH_NUM);
其他选项记录在此处:http://php.net/manual/en/pdostatement.fetch.php
顺便说一下,为什么要运行一个查询来获取$myArray
中的值,然后在第二个查询中以SQL注入漏洞的方式使用它们?使用JOIN
会不会更容易?
重新评论:
首先,我强烈建议您第一次安全编码,不要依赖"稍后再回来。"你可能以后没有时间回去,因为一旦代码似乎工作得足够好,"诱惑就是立刻上线。即使您稍后再回过头来修复安全漏洞,也可能会错过一个漏洞。无论哪种方式,您的开发过程都会产生很高的风险,您将使用不安全的代码。
来自着名计算机科学家Andrew S. Tanenbaum的一条老建议:"安全性,如正确性,不是附加功能。"
现在关于加入。如果使用SQL,则应了解如何进行连接。即使你不知道如何使用foreach()
,不知道SQL中的连接就像是在想你知道PHP。从技术上讲,你仍然可以做一些事情,但是你错过了语言的主要部分。
联接允许您在一个查询中查询多个表,并从每个表中查找匹配的行。
在您的示例中,我不知道您的第一个查询,但我猜测它会查询其他表以获取用户名列表。也许它会查询作为电子邮件收件人的用户列表,如下所示:
SELECT username FROM EmailRecipients WHERE EmailId = 1234
然后您的代码在第二个查询中使用用户名的结果列表。但是您可以在一个查询中完成所有操作:
SELECT Users.username, Users.status, Users.location
FROM Users JOIN EmailRecipients
ON Users.username = EmailRecipients.username
WHERE EmailRecipients.EmailId = 1234
SQL引擎搜索EmailRecipients表并说它为电子邮件1234的收件人找到六行。对于六行中的每一行,它使用匹配的用户名在Users表中查找相应的行。然后它使用SELECT结果中那些行的列。
当您连接表时,两个表都可能有一些具有相同名称的列。这就是为什么我将命名的列显示为属于一个表或另一个表的原因。这消除了在每种情况下您所指的表格的模糊性。
首先列出哪个表并不重要。这种类型的连接从左到右是相同的,因为它是从右到高的,就像代数中的一些表达式(2 + 4与4 + 2相同,等等)。 MySQL自动确定哪个表最有效率首先阅读。
还有更多关于联接的知识,但这应该让你开始。我建议你在某个时候拿起关于SQL的教程或书。
重新评论:
在第二个查询中," SQL注入易受攻击的方式"?
在您的代码中:
$ result = $ conn-> query($ sql) - > fetch(PDO :: FETCH_COLUMN); $ myArray = explode(',',$ result); $ sql =(" SELECT用户名,状态,位置FROM用户WHERE用户名IN('"。implode("','",$ myArray)。"')AND状态> 0 ORDER BY username"); $ data = $ conn-> query($ sql) - > fetchAll(PDO :: FETCH_OBJ);
无法保证$ myArray中的元素在SQL语句中可以安全使用。仅仅因为他们从数据库中出来并不能保证他们的安全。如果它们包含像" O' Reilly"?这会打乱你的报价内爆。
您永远无法100%确定数据是安全的,因此最好使用查询参数。那么你不关心它是否安全,因为绑定参数永远不会与SQL查询字符串结合。
以下是如何从数组创建IN ( )
谓词的动态列表,并使用PDO将参数值绑定到查询:
$result = $conn->query($sql)->fetch(PDO::FETCH_COLUMN);
$myArray = explode(',', $result);
$placeholders = implode(',', array_fill(0, count($myArray), '?'));
$sql = "
SELECT username,status,location FROM Users
WHERE username IN ($placeholders) AND status > 0
ORDER BY username");
$stmt = $conn->prepare($sql);
$stmt->execute($myArray);
$data = $stmt->fetchAll(PDO::FETCH_OBJ);
答案 1 :(得分:2)
虽然这两个答案都完全有效,但我只是想补充一下,你的问题还有另一个解决方案。
您可以通过在连接数据库的位置定义默认提取样式来更改默认提取样式:
$host = 'localhost';
$user = 'user';
$pass = 'pass';
$mydb = 'mydbname';
$conn = new PDO("mysql:host=$host;dbname=$mydb", $user, $pass, [
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);
或者您可以使用现有连接使用setAttribute()
来更改它:
$conn->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
然后你可以简单地使用:
$conn->query($sql)->fetchAll();
您仍然可以覆盖默认值:
$conn->query($sql)->fetchAll(PDO::FETCH_NUM);
答案 2 :(得分:1)
使用PDO::FETCH_ASSOC
可以将其设为数组。所以
$data = $conn->query($sql)->fetchAll(PDO::FETCH_ASSOC);
文档链接: