symfony 初始化资料模型
2010-01-25 09:31:33   来源:   评论:0 点击:

昨天的複習

經過第一天,有點長但稍微有趣的學習,我們看到如何安裝 symfony 框架,設定一個新的程式和開發環境,然後將源碼安全的從源碼版本控制拿回來。BTW,第一天產生的源碼,已經在 askeet SVN 源碼倉庫裏:

http://svn.askeet.com/

第二天的目標,定義最終的結果應該和功能,粗略的資料模型,開始寫源碼。將會包含產生一個物件相關的映射和程式scaffolding交互的使用它來新增,讀取,修改資料庫裏的記錄, 內容也是不少,讓我們快開始吧

項目的內容揭曉

(askeet是一個新字,其官方網站也沒直接解釋這個字,隨後跟著ASK IT,FIND IT,ANSWER IT,發問,找答案,回答問題)

什麼是你想要知道的?那是個有趣的問題。有很多有趣的問題,如:

  • 今晚我將和我的女友做什麼?
  • 我如何增加我的部落格的流量?
  • 最好的網站框架是?
  • 巴黎最物美價廉的旅館是?
  • 生活,宇宙萬物的終極答案是?

這些問題不會只有唯一解,最好的答案通常是萬中選一,事實上,只有一個答案的目題常是最無趣的(如,1+1=?)但是網頁只有一個解,這是不公平的

逛逛 askeet。這網站致力於幫助人們對他們的問題找答案。誰來回答這些難對付的問題?每個人皆可。每個人也可以評比別人的答案,然後最受歡迎的答案會最受注目。當一堆問題產生,要用一個分類或子分類來組織它們幾乎是不可能的事,所以提問者要會貼標籤(tag), 可用他/她想要的任何字眼。”à la” del.icio.us.當然最受歡迎的標籤會容易冒出來。

假如一個人想要追蹤一個特殊問題的答案,他/她可以訂閱這問題的 RSS feed 。這些功能必須是高雅的和輕量的,讓所有的互動不要跑到下一頁,而是一種 AJAX 的型式。最終,一個後端是需要的->處理一下垃圾問題和答案,有鼓勵性人工的推一個問題。

然後你會問:這類網站似曾相識?當然,有類似的網站,但和 faqts, eHow, Ask Jeeves 這類的網站比較,它們是少了共同的答案,沒有AJAX,沒有 RSS 沒有 tags ,所以和本站並不相同。我們是強調 web 2.0 的服務。

譯註:(web 2.0的網站目前有很多成功的範例,簡單之外,還要讓人家樂於參與,然後衝高流量,昨天(10/11),google用16億買下了youtube, 這個供大家上傳10分鐘以下短片的網站也是 當紅的web 2.0範例,也創造了不少的話題性,主要是使用者會上傳一些有版權爭議的影片,一般是認為google藉此一舉變成最大的電視台,可提供最多的節目,不用攝影棚,不用養演員,只要提供頻寬,超大的頻寬,所以南韓的寬頻基礎建設,是google下一個攻佔的目標。當紅的超女在上面應該都找得到)

Askeet最大的理想,希望不只是個網站,也是個任何人可以下載,在家或公司安裝,用力修改或新增特性。源碼也將用open-source license釋出。

你的人力資源的頭頭在找一個知識管理的系統嗎?你想要跟催修理你的車子的所有點子?你不必建一個常問問題集在你的網站?不要再找個不停,只要有 askeet 。當然,askeet將會出現,這是我們的耶誕節禮物。

從那開始?

你想怎麼展開一個 symfony 程式?全靠你。你可以寫故事,做個計劃,找個同伴來 pair programming (假如你是個XP熟手),或寫個仔細的規格,如果你是個UML迷,你可以畫一下所有的bjects, states, interactions。

不過,這教程不是一個程式的一般開發過程,所以我們直接用一個關聯資料庫模型來開始,然後一個接一個的加特性。重要的是,每天要有一個能跑的程式。不是龐大但還不能產出任何東西的源碼。在真實世界裏,我們將對所有特性做單元測試,但我們相信我們沒有那麼多時間做品保。有一天會專門來講單元測試,所以請繼續閱讀。

這個項目裏,我們用 MySQL 加上InnoDB 的特性,利用一致性的限制和交易的支援。一開始,我們會用 SQLite ,為了避免設定資料庫的細節,在databases.yml 要有一些修改,我們留給你研究,算是個習題。

资料模型

 

Relational model

明顯的,有’question’ , ‘answer’ 兩個表,我們也要’user’表,和’interest’表來放對某問題有興趣的人,’relevancy’是放人和答案的關係。

