【翻译】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了,描述咱们功能需求的最佳方法,就是写一个完整的端到端测试。

下一节        上一节

相关文章
相关标签/搜索