【翻譯】Yii2 第2章 用Yii2建立自定義應用(第1部分)

在這一章裏,咱們將看到Yii2怎樣幫助咱們建立web應用。示例雖然很簡單,但整個過程都符合軟件工程思想。咱們將完成應用開發的每個步驟,而且每一步都會根據權威書籍中的最佳實踐來進行:
php

  • 建立領域模型:這本書解釋了領域驅動,Tackling Complexity in the Heart of Software, Eric Evans, Addison-Wesley Professionalhtml

  • 設置測試裝置:咱們遵守驗收測試驅動實踐,Growing Object-oriented Software, Guided by Tests, Steve Freeman and Nat Pryce, Addison-Wesley Professionalgit

  • 設置開發流水線github

    • 持續交付:Reliable Software Releases through Build, Test, and Deployment Automation, Jez Humble and David Farley, Addison-Wesley Professionalweb

    • 持續集成:Improving Software Quality and Reducing Risk, Paul M. Duvall, Steve Matyas, and Andrew Glover, Addison-Wesley Professionalshell

  • 紅-綠-重構 開發循環:深度解釋,請參考下列圖書:數據庫

    • Clean Code:A Handbook of Agile Software Craftsmanship, Robert Martin, Prentice Hallapache

    • Test-Driven Development by Example, Kent Beck, Addison-Wesley Professionaljson

  • 部署和手工測試:這符合持續交付,而且這些步驟也是必不可少的bootstrap

保持專一。

設計階段

貫穿整本書,在使用示例應用的時候,咱們須要注意實際需求。在這個小節,咱們將定義整個示例的場景。

任務

假設咱們有一個小的商業應用,要對外提供一些服務。咱們有一些客戶,他們有一些數目巨大的帳目記錄在紙面上,用商業卡片管理很是不方便。所以,咱們須要用自動化的方式把這些檔案管理起來。

首先,咱們須要一些增刪查改(CRUD)界面進行記錄管理,爲客戶展現最核心的屬性。

很明顯,咱們的業務和客戶可能會隨着時間的推移而增加、變化,所以咱們的應用也應該隨之變化。在一開始,咱們應該爲可能的變化作好準備。

本着吃本身狗食的原則(譯註:微軟在1998年提出),既然本身開發的系統本身要使用,那這個系統最好保證是高質量的。

領域模型設計

很明顯,咱們將在應用中處理客戶模型。在「customer」和「client」兩個詞中,咱們以爲「customer」更爲貼切。

一個客戶(customer)是一我的,他至少具備姓名、地址、電子郵件,以及電話號碼等屬性。咱們爲客戶提供一個服務,按小時統計,並根據合約支付這段時間產生的費用。這就是咱們在第一次迭代設計中打算解決的問題。

咱們假設每位客戶都是單個的人,所以咱們不用處理公司,有多個聯繫人的狀況。姓名是一個複雜的結構,若是咱們深刻細節,有敬語、職務、暱稱、中間名、姓等屬性須要考慮。但在這個應用中,咱們真正感興趣的並非客戶的姓名,咱們只是須要用姓名來識別一個客戶。所以,咱們將簡單的使用一個文本行來表示,容許咱們按任何格式來寫入姓名。地址一樣能夠是一個複雜的結構,此次咱們打算用一個結構來描述,而再也不是一個簡單的文本行。這是由於咱們須要經過地址來實現如下兩件事情。

  • 進行一些統計,例如在一個特定的城市,有多少個客戶

  • 遵守不一樣的文化背景,正確地生成郵寄地址

所以,咱們決定採用下面的結構:

  • 用途(例如:帳單地址、購物地址、家庭地址、工做地址)

  • 國家

  • 州,國家下級的區域,好比美國

  • 城市

  • 街道

  • 建築物

  • 部門/辦公室

  • 收件人姓名

  • 郵政編碼

咱們應該注意到,一個地址能表明一個部門、郵箱、辦公室、組織中的僱員,甚至是整個建築。一樣,一個客戶也能夠多個地址。

電話這個實體具備如下屬性:

  • 用途(我的或工做)

  • 號碼

一個客戶可能有幾個電話號碼,經過用途字段區分。

除了姓名、地址、電話這個實體以外,咱們的職員須要經過一種途徑對客戶進行自由的描述。這裏咱們簡化了姓名屬性。而後,咱們加入生日、電子郵件屬性,固然,一個客戶能夠有多個電子郵件。

咱們先停一下。

咱們如今能畫出客戶模型的完整聚合圖了,以下圖所示:

根據Eric Evans的《領域驅動設計》,客戶是一個實體(Entity),也就是說,是一個狀態能夠改變的對象,所以咱們要關心它在整個系統中的一致性。而其它部分是值對象(Value Object),意味着初始建立後,狀態不會改變的對象,所以他們是能夠徹底互換的。

爲了簡化處理,咱們再也不詳細描述商業上是如何處理客戶的,咱們不打算在這本書中涵蓋它。不管如何,讓咱們把注意力回到咱們爲客戶提供的一系列服務中來,維護這些記錄將會頗有用。咱們將在後面的章節用到這個模型

目標特性

讓咱們來執行一個特定的任務。考慮到有的人給咱們打電話(假如咱們已經識別出號碼),咱們想獲取呼入者的全部詳細信息。在應用中,若是這個號碼沒有找到關聯的人,那咱們就知道他並非咱們的客戶。若是找到關聯人,咱們至少能夠直接用他的姓名跟他打招呼,這是很好的客戶服務。

咱們應該理解數據庫查詢,咱們須要一個途徑能夠插入數據,有可能還須要編輯和刪除它。所以,咱們第一次開發迭代的特性包含如下內容:

  • 將客戶信息插入數據庫

  • 在數據庫中編輯客戶信息

  • 從數據庫中刪除客戶信息

  • 根據電話號碼從數據庫中查詢客戶信息

構造通用的數據庫查詢並非咱們的目標,咱們僅僅須要根據一個電話號碼進行查詢。

讓咱們開始吧。

初始準備

一直到本書結束,咱們將在接下來的章節中討論同一個應用,所以準備工做只須要作這一次。

下載示例代碼:Packt的網站上能夠下載你購買過圖書的示例代碼,地址是http://www.packtpub.com,若是你已經購買了這本書,請訪問http://www.packtpub.com/support,註冊後會直接將文件經過電子郵件發送給你。

配置項目管理

咱們要開發的應用,從本質上說,是一個客戶關係管理系統(CRM)。所以,咱們首先建立一個名爲 crmapp 的目錄。

請注意,正本書中,經過命令行調用的示例,都假定你當前目錄爲crmapp目錄。

Yii2推薦使用包管理器Composer進行安裝,所以咱們就來使用這個工具。你能夠去閱讀Composer的完整文檔瞭解詳細的細節,咱們這裏準備了一個簡短的說明:

  • 全部經過Composer安裝的包,都會存放在項目路徑下,一個名爲vendor的子目錄中。

  • 與Composer相關的數據,全部依賴和其它信息,都保存在名爲composer.json的清單文件中,位於項目根目錄下。只要你在這個文件中申明瞭依賴,你就能在任什麼時候候安全的刪除vendor目錄,並在調用php composer.phar install 或 php composer.phar update時徹底重建。

Composer的文檔描述了一個獲取composer.phar的方法:

curl -sS https://getcomposer.org/installer | php

固然,若是你的PATH路徑中若是沒有CURL,你也能夠直接去Composer的官方網站 https://getcomposer.org/  直接下載PHAR文件。(譯註:若是是windows環境,推薦直接下載一個Composer的安裝包,安裝完成後,添加到PATH目錄,之後就能夠直接使用composer <command>進行調用,而不使用php composer.phar <command>,更爲方便)。

咱們準備好後,就能夠按下面的格式執行命令了:

php composer.phar <command>

假定你會使用版本控制系統來管理代碼,本書的代碼使用Git(http://git-scm.com/)進行管理。

準備階段快速指引:

mkdir crmapp
cd crmapp
curl -sS  | php
git init
配置測試工具

正如咱們在本章的開始部分所說,咱們將聽從測試優先的開發實踐來進行驗收測試。這樣作的緣由以下:

  • 咱們想檢查應用是否能正常工做,又不想使用乏味的人工測試

  • 咱們尚未深度的單元測試需求,由於咱們目前主要的工做只是把已經存在的組件裝配在一塊兒,所以,經過對UI進行端對端的驗收測試最爲簡單可行

若是咱們關心用戶特性請求的實現狀況,咱們須要一些形式的驗收測試。

Yii2內置支持Codeception測試框架,官方站點是 http://codeception.com/。咱們不會在自己中直接使用它,可是 yii2-codeception(https://github.com/yiisoft/yii2-codeception)提供了一些輔助類,來集成到Yii框架中。

讓咱們來申明,咱們須要在項目中使用 Codeception,執行下面的命令:

php composer.phar require "codeception/codeception:*"

稍等片刻,直到Composer執行完成。

目前,composer.json文件的內容是:

{
    "require": {
        "codeception/codeception": "*",
    }
}

命令 php composer.phar require <包名:版本> 只是一個輔助方法,將require塊插入到清單文件中,並調用update命令。

固然,我也須要將Yii2一樣做爲依賴加入,但在這以前,讓咱們先幹一件事情。

正如咱們看到的,Codeception已經存在於 ./vendor/bin/codecept 目錄中了。這個路徑敲起來比較長,在POSIX兼容的shell中,好比bash,容許咱們使用下面的方式來進行簡化:

alias cept="./vender/bin/codecept"

這樣作更好。在本章餘下的部分,咱們都假定你已經執行了上面這條命令。

Codeception是一個複雜的系統,因此咱們須要依賴它本身內建的命令。不必深刻Codeception的內部細節,咱們只是簡單實用就能夠了。執行下面的命令:

cept bootstrap

這將爲Codeception生成一個tests目錄,並進行配置。

如今,讓咱們建立一個傻瓜型的驗收測試,用以檢查咱們的測試工具。

cept generate:cept acceptance SmokeTest

這個命令將生成 SmokeTestCept.php,位於 tests/acceptance 目錄下。當咱們打開這個文件,咱們將看到以下代碼(根據Codeception版本,代碼可能略有不一樣):

$I = new AcceptanceTester($scenario);
$I->wantTo('perform actions and see result');

AcceptanceTester是一個能夠模仿瀏覽器後的真實用戶,對應用進行測試的類。Codeception同時也提供 CodeGuy 用以進行單元測試,提供 TestGuy 進行功能測試,在後面咱們纔會用到。

當咱們調用 AcceptanceTester.wantTo("do something")時,咱們只是爲下面的測試行爲建立了一個標題(用雙引號括起來的)。

讓咱們修改一下代碼,加入冒煙測試的功能,對咱們的首頁進行測試:

$I = new AcceptanceTester($scenario);
$I->wantTo('See that landing page is up');
$I->amOnPage('/');
$I->see('Our CRM');

當咱們訪問應用首頁的時候,咱們但願看到有 Our CRM 這一行。假設咱們應用中已經有那麼一個標題存在了。

如今運行測試:

cept run

咱們會看到失敗的信息,由於咱們尚未設置web服務器,處理 / 請求。這樣,到了該咱們寫一些生產代碼來經過這個測試的時候了。然而,到目前而言,咱們須要的還不是生產代碼,咱們的基礎服務都尚未創建起來。咱們須要先創建發佈機制。

配置發佈流水線

咱們已經說過,編寫的web驗收測試會模擬真實用戶,在瀏覽器中打開應用,經過可視的UI進行交互。所以,咱們如今須要作的是將應用整個部署到咱們能運行驗收測試的機器。

提示:最多見的狀況是,你決定開發和測試使用同一臺機器,這是錯誤的!別這麼幹。

極可能你的工做平臺和應用最終要運行的機器不是同樣的。參照已有數十年曆史的工業生產,這已是一個持續不斷的問題了。當應用的生命週期預計是數年時,在不一樣環境的生產服務器上測試你的應用,你會面臨類似的集成問題。固然,這不是將打包好的軟件賣給用戶,這仍是要簡便一些。在咱們的案例中,咱們假定一個單一的發佈點只有一個固定web應用,所以,簡便性不是問題,可重複性測試纔是問題。

最終,你的驗收測試將會包含如下幾個步驟:

  • 將應用發佈到測試服務器

  • 在你的機器上運行驗收測試

固然,你能夠在測試服務器上運行驗收測試。要這樣作,你只須要用localhost這個本地迴路網絡接口來配置測試就能夠了。然而,仍是須要你安裝一些與測試服務器不相干的軟件。例如,若是你想全棧運行,使用Selenium進行瀏覽器內測試,你可能須要安裝一個web瀏覽器,Java運行時,虛擬幀緩衝軟件,而且這又須要安裝它們各自相關的軟件,這樣作很是費勁。最有效的作法是使用你本身的桌面環境,來運行web驗收測試。

提示:這固然不是在談論單元測試和功能測試。單元測試因爲只與自己有關,應在有原始代碼的地方執行,徹底不須要部署。功能測試,應在部署後的應用上測試,由於須要測試通過配置後的最終應用以及交互的正確性。

在任何案例中,理想化的方案是,你只需一個就像deploy這樣的簡單命令,就能完成如下功能:

  1. 訪問並啓動目標機器(特別是,當它是一個虛擬機實例的時候)

  2. 確保除應用外,環境是有效的

  3. 將當前代碼拷貝到目標機器

  4. 在目標機器上,配置剛拷貝過去的代碼的環境

  5. 啓動應用

你應該能在命令行中輸入deploy,並敲擊Enter鍵,完成上述的全部步驟。正如Martin Fowler在他的《持續集成》(http://martinfowler.com/articles/continuousIntegration.html)中所說,這對你來講小菜一碟。理想狀況下,部署行爲應該在你啓動驗收測試工具時自動完成。

在本書中,咱們只關心最後兩步。由於咱們開發的是PHP應用,只要目標機器上的web服務器在運行,」啓動應用「這一步就算已經完成了。

本書僅關注web應用開發,並不涉及系統管理,那是系統管理員的事。然而,在附錄A,」使用Vagrant進行部署設置「,咱們準備介紹一個基於虛擬機的部署,一樣也很容易在任何桌面工做站上實現。你能夠沒必要須要另一臺物理機,就仍然能模擬現實世界的部署過程。若是你別無選擇,強烈推薦你讀讀。實際上,採用那裏的描述,自己全部的代碼都準備好了。讓咱們假設你有一個準備好的環境和deploy命令,爲了簡化,咱們同時假定每次運行驗收測試前,部署都會自動運行。部署的結果能夠從你的機器經過一個簡單的URL進行訪問,驗收測試工具會將它做爲應用的入口點。

如今,讓咱們到Codeception的跟驗收測試相關的配置部分,打開文件 tests/acceptance.suite.yml,把入口URL加入到 modules.config.PhpBrowser.url 詞條中。假定你沒修改過這個文件,文件內容看起來應該像這樣:

class_name: AcceptanceTester
modules:
    enabled:
        - PhpBrowser
        - WebHelper
    config:
        PhpBrowser:
            url: 'http://YOUR.APPLICATION.URL'

(譯註:本機acceptance.suite.yml文件格式跟上面不一樣,不存在config項,url直接放在enabled的PhpBrowser下)

舉例來講,若是你用Apache的基於IP的虛擬主機技術來配置目標機器(https://httpd.apache.org/docs/2.2/vhosts/ip-based.html),modules.config.PhpBrowser.url 的值就應該像這樣:http://127.0.0.01:8000。

當咱們改變配置,咱們須要重建Codeception,執行下面的命令:

cept build

不要忘記 cept 這個別名是咱們本身建立的。實際運行的是 ./vendor/bin/codecept 文件。

若是你如今運行測試:

cept run

你應該能夠看到以下輸出:

你會看到Codeception在 / 路由上顯示了一些東西,但還不是咱們指望的。根據使用的Apache版本不一樣,能夠是404錯誤或者403錯誤。若是你使用的其它Web服務器,可能顯示的另外的錯誤信息。不管如何,問題的根源很簡單,這就是咱們須要在外界可訪問的web目錄中,加入index.php文件。

建立一個可見的web應用入口

咱們先作一個約定,能夠被外部訪問到的目錄只有一個,命名爲web,放在項目的根目錄下。例如,若是你的web服務器是Apache,應該把DocumentRoot指向web目錄。

所以,將下面的內容放在web目錄的index.php文件中:

Our CRM

是的,就是7個字符的文本文件。畢竟,這就是咱們的驗收測試指望的全部內容了,正確嗎?

讓咱們來運行測試:

cept run

咱們獲得了以下輸出:

如今,咱們須要在項目中使用Yii2了,描述咱們功能需求的最佳方法,就是寫一個完整的端到端測試。

下一節        上一節

相關文章
相關標籤/搜索