2009-04-17 38 views
0

今晚有點花時間在PHP學習一些面向對象的操作,並碰到一堵磚牆。我正在創建一本小書庫應用程序來跟蹤我的書籍收藏,並認爲我將使用面向對象的實踐。查看一些代碼?

我有一個名爲library.php的主要php文件,其中包含2個主要的類到目前爲止。

  1. 級數據庫(連接到MySQL,數據庫等)
  2. 類書籍(包含標題,作者,流派信息等和方法將數據插入到數據庫)

所以,我的問題:

可以爲我的所有類使用一個文件嗎?

而下面的代碼是將書籍添加到數據庫的過程頁面,這是好的,還是我會在錯誤的方向?

另外,我該如何去了解何時在類中創建新方法或創建整個新類?

<?php 
    include 'library.php'; 

    // Connect to Host & DB 
    $database = new database(); 
    $database->mysqlConnect('localhost', 'root', ''); 
    $database->selectDB('books'); 

    // Retrieve Values 
    $book = new books(); 
    $book->retrieveValues(); 
?> 

感謝, 基思

回答

8

在我看來,最好爲每個類創建一個文件,其中文件以該類的名字命名。我使用與乍得樺樹略有不同的符號,即Classname.class.php。類自動加載是一個很好的功能,但我不經常使用它(只有在某些情況下,如MVC,經常添加或刪除相同類型的類)。

關於對象建模:開始爲名詞創建類。確定應用程序中的角色。這樣做的一個方法是記下你的應用程序應該做什麼,然後掃描它的名詞並在這些之後爲你的類建模。因爲一個類代表一個單獨的對象,所以大部分時候類名都是單數。如果有多個對象,你應該把它命名爲ObjectCollection或類似的東西(例如「BookCollection」)。

讓我們試試吧:

我想創建一個小本子庫的應用程序來跟蹤我的藏書。它應該跟蹤我擁有的書籍,流派,作者和我借給他們的朋友。另外,對於每個朋友都應該存儲電話號碼,所以我可以給他打電話。所有的信息都存儲在數據庫中。

  1. Book:代表一本書( 「教父」, 「Cryptonomicon」)
  2. Library:代表書籍
  3. 集合
  4. Collection:已經涵蓋圖書
  5. Genre(「Sci- 「」恐怖片「,」...「)
  6. Author(」Neal Stephenson「,」Mario Puzo「)
  7. Friend( 「喬」, 「吉爾」, 「傑克」)
  8. PhoneNumber(朋友的屬性)
  9. Database(杜)

然後你建立層次結構。哪些對象包含其他對象,它們之間的關係是怎樣的?

  • Library包含0,1或更多Book小號
  • Book屬於一個Genre
  • Book被1個或多個Author小號
  • 我可以借一Book爲0或1寫入Friend並且一次只有一個Friend
  • A Friend有一個PhoneNumber

(這也會告訴你一兩件關於你的數據庫應該如何)。

並非一切都很明顯。你真的需要電話號碼課嗎?這只是一個字符串。在這種情況下,你應該把它變成財產。此外,電話號碼並不是真的在Friend對象之間共享的(如果有幾個朋友住在一起,並且它們經常改變,但是現在這會有點矯枉過正)。如果名詞可以用一個標量值(一個字符串,整數,浮點數)表示,並且沒有其他值連接到它們,那麼創建類可能會過度。

因此,隨着時間的推移,你擴展你的應用程序。你決定不僅存儲電話號碼,而且還存儲地址。地址和電話號碼是非常相似的信息類型,因此您可以爲街道,城市,郵政編碼等添加其他變量。在某個時候,你會感到沮喪,因爲Friend類增長巨大,有很多屬性,getters-和setters-方法,其中一些前綴將它們組合在一起(Friend->addressStreet,Friend>addressPostCode等)。因此,您可能決定將其重新定位到自己的類,稱爲Address(如果您將電話號碼保留爲Friend)或Contact,只是爲了保持代碼清潔(沒有錯誤,但要小心)。

類層次結構和對象層次結構如何?不要混淆它們,它們是完全不同的東西!如果類似的類共享某些屬性,但是在其他屬性上不同,則會出現類層次結構。因此,您可以使用它們共享的屬性和方法以及繼承父級的屬性和方法的子類創建一個類,並添加它們自己來處理差異。

在我們的圖書館例子中,那可能是什麼?說實話,除了一件有點無意義的事情之外,我想不出任何東西,但我們不妨去想它... Friend s和Author s都是Person s!都有姓名,電話號碼和地址。但他們也不同,因爲作者寫書和朋友不寫(作者通常不借你的書)。因此,您可能會定義和Address - Person類中的對象,但getUnreturnedBooks()明確屬於Friend,而getBooksWritten()屬於Author