一個提問(回答)的人,將要提一個問題,也可以推崇一個答案,或是宣告對一個問題的興趣,提問者不一定要對上一個答案,但答案總是可以和人有關連,所以有提供熱門回答的人可以容易被識別出來,沒有指定人的答案將會是一個一般使用者的貢獻。叫匿名烏雅。這是容易被了解的用一個 entity relationship圖。

注意我們在每一個表都已經宣告一個欄位: created_at 。 created_at 可以認出這種欄位,會自動填入系統時間到這種欄位裏,當新增一筆記錄時。同理 ,updated_at也是這樣處理:當修改一筆記錄時,系統時間會自動加入這個欄位。

schema.xml

這個關連性的模型必須翻譯成一個讓symfony能理解的設定檔。這就是 schema.xml 的目的。放在askeet/config/ 目錄下。

有兩者方法來寫這個檔:手寫,也是我們喜歡的方式。或是從一個現存的資料庫產生。讓我們看看第一種解法。首先。我們必須要重新命名這個樣本。

$ svn rename config/schema.xml.sample config/schema.xml

schema.xml的文法是相當簡單的,在Propel 網站上有詳細的說明,這是個XML,每一個<table> tags 裏有<column>, <foreign-key> and <index>tags. 一旦你寫一個

<?xml version="1.0" encoding="UTF-8"?>
  <database name="propel" defaultIdMethod="native" noxsd="true">
     <table name="ask_question" phpName="Question">
        <column name="id" type="integer" required="true" primaryKey="true" autoIncrement="true" />
        <column name="user_id" type="integer" />
        <foreign-key foreignTable="ask_user">
          <reference local="user_id" foreign="id"/>
        </foreign-key>
        <column name="title" type="longvarchar" />
        <column name="body" type="longvarchar" />
      <column name="created_at" type="timestamp" />
        <column name="updated_at" type="timestamp" />
     </table>
     <table name="ask_answer" phpName="Answer">
        <column name="id" type="integer" required="true" primaryKey="true" autoIncrement="true" />
        <column name="question_id" type="integer" />
        <foreign-key foreignTable="ask_question">
 
        <reference local="question_id" foreign="id"/>
      </foreign-key>
      <column name="user_id" type="integer" />
      <foreign-key foreignTable="ask_user">
         <reference local="user_id" foreign="id"/>
      </foreign-key>
      <column name="body" type="longvarchar" />
      <column name="created_at" type="timestamp" />
    </table>
    <table name="ask_user" phpName="User">
      <column name="id" type="integer" required="true" primaryKey="true" autoIncrement="true" />
      <column name="nickname" type="varchar" size="50" />
      <column name="first_name" type="varchar" size="100" />
      <column name="last_name" type="varchar" size="100" />
      <column name="created_at" type="timestamp" />
    </table>
    <table name="ask_interest" phpName="Interest">
      <column name="question_id" type="integer" primaryKey="true" />
      <foreign-key foreignTable="ask_question">
         <reference local="question_id" foreign="id"/>
      </foreign-key>
      <column name="user_id" type="integer" primaryKey="true" />
      <foreign-key foreignTable="ask_user">
         <reference local="user_id" foreign="id"/>
      </foreign-key>
      <column name="created_at" type="timestamp" />
    </table>
    <table name="ask_relevancy" phpName="Relevancy">
      <column name="answer_id" type="integer" primaryKey="true" />
      <foreign-key foreignTable="ask_answer">
         <reference local="answer_id" foreign="id"/>
      </foreign-key>
      <column name="user_id" type="integer" primaryKey="true" />
      <foreign-key foreignTable="ask_user">
         <reference local="user_id" foreign="id"/>
      </foreign-key>
      <column name="score" type="integer" />
      <column name="created_at" type="timestamp" />
    </table>
 </database>

注意在這個檔裏,資料庫的名稱是設成 propel ,是實際的資料庫名。這是一個參數, 被用來連接symfony 框架的 Propel 層。真實的資料庫名稱是定義在databases.yml 設定檔(請看下面)。也有另一個方法來產生 schema.xml ,假如你有一個已經存在的資料庫 ,且你也熟悉一個資料庫的設計工具,你會比較喜歡從被產生的MySQL資料庫建這個結構檔。在你這樣做之前,你只要編輯在askeet/config/的 propel.ini檔輸入你的資料庫的連接設定:

propel.database.url = mysql://username:password@localhost/databasename

在這裏 ,帳號,密碼,主機,資料庫名都是你資料庫實際上的設定值,你現在可以呼叫

$ symfony propel-build-schema

命令來產生 schema.xml

注意:有一些工具可以讓你圖形化的方式建一個資料庫(例如:Fabforce's Dbdesigner),可直接產生schema.xml (透過DB Designer 4 TO Propel Schema轉換器)

譯註: 我覺得如果舉phpmyadmin會更好,不但是圖形界面,而且是WEB界面,易用性超高,幾乎無所不能,只限於對mysql。)

物件模型建立

請用 InnoDB 引擎,請在askeet/config/目錄下的 propel.ini 加一筆記錄

propel.mysql.tableType = InnoDB

一旦 schema.xml 建立,你可根據關係模型來建立物件模型,在 symfony ,這物件關係的映射是由 Propel 處理。封裝進 symfony 指令

$ symfony propel-build-model

上述指令(你必須在askeet項目裏的根目錄下指令)會產生 相對應於schema的表的類別,也一併產生 標準的存取器(→get() and →set()方法)你可以在askeet/lib/model/om/目錄下看產生出來的類別。

如果你發現為何每一個表有兩個類別,請去看symfony book.的 model 章節。你每次一重建模型,這些類別就會覆寫。在這個專案中發生的機會滿大的。假如你需要對一個物件模型加方法,你必 須要要進askeet/lib/model/目錄修改,這些類別繼承自/om。

数据库

 

連接

現在 symfony 有一個資料庫的物件模型。該是你的項目連上MySQL的時候了, 首先,你必須要建一個資料庫。

$ mysqladmin -u youruser -p create askeet

現在打開askeet/config/databases.yml設定檔,假如這是你第一次用symfony,你將發現 symfony 設定檔是用 YAML 文法簡單,但有一個主要的約束,就是永遠不要用Tab鍵,永遠用空白鍵。一旦你了解,你可以開始把實際的連接設定寫入這個檔裏。

all: category:
all:
   propel:
     class:          sfPropelDatabase
      param:
         phptype:     mysql
         host:        localhost
         database:    askeet
         username:    youruser
         password:    yourpasswd

如果要知道更多。請讀 symfony book.的practice chapter

建構

假如你不想手寫設定檔。你可能也有相對應的表在資料庫,你可以省略這一步。如果你是打字迷,這裏有個驚奇,你不需要建表和欄位,在 schema.xml 裏做这个,然後 symfony 會產生建表及欄位的指令。

$ symfony propel-build-sql

上面指令會產生一個 schema.sql (在askeet/data/sql/),將SQL執行

$ mysql -u youruser -p askeet < data/sql/schema.sql

用CRUD測試資料的存取

symfony 知道之前做過的工作是有用的永遠是好的,到現在,你的瀏覽器無用武之地,我們馬上將建一個網頁程式,就讓我們建一組基本的symfony 的動作和樣板,來維護資料表。這將允許你提一些問題,並展示它們。

在這個目錄下,鍵入:

$ symfony propel-generate-crud frontend question Question

這指令產生了問題模組的scaffolding 在前端程式,根據Question Propel的物件模型,產生了基本的新增,查詢,修改,刪除的動作()。不用困惑: scaffolding 還不是一個完成的程式,是個基礎的結構,在這結構之上你可開發新特性,加上一些商業規則,修改它的外觀和感覺。

這是 用CRUD 生成子的產生的動作的列表:

动作 说明
列表 將表裏的所有記錄秀出來
索引 可去找列表
對一個指定的目錄秀出所有欄位
編輯 秀一個表單來新增一筆記錄或編輯一筆已存在的
修改 根據需求的參數來修改一筆記錄,從後導向到秀
刪除 從表中刪除一筆指定的記錄

你可在 scaffolding 這章,發現更多關於生成的動作。

在這個目錄下,注意這個新問題的模型和瀏覽它的源碼。

不論何時你加入了一個 新類別,都需要被自動載入,不要忘記清掉設定的快取殘留(再重載入自動載入的快取)

$ symfony cc frontend config

你現在可以線上測試它了,

繼續往前,測試它,在一些新的問題,編輯它,列出它,刪出它,如果可運作,表示這個物件模型是正確的,連接資料庫也無誤,而關連的模型和資料庫也是正確的,這是一個良好的功能測試。

http://askeet/question

你不用寫一行PHP代碼,一下子,你有一個基礎的程式可以用了。就第二天來說,這樣還不壞,明天,我們將為了寫一歡迎網頁和列出這些問題而寫一些代碼,我們也將用批次指令加一些測試的資料到資料庫裏,並學習擴展這個模型。

測試用CRUD存取資料 現在你知道這程式將要做什麼,你也可以想像加上一些新功能。請使用 askeet mailing-list 不吝賜教,最棒的建議將變成第21天的內容。

請自由取用今天教程的源碼(標籤為) release_day_2

http://svn.askeet.com/tags/release_day_2

相关热词搜索:

上一篇:Practical symfony 开始这个项目
下一篇:Symfony Project 深入MVC架構

分享到: 收藏
频道总排行
频道本月排行