2015-06-12 118 views
1

我將盡我所能盡力解釋這一點,如果零件不具有完全意義,請原諒我。我正在構建一個用於教育目的的PHP庫/框架。我正在使用singleton模式構建它,但遇到了一些問題,最近似乎也認爲它不應該被使用,因爲它不是非常可測試的(儘管我並不擔心這是可測試的,但我想學習如何去做),而應該使用依賴注入。使用Dependancy Injection和共享變量的PHP設計模式?

我想要的是一個共享變量,如果你願意的話,它可以容納許多不同的類。例如$ app-> database; $ APP->的意見; $ APP->會議;等等,而且我不確定我是否正在做這件事。所有的課程也被自動加載。

我有引導/ start.php它初始化主變(有一個名字嗎?)有:

$app = new App(new Database, new Views, new Session); 
在App.php類

我使用的主要有:

public $database; 
public $views; 
public $session 

public function __construct(Client $client, Views $views, Session $session) 
{ 
    $this->database = $database; 
    $this->views = $views; 
    $this->session = $session; 
} 

我的問題是這樣的:我應該在構造函數中初始化所有的類嗎?還有一個大問題......如何在我的Views.php類中使用$ database變量而不創建可能會覆蓋Database類中某些屬性的全新實例?

希望能對此有所瞭解。

+0

作爲一種方式,您可以在應用程序中創建靜態方法,它將返回數據庫,視圖實例 – sergio

+2

您應該尋找像'Pimple'或'Symfony'這樣的容器,並創建'Client','Views',Session'服務。這樣,容器包含每個服務的1個實例。 現在對於依賴注入,如果'View'服務需要'Database'服務,那麼在他的構造函數中,你必須在裏面注入一個'Database'對象,並且在他的服務聲明中注入數據庫'服務' – Med

+0

@Med謝謝答覆。我以前使用過Symfony容器,但是想看看我是否可以從頭開始自己解決一些問題。 – PumpkinJack

回答

-1

你的代碼看起來不錯,但我會推薦這些更改,使變量私人併產生getter和setter。

<?php 
Class App { 

private $database; 
private $views; 
private $client; 
private $session; 

/** 
* 
* @param type $database 
* @param type $views 
* @param type $client 
* @param type $session 
*/ 
function __construct($database, $views, $client, $session) { 
    $this->database = new $database; 
    $this->views = new $views; 
    $this->client = new $client; 
    $this->session = new $session; 
} 

/** 
* 
* @return type 
*/ 
function getDatabase() { 
    return $this->database; 
} 

/** 
* 
* @return type 
*/ 
function getViews() { 
    return $this->views; 
} 

/** 
* 
* @return type 
*/ 
function getClient() { 
    return $this->client; 
} 

/** 
* 
* @return type 
*/ 
function getSession() { 
    return $this->session; 
} 

/** 
* 
* @param type $database 
*/ 
function setDatabase($database) { 
    $this->database = $database; 
} 

/** 
* 
* @param type $views 
*/ 
function setViews($views) { 
    $this->views = $views; 
} 

/** 
* 
* @param type $client 
*/ 
function setClient($client) { 
    $this->client = $client; 
} 


/** 
* 
* @param type $session 
*/ 
function setSession($session) { 
    $this->session = $session; 
} 

} 
//and in bootstrap or where you loading just do this and make database, view and all other singleton. 
$database = database::getInstance(); 
$views = views::getInstance(); 
$client = client::getInstance(); 
$session = session::getInstance(); 
$App = new App($database, $views, $client, $session); 
+0

您的更改不好,因爲:您違反了德米特法,您宣傳了一種被稱爲緊密耦合的不良做法 – Yang

+0

我完全同意您的意見@DavidY,但我相信這是應用程序啓動時的啓動部分,我認爲我們需要緊密耦合。 –

+1

無需緊耦合就可以輕鬆完成。這裏是服務定位器,然後它被注入 – Yang

1

你應該瞭解MVC樣的架構是什麼,是他們基於整個點稱爲關注(SoC)的分離。

爲什麼你會在視圖中訪問數據庫連接?很明顯,因爲你想在那裏執行查詢並顯示結果。這就是破壞SoC的原因。爲了顯示數據,必須訪問模型中的數據庫連接,如果需要可以以某種方式解析,然後簡單地將準備好的數組傳遞給視圖,以便視圖甚至不知道數據庫是否存在等,他們只知道有一個數組,需要以某種方式顯示。這種方法引入了一個主要優勢 - 您可以輕鬆地交換數據庫引擎(無論是SOAP/REST,Mongo,還是其他),而無需觸及視圖!

至於你的問題,你可以通過創建一個抽象類來解決這個問題,該類將被稱爲AbstractApplication,並將所有這些初始化邏輯放在那裏。然後你可以簡單地繼承這個基類。

您擁有的另一種方法是使用所謂的服務定位器來處理它。你創建一個包裝器,把你所有的依賴關係放在那裏,然後你只需要爲需要它的類注入服務定位器。這不是最好的方法,但它是處理大量依賴關係的唯一方式(在現實世界中,您將有超過4個參數被注入)

+1

沒有參數的Downvotes是跛腳 – Yang

+0

我認爲綁定數據庫(模型)和視圖(模板)需要Controller類 –

+0

1)視圖不是一個模板,而是一個由UI邏輯和模板組成的圖層。 2)模型不是一個類,而是由存儲抽象和域對象組成的抽象層。 3)他沒有說這是MVC。正如我在開頭的答案中所說的那樣,** SoC全部是關於類似MVC的體系結構** – Yang