它沒有意義,因爲你永遠不會在同一運行中處理Author s和Friend s。但讓我們說你需要存儲在你的圖書館中的所有地址列表,你可以循環你的收藏人員,並致電getAddress()。說實話,即使PHP是一個不好的例子,因爲你可以將任何你想要的類型一起存儲在一個數組中,並以任何你想要的方式訪問它們,但是在強類型語言中是不可能的。在Java中,你必須爲一個數組定義一個數據類型,如果它們有一個公共繼承(但你僅限於原始類的方法),則可以存儲不同的類型。足夠的那個類繼承巫術。

對象層次結構只是說明哪些對象應該包含其他對象。 A library包含book對象。 A book包含一個author對象。

的其他建議:

  • 嘗試是描述性的。不要使用像Library->retrieveValues()這樣的名稱,將它命名爲Library->getBooks(),因爲Book對象就是您所得到的。

  • 有時最好在數據類型返回後命名方法。如果他們返回布爾值,這很常見。良好的命名約定可能是hasis,如Friend->hasBook($book)Book->isInLibraryCurrently()

  • 對於某個類的所有對象來說總是相同的值可能是類常量。比方說,如果一個Person可以是男性或女性,並且您將其存儲爲數據庫中的「m」或「f」,則可以定義類常量Person::GENDER_MALE = 'm'Person::GENDER_FEMALE = 'f',因此您沒有「m」s和「f」分散在你遍歷的SQL查詢中。

  • 只生成單個實例的類可以建模爲單例。一個很好的例子可能是數據庫類 - 它不太可能需要一次打開多個事務。閱讀更多關於維基百科的單身人士(http://en.wikipedia.org/wiki/Singleton_pattern),但可能有點早。

更新:有些人認爲單身人士一個壞主意,因爲他們或多或少「刻在石頭上,」一旦他們實現這種方式。因此,如果您將Database類作爲單例建模,但後來決定需要多個數據庫連接(不太可能,但可能),則會出現問題。如果你冒險,單身人士可能會很方便。

1

我認爲面向對象編程的思想,部分是類和邏輯分離,因此可能會更好每個等級達到拆分成單獨的文件。至於何時在類或新類中創建新方法,我認爲如果您使用的方法與該特定類的主要操作有關,則應該添加它。只有在執行例程或重要功能時才能創建新類,並將正確的邏輯保存在正確的類中。

+0

類和邏輯是分開的嗎?你什麼意思? – 2009-04-17 09:30:46

3

對不起,我沒有時間來解決你所有的問題在此刻(我會回來這個明天早上),但我可以快速回答第一個:

是否確定爲我的所有課程使用一個文件?

它在技術上是「OK」,因爲在語言允許你這樣做,但你不應該這樣做。除了改進代碼組織的好處之外,它還允許您使用稱爲Autoloading Objects的PHP的一個很好的功能。

如果按照例如頁面所顯示,您可以如下定義__autoload功能:

function __autoload($class_name) 
{ 
    require_once $class_name . '.php'; 
} 

這使得它,這樣你就不必明確地包括所有與你的類定​​義的文件。相反,只要將它們放入與類名稱相同的文件中,自動加載將自動包含所需的文件。也就是說,在你的代碼中,你顯示你有一個名爲「books」的類。如果這個類的定義保存到一個名爲「books.php」文件,當你有這樣一行代碼:

$book = new books(); 

PHP將自動包含在該點books.php。這非常方便,並且絕對是將每個課程保存在自己的文件中的好動力。

+0

我從來沒有發現__autoload可讀。事實上,當我認爲自己有東西是自動加載的時候,它一直是令人困惑的原因,但我最終沒有。最好是明確的。 – 2009-04-17 05:56:56

+0

非常感謝你 – 2009-04-17 07:43:50

2

一個類是一個函數和屬性的集合。如果你需要完成一個特定的動作,那麼你創建一個新的功能。如果您需要一種可以對其執行一組不同操作的數據,則可以創建一個新類。

而且由於我看到您使用的是MySQL,因此您應該檢查預準備語句(http://us2.php.net/pdo.prepared-statements)以避免不安全的代碼。 PS:我會命名類「書」而不是「書」。想想它宣佈的方式 - new books()?您正在創建一本新書,因此new book()似乎更合適。

+0

歡呼,k感謝你的反饋 – 2009-04-17 07:44:43

1

您可能會考慮的另一件事是使用已編寫的數據庫庫。關於編程,特別是面向對象的最好的事情之一就是能夠重複使用各個部分來創建不同的整體。就個人而言,我用ADODB以優異的成績。我同意將這些課程放在單獨的文件中,既可以用於自動加載,也可以讓您將它們分開放置在頭腦中。您是否介意在這裏發佈您的課程副本,以便我們更好地瞭解他們的內部工作方式,而不僅僅是方法名稱?