2017-04-26 29 views
6

我認爲我在理解OOP的工作方式方面存在問題。我已經改變了它的工作原理,但這不是我想的方式。下面的情況下(不,我不是自己創建一個用戶登陸,它真的只爲本地開發瞭解OOP更好。):瞭解OOP - 如何在其他類中使用PDO連接

我有一個database.php中的文件:

class Database { 

    /* Properties */ 
    private $conn; 
    private $dsn = 'mysql:dbname=test;host=127.0.0.1'; 
    private $user = 'root'; 
    private $password = ''; 

    /* Creates database connection */ 
    public function __construct() { 
     try { 
      $this->conn = new PDO($this->dsn, $this->user, $this->password); 
     } catch (PDOException $e) { 
      print "Error!: " . $e->getMessage() . ""; 
      die(); 
     } 
     return $this->conn; 
    } 
} 

所以在這個類我創建一個數據庫連接,並返回連接(對象?)

然後我有第二類,着名的用戶類(實際上我沒有使用自動加載,但我知道它):

include "database.php"; 

class User { 
    /* Properties */ 
    private $conn; 

    /* Get database access */ 
    public function __construct() { 
     $this->conn = new Database(); 
    } 

    /* Login a user */ 
    public function login() { 
     $stmt = $this->conn->prepare("SELECT username, usermail FROM user"); 
     if($stmt->execute()) { 
      while($rows = $stmt->fetch()) { 
       $fetch[] = $rows; 
      } 
      return $fetch; 
     } 
     else { 
      return false; 
     } 
    } 
} 

這是我的兩個班。如你所見,沒有什麼大不了的。現在,不要關注函數名稱login - 實際上我只是試圖從數據庫中選擇一些用戶名和用戶郵件並顯示它們。我試圖做到這一點:

$user = new User(); 
$list = $user->login(); 

foreach($list as $test) { 
    echo $test["username"]; 
} 

問題在於這裏。當我執行這個代碼,我得到了以下錯誤消息:

Uncaught Error: Call to undefined method Database::prepare()

而且我不知道,我真的知道是什麼原因導致這個錯誤。

代碼工作得很好,當我改變了以下幾件事:

變化$conn在database.php中以公開,而不是私有的(我認爲是壞的......但是,當其私有的,我只能執行?查詢內部的數據庫類,我是對的?所以我應該把所有這些querys在數據庫類?我認爲那很糟糕,因爲在一個大項目中它會變得非常大..)

而第二個更改我要做的是: 在user.php文件中將$this->conn->prepare更改爲$this->conn->conn->prepare。在這裏我真的不知道爲什麼。

我的意思是,在user.php的的構造函數我有一個$this->conn = new Database()以來新數據庫將返回我從DB類連接對象,我真的不知道爲什麼非得是第二conn->

如果有人能更好地解釋我,我會非常感謝。我知道變量的可見性,並且我已經閱讀了很多,但我認爲我現在還不明白,否則我不會有這個問題。

感謝您的每一個建議! :)

+1

構造函數不應該返回任何東西:http://stackoverflow.com/questions/6849572/returning-a-value-in-constructor-function-of-a-class - 有權訪問該方法您的數據庫'class需要擴展'PDO' – CD001

+2

你的錯誤是'$ this-> conn-> prepare('你正試圖在你的Database類上調用prepare函數,但是沒有準備函數,你可以使'$ conn-> conn-> prepare'數據庫的公共''conn'會導致'$ this-> conn-> conn-> prepare'。你的數據庫'__construct()'的返回值正在返回一個數據庫對象而不是連接,即使你'retrun $ this- > conn' –

+0

@ CD001感謝關於構造函數的建議,我會看看它,關於第二點是肯定的,因爲當我將整個'login'函數放在數據庫類中時,它完美地工作,不需要從PDO延伸... – Twinfriends

回答

9
  • 擺脫數據庫類。它增加了什麼什麼PDO已經
  • 香草PDO創建 $ DB實例
  • 把它作爲一個構造函數的參數爲​​每個需要一個數據庫連接

數據庫類。PHP:

<?php 
$host = '127.0.0.1'; 
$db = 'test'; 
$user = 'root'; 
$pass = ''; 
$charset = 'utf8'; 

$dsn = "mysql:host=$host;dbname=$db;charset=$charset"; 
$opt = [ 
    \PDO::ATTR_ERRMODE   => \PDO::ERRMODE_EXCEPTION, 
    \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC, 
    \PDO::ATTR_EMULATE_PREPARES => false, 
]; 
$pdo = new \PDO($dsn, $user, $pass, $opt); 

user.php的

<?php 
class User { 
    /* Properties */ 
    private $conn; 

    /* Get database access */ 
    public function __construct(\PDO $pdo) { 
     $this->conn = $pdo; 
    } 

    /* List all users */ 
    public function get_users() { 
     return $this->conn->query("SELECT username, usermail FROM user")->fetchAll(); 
    } 
} 

app.php

include 'database.php'; 
$user = new User($pdo); 
$list = $user->get_users(); 

foreach($list as $test) { 
    echo $test["username"]; 
} 

輸出:

username_foo 
username_bar 
username_baz 

看看我(The only proper) PDO tutorial更多細節PDO。

+0

天才!這很有道理。這樣我就可以在課堂上保持querys!非常感謝:) – Twinfriends

+1

雖然這是一個很好的解決方法,但我個人不喜歡在我的模型中建立連接。也可以保持它的「乾淨」擴展包含連接方法的基本模型。 –

+0

@NiekvanderMaaden如果你擴展了一個Base模型,那麼你在子類中也有連接。 –