2012-10-09 56 views
7

我一直在努力轉向PHP中的OOP。我有閱讀php.net解釋,但我希望我可以在這裏得到一些具體的答案。如何在PHP中構造類

我試着創建下面的例子來說明我的問題。假設我有「數據庫」,「產品」和「用戶」類,並且我想在用戶有權訪問時顯示產品。因此,我調用「產品」類「showProducts()」函數,該函數依次創建「用戶」類的實例,該實例創建「數據庫」對象的實例並檢查用戶訪問級別。

如果用戶有權訪問,則「showProducts()」函數會創建「數據庫」對象的另一個實例,並查詢數據庫。

class Database{ 

    public function query(){ 
     //runs query here 
    } 

    public function __construct() { 
     //sets up connection here 
    } 

} 

class User{ 

    public function checkAccess(){ 
     $db = new Database(); 
     $db->query(//pass in query to check access) 
     //does stuff, then returns true or false 
    } 

} 

class Products{ 

    public function showProducts(){ 

     $user = new User(); 

     if($user->checkAccess()) 
     $db = new Database(); 
     $db->query(//pass in query to get products) 
     } 

} 

我希望有人能說明如何以正確的方式做到這一點。

我想有某種控制器類的,創建一個「數據庫」對象,即提供給所有需要訪問它的類,而無需創建「數據庫」對象的多個實例。我希望用戶類具有相同的功能,因此有一個$ users用戶可以訪問所有類,而無需在每次需要使用「用戶」類時都創建新對象。

我很抱歉如果我的問題不清楚,並且預先感謝任何回覆!

感謝大家的回覆!

回答

11

將窗體過程移動到面向對象的編程時,應該更多地掌握如何構建類。 OOP不是在編寫類,它關於遵循OOP中的最佳實踐,原則和模式。

你不應該在另一個實例化新對象,你應該通過構造函數或setter方法給User對象,User依賴的他的Database對象。這就是所謂的依賴注入。目標是通過構造函數或setter方法將對象提供給需要它們的類。而且它們應該從該類之外實例化,因此更容易配置類。當你想要建立一個類時,你很容易看到這個類有什麼依賴關係。你可以閱讀有關的控制原理在這裏反轉:IoC

所以,你的代碼應該是這樣的:

<?php 

// User object that depends on Database object, and expects it in constructor. 

class User 
{ 
    protected $database; 

    public function __construct($database) 
    { 
     $this->database = $database; 
    } 

    // -- SNIP -- 
} 

?> 

現在使用你做這個用戶等級:

<?php 

    $database = new Database($connParams); 
    $user = new User($database); 

?> 

你可以也使用依賴注入使用setter方法來設置依賴關係,但是我讓你谷歌爲自己:)

這就是它,joust閱讀關於控制反轉關於依賴注入和依賴注入容器,這些是管理類的最佳方式。

我已經看到很多PHP代碼是「OOP」,事實上它們只是使用類作爲功能命名空間:)所以,你可以瞭解OOP原則和模式。

玩得開心! :)

+0

非常感謝您的回覆!因此,如果我有另一個在用戶類上引用的類,我還會將$ user對象作爲參數傳遞給它? – Ben

+0

是的,你可以!你可以通過儘可能多的類,只要你喜歡。如果對象真的需要該對象來工作,則可以通過構造函數傳遞對象。如果object是可選的,你可以通過setter方法傳遞它。一旦你得到了複雜的依賴關係,那麼你可以考慮使用依賴注入容器來描述依賴關係,而Container將能夠從其他對象組裝對象並將其返回給你:)你可以在這裏閱讀更多關於依賴注入和依賴注入容器:http://fabien.potencier.org/article/12/do-you-need-a-dependency-injection-container – otporan

0

爲了使一個對象所有的代碼使用Singleton模式:

class Database{ 
    private $db_descriptor; 

    private function __construct(){ 
     /* connect and other stuff */ 
    } 
    public static function getInstance(){ 
     static $instance; 
     if($instance === null){ 
      $instance = new self(); 
     } 
     return $instance; 
    } 
} 

你也可以使用與用戶相同的技術,我多說用PHP 5.4,你可以使用1個特質的單例模式。 最後一個提示:當你使用數據庫和其他重要的東西時,使用的技術叫lazy initialization。當你提高你的面向對象的技能看看Doctrine Project他們使用這種技術很多!

+0

實際上,我會建議從企業框架中查看示例,以瞭解如何完成工作。你可能不需要馬上使用,但他們會給你一個關於如何構造事物的好主意。 – prodigitalson

+0

你能建議嗎?我以前沒有和他們一起工作。 – kirugan

+1

Symfony2和Zend2框架是唯一值得關注的框架:)我知道我會得到很多這個選票。但是這兩個是最好的在PHP中學習適當的OOP! – Limeni

2

不要在您的構造函數或其他方法中實例化對象。將它們作爲參數傳遞,最好在不同的工廠中稱爲工廠。這樣可以很容易地測試代碼,但也可以很容易地創建對象。

此外,不要嘗試使用單身。這是「全局變量」的面向對象版本,您不想使用全局變量。它使得你的代碼測試非常困難,幾乎不可能。

觀看此視頻http://www.youtube.com/watch?v=-FRm3VPhseI瞭解爲什麼它不好使用單身。特別是19:00的CreditCard例子值得關注。

如果你真的想要做到最先進的技術,可以看看「依賴注入」的概念。從本質上講,將外部需要的東西傳遞給一個類是完全的祕密,但有些框架會自動爲你做這件事,所以你不必再自己寫一個工廠了。這些被稱爲「依賴注入容器」或「DIC」。

+0

非常感謝!現在Googleing工廠類。你知道關於建立網站的類結構的一般教程嗎?我開始理解原則,但就實際實施而言,我仍然有點失落。 – Ben

+0

首先我建議你看看自動加載。有幾個系統可以簡化這個過程,但歸結起來就是將目錄樹中的類(每個文件一個類)組織到目錄樹中,並相應地對齊類名,以便自動加載器(只將所需的類名作爲參數)構建該類應該在的路徑和文件名。看一看Zend Framework(1或2)的例子。您也可以瞭解其他人如何在那裏爲他們的班級命名。 – Sven

相關問題