更新該類的最好方法是在它旁邊創建一個新的恕我直言。這將允許您逐步更改代碼而不破壞現有代碼(或至少以更受控制的方式)。
您可以通過首先將接口從現有類中提取出來,然後實現實現相同接口的新類來實現。
你用PHP Storm這樣的IDE最容易做到這一點,但這不是必需的,你也可以手工完成。
首先你提取接口出db
類,例如DbInterface
(在PHPStorm在類名「DB」單擊鼠標右鍵,然後選擇重構 - >提取物 - >接口):
interface DbInterface {
/**
* @param $link
* @return mixed
*/
function close($link);
/**
* @param string $query
* @return mixed
*/
function query($query);
function connect();
}
我還添加了一些缺少的docblock評論。此外,我們做db
類來實現接口:
class db implements DbInterface {
現在再次測試你的代碼,一切都應該運行沒有任何問題。
這個界面已經顯示了一些毛病,你最好是值得大家注意的,所以我們沒有在以後想念他們:
- 該類的對象配置了一些代碼,分配數據庫配置和憑據通過公共成員,所以有其他代碼(在你的問題中不可見)。隨着數據庫客戶端庫的更改,類的配置方式也可能會發生變化。配置代碼也應該被封裝,以便它可以被替換(例如移入類或配置對象)。
- close方法需要從外部連接數據庫。由於類本身控制連接,所以該鏈接實際上應該是內部信息。
此時您可以決定如何繼續。我建議你從2開始。)首先重構代碼,以將該變量拉入$link
,而不是將其外部化爲類。然而,外化可以做到很好,它只是需要一個新的類型,那麼其被引入作爲一個新的接口:
interface DbLinkInterface {
/**
* @return mixed
*/
public function getLink();
/**
* @return DbInterface
*/
public function getDatabase();
public function close();
}
該接口則是由一類新的主要封裝有關該鏈接的細節實現:
class DbLink implements DbLinkInterface
{
private $link;
/**
* @var DbInterface
*/
private $db;
public function __construct($link, DbInterface $db) {
$this->link = $link;
$this->db = $db;
}
/**
* @return mixed
*/
public function getLink() {
return $this->link;
}
/**
* @return DbInterface
*/
public function getDatabase() {
return $this->db;
}
public function close() {
$this->db->close($this);
}
}
當您現在測試它時,您的代碼仍然應該完美無缺。在每一步之後進行測試。
接下來就是將這個類引入到現有的類中,以便數據庫鏈接可以作爲具體類型傳遞。這一步有點危險,因爲根據你在其他地方的代碼中如何使用$link
,所以事情可能需要更多的更改才能像往常一樣運行,所以你需要測試。你可能例如至少
mysql_something($link->getLink());
更換
mysql_something($link);
但是你實際上必須從那裏刪除功能。所以改變$link
的類型實際上使所有這些地方可見。到DbInterface
然後添加方法和/或DbLinkInterface
,這樣你可以做的事情更流暢:
$link->something();
但是,這在很大程度上取決於你的代碼,以及如何好你與重構(見鏈接的重複問題它建議採用不同的方式掃描所有文件,並使用兼容的API自動替換,如果您認爲不值得通過抽象進行分支)。
首先,在DbLinkInterface
引入DbInterface
:
interface DbInterface {
/**
* @param DbLinkInterface $link
* @return void
*/
function close(DbLinkInterface $link);
...
這將使現有的代碼失敗,因爲該接口不是db
,然後至少需要這種改變感到滿意:
class db implements DbInterface {
...
function close(DbLinkInterface $link) {
if ($link->getDatabase() instanceof $this) {
return mysql_close($link->getLink());
}
throw new InvalidArgumentException('Invalid Link given. Can only close link of my own type.');
}
}
現在可以再次加載代碼,但是在傳遞鏈接到close
的地方會出現致命錯誤。因此返回該鏈接時,該類db
需要另一個變化:
class db implements DbInterface {
...
function connect() {
$link = mysql_connect($this->host . ':' . $this->port, $this->login, $this->pass);
return new DbLink($link, $this);
}
...
當您使用的鏈接只關閉數據庫連接(因爲它看起來像一個位),你的整個代碼應該重新工作。測試它看到如此。
所以現在最後老的類已經被抽象成兩個接口,這將允許你更容易地替換它。這意味着您將添加額外的代碼,以便舊應用程序仍可以使用舊代碼運行,並且您還可以使用新代碼進行測試。您只需在使用它的位置進行更改,通常是單個對象實例(變量)。
所以,現在你介紹一個使用新的數據庫客戶端API類:
class db_mysqli extends db implements DbInterface {
/**
* @var mysqli
*/
private $db;
function connect() {
$this->db = new mysqli($this->host, $this->login, $this->pass, $this->data_base, $this->port);
return new DbLink($this->db, $this);
}
function query($query) {
return $this->db->query($query);
}
function close(DbLinkInterface $link) {
if ($link->getDatabase() instanceof $this) {
return $link->getLink()->close();
}
throw new InvalidArgumentException('Invalid Link given. Can only close link of my own type.');
}
}
現在你可以使用這個類,而不是另一種互換,所以出於測試目的,並且你不需要在你的整個應用程序中使用它,或者你可以通過腳本或類似的腳本移動腳本。
如本例所示,外部化的鏈路確實引入需要被第一次封裝的差異。
因爲你不更改數據庫服務器,配置和您的舊代碼的某些部分可以保持。
置於版本控制之下你的代碼,所以你可以很容易地一步做到這一步,也恢復的情況下,你介紹一個錯誤和/或此處列出的概念一不爲你工作。
我希望這是有幫助的。記住要做小步驟,並考慮如何在不改變舊的代碼的情況下引入新的代碼。例如。就像我在這裏做了一個新班,而不是改變舊班。
爲了使這個過程更加健壯,你還可以引入斷言,看到Should I be using assert in my PHP code?,瞭解有關的更多信息。
順便說一句,不推薦使用的東西不(但)意味着您需要更改代碼。它仍然有效,它只是警告你,接下來你需要計劃重構代碼以利用新的數據庫客戶端API。這是一個警告,不是一個致命的錯誤。 PHP手冊指導瞭如何從一個PHP版本遷移到另一個PHP版本。 3至4:http://www.helmholtz-muenchen.de/ibb/homepage/karsten.rodenacker/php_html/migration4.html 4至5:http://php.net/manual/en/faq.migration5 .php – hakre