簡體   English   中英

在PHP中遇到關聯數組結構的麻煩

[英]Having trouble with associative array structure in PHP

不太確定如何表達這個問題,但是我在編寫的類中遇到了一個關聯數組的結構問題。 代碼的相關部分如下所示:

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'];

我必須添加數組索引才能訪問任何數據,我不想這樣做,但是我不知道如何解決此問題。

這與PDOStatement :: fetchAll()返回行數據的方式有關。

即使您僅選擇一行,它仍將返回行索引(零),即,如果您這樣做的話

print_r($row);

你會得到這樣的東西

Array
(
    [0] => Array
        (
            [username] => Roy
            [0] => Roy
        )
)

請注意,默認情況下,fetchAll()返回數據中的每一列兩次-按列名一次,按列索引一次

您為變量$row命名的事實可能是絆倒您的一部分-語義上應該是$rows

要解決此問題,您有幾種選擇

  1. 直接訪問結果的第一行

     $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); // Notice the addtion of the foreach($rows[0] AS $key => $val) 
  2. 使用PDOStatement :: fetch()代替

     $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器或設置器的方法應避免使用getset作為前綴
    • 可能的獲取替代方案:查找,獲取,獲取,定位,提取,訪問
    • 可能的替代設置 :推送,應用,制作,發布,標記,附加,分配

這意味着開發人員可以編寫不僅返回類屬性的get*()方法,而且鼓勵他們不要這樣做

因此,當我說“提取程序”時,這是一個口語化的術語,並不是真正的通用軟件工程術語的一部分。

更好的方法

這是一個示例,其中我們對關注點進行了嚴格的分離 用戶數據的“獲取”和“獲取”分別具有自己的實現,即自己的方法。

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()添加保護檢查,以防PDO::fetch()返回FALSE 也許像

$user = $stmt->fetch(PDO::FETCH_ASSOC);
if (false === $user)
{
  throw new Exception("User with id ($this->ID) not found");
}

問題是您的$stmt->fetchAll() ,在您的查詢中確實暗示您正在嘗試獲取單行。 您需要將其替換為$stmt->fetch()

原因是因為在您的示例中,每行的$ key是行索引,所以對於第0行,您的賦值語句是:

$this->userData[0] = $val;

您要做的是使用兩個字段的值將值分配給數組(我猜):

$this->userData[$val['field1']] = $val['field2'];

要么,

$this->userData['username'] = $val['username'];

但是,我認為真正的問題是,您試圖獲取一行並取而代之以獲取結果數組-並在無意中遍歷行,而不是您認為的字段。

如果要查找單個用戶記錄,則需要使用關聯的單個訪存,而不是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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM