不太确定如何表达这个问题,但我在编写的类中遇到了关联数组的结构问题。代码的相关部分如下:
class User {
public $userData;
function getUserData() {
$stmt = $this->conn->prepare('SELECT * FROM user_table WHERE id = :id');
$stmt->execute(array('id' => $this->ID));
$row = $stmt->fetchAll();
foreach($row AS $key => $val) {
$this->userData[$key] = $val;
}
return $this->userData;
}
我希望能够使用它来设置类属性,以便我可以像这样访问它们:
$this->userData['username'];
例如,,但这对我不起作用。相反,我必须像这样访问它们才能工作:
$this->userData[0]['username'];
我必须添加数组索引才能访问任何数据,我不想这样做,但我不知道如何解决这个问题。
答案 0 :(得分:2)
这与PDOStatement::fetchAll()返回行数据的方式有关。
即使您只选择一行,它仍将返回行索引(零),即,如果您这样做
print_r($row);
你会得到这样的东西
Array
(
[0] => Array
(
[username] => Roy
[0] => Roy
)
)
请注意,默认情况下,fetchAll()会在数据中返回两次列 - 一次按列名称,一次按列索引
您为变量$row
命名的事实可能是绊倒你的一部分 - 在语义上应该是$rows
。
要解决此问题,您可以选择几个
直接访问结果中的第一行
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC); // Notice the addtion of the
foreach($rows[0] AS $key => $val)
$row = $stmt->fetch(PDO::FETCH_ASSOC); // Notice the addtion of the
foreach($row AS $key => $val)
但在这两种情况下,for循环都是不必要的。你可以简单地做
$this->userData = $stmt->fetch(PDO::FETCH_ASSOC);
最后,我必须质疑为什么User::$userData
是公开的,但你也为它写了一个吸气剂(从学术角度讲,它甚至不是吸气剂 - 它是一个吸气剂)
在编写返回某些内容的方法时,人们使用 get 作为选择的动词并不罕见。但是,有一个同样广泛的思想流派,即吸毒者应该仅限于返回班级成员 。在我工作的地方,我们在编码标准中有关于方法命名的这些内容
get
和set
作为前缀
这意味着允许开发人员编写不只返回类属性的get*()
方法,但不鼓励他们这样做。
所以当我说“fetcher”时,这是一个口语术语,而不是普通软件工程白话的一部分。
以下是我们应用了一些separation of concerns严谨性的示例。用户数据的“获取”和“获取”每个都有自己的实现,即他们自己的方法。
class User
{
private $userData = null;
/**
* Lazy-load-style getter for $userData
*
* @return array
*/
public function getUserData()
{
if (null === $this->userData)
{
$this->userData = $this->fetchUserData();
}
return $this->userData;
}
/**
* Fetch the user's data from the database
*
* @return array Associative array of user data where the keys
* are column names
*/
private function fetchUserData()
{
$stmt = $this->conn->prepare('SELECT * FROM user_table WHERE id = :id');
$stmt->execute(array('id' => $this->ID));
return $stmt->fetch(PDO::FETCH_ASSOC);
}
}
虽然如果User::fetchUserData()
返回 FALSE ,我建议在PDO::fetch()
添加一次警卫检查。也许像是
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if (false === $user)
{
throw new Exception("User with id ($this->ID) not found");
}
答案 1 :(得分:1)
问题在于您的$stmt->fetchAll()
,在您的查询中,它确实暗示您正在尝试获取单行。您需要将其替换为$stmt->fetch()
答案 2 :(得分:1)
原因是因为在您的示例中,每行的$ key是行索引,因此对于第0行,您的赋值语句为:
$this->userData[0] = $val;
您要做的是使用两个字段的值将值分配给数组(I'猜测):
$this->userData[$val['field1']] = $val['field2'];
或者,
$this->userData['username'] = $val['username'];
然而,真正的问题是,我认为,你试图获得一行并取代一系列结果 - 而无意中迭代行,而不是你认为的字段。< / p>
如果您要查找单个用户记录,则需要使用关联单次提取,而不是fetchAll:
class User {
public $userData;
function getUserData() {
$stmt = $this->conn->prepare('SELECT * FROM user_table WHERE id = :id');
$stmt->execute(array('id' => $this->ID));
$this->userData = $stmt->fetch(PDO::FETCH_ASSOC);
return $this->userData;
}