2017-01-25 34 views
1

我有以下代码:PHP/MySQL的:数组代替stdClass的对象

$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

*但我真的只是想看到一个二维数组没有它在每个项目的前说stdClass的对象*那么,为什么在地球上,你再审使用'PDO对象:: FETCH_OBJ'?只需将该常量移除或更改为'FETCH_ASSOC',即可解决问题。 – Xorifelse

+0

也许你可以使用'PDO :: FETCH_ASSOC'? – Ibu

+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,你应该知道如何做一个连接。不知道SQL中的连接就像你认为你知道PHP,即使你不知道如何使用foreach()。从技术上讲,你仍然可以做一些事情,但是你错过了语言的主要部分。

连接允许您在一个查询中查询多个表,并从每个匹配的表中查找行。

在您的示例中,我不知道您的第一个查询,但我会猜测它会查询其他表以获取用户名列表。也许它会查询谁是电子邮件的收件人用户的列表,像这样:

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注入脆弱的方式在第二查询”?

在您的代码:

$结果= $ conn->查询($ SQL) - >取(PDO :: FETCH_COLUMN); $ myArray = explode(',',$ result); $ sql =(“SELECT用户名,状态,位置FROM Users WHERE用户名IN('”。implode(“','”,$ myArray)。“')AND状态> 0 ORDER BY用户名”); $ 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); 
+0

首先,我将在项目上线之前对所有非注入性内容进行研究。如果有一个网站可以自动将php btw中的所有语句转换为安全的语言,那将会很棒:)我不熟悉JOIN,这将如何工作? –

+0

非常感谢Bill Karwin!你对第一次获得正确答案有一个有效的观点。幸运的是,我没有实际的截止日期 - 只是todo的一长串清单,这是一个稍后要研究的任务。整个安全事情不能因为我在这里做的事情而受到损害,而且我已经让自己意识到,如果不安全,没有人愿意使用我正在开发的东西。感谢JOIN课程,我将尝试查看代码是否可以更有效地重写! –

+0

不知道是否这是正确的事情发表评论2个月以上的东西,但现在我坐着,并通过我所有的PHP代码,这是不是很多,并希望得到它的保护注射。据我所知,在使用PDO对象时,查询中的事情是安全的,这是代码中的两个查询的情况。所以,我很高兴知道我错在哪里:第二个查询中的“SQL注入易受攻击的方式”在哪里? –

1

使用PDO::FETCH_ASSOC你可以把它作为一个数组。所以

$data = $conn->query($sql)->fetchAll(PDO::FETCH_ASSOC); 

文档链接:

PDO Statement

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); 
+1

是的,这是一个很好的提示! –

+0

确实非常有用! –