06第五章迭代2项目project的CRUD.docx
- 文档编号:23361249
- 上传时间:2023-05-16
- 格式:DOCX
- 页数:35
- 大小:366.51KB
06第五章迭代2项目project的CRUD.docx
《06第五章迭代2项目project的CRUD.docx》由会员分享,可在线阅读,更多相关《06第五章迭代2项目project的CRUD.docx(35页珍藏版)》请在冰豆网上搜索。
06第五章迭代2项目project的CRUD
第五章:
迭代2:
项目(project)的CRUD
现在,我们已经制定了一个基本的应用程序并配置连接了数据库,现在我们的工作是开发一些实用的功能。
我们知道项目(project)是这个应用程序最根本的组成部份之一。
用户首先会在TrackStar应用程序创建或选择一个已经存在的项目(project)并在其中添加任务和问题。
出于这个原因,我们想在第二个迭代中集中精力在项目(project)这个模块上。
迭代计划
这个迭代相当明了,在这个迭代结束时,我们的应用程序将允许用户创建新的项目(project),在项目(project)列表中选择现有的项目(project),更新/编辑现有项目,并删除现有的项目。
为了实现这个目标,我们需要确定具体更细小的任务,下面列出了这次迭代需要完成的所有任务:
▪设计数据库结构
▪建立必要的表和所有其他的数据库对象
▪创建Yii的AR模型类,允许应用程序能够轻松地与数据库表交互。
▪创建Yii的控制器类,其实中包括的功能:
o创建项目(project)
o取得现有项目(project)列表并可以显示
o更新现有项目(project)的相关数据
o删除现有项目(project)
▪创建Yii的视图文件,显示的方式和逻辑是:
o显示创建新项目(project)的表单,并允许创建
o显示所有现在项目(project)的列表
o显示编辑现有项目(project)的表单,并允许编辑
o在项目列表中添加一个删除按钮,并允许删除项目(project)
这些已经足够了,让我们开始吧。
我们将很快就把这些任务放到TrackStar中并管理。
现在,我想我们只能先将它们记在记事本上
运行我们的测试套件
在我们进入正式开发之前,我们应该选执行现有的测试套件并确保所有测试全部通过。
现在我们只有一个测试,这个测试是在第4章中添加的用来验证数据库连接是否有效。
所以,不会花太多的时间运行我们的测试套件。
打开你的命令提示符,进入/protected/tests目录,并运行以下单元测试:
SHELL代码或屏幕回显:
%phpunitunit/
PHPUnit3.3.17bySebastianBergmann.
Time:
:
:
0seconds
OK(1test,1assertion)
随着所有的测试都通过,我们更有信心了。
现在我们可以开始进行修改。
创建项目(project)表
早在第3章,我们谈论关于一个项目(project)的基本数据,并在第4章,我们决定使用MySQL关系数据库构建这个应用程序的持久层。
现在我们将这个项目(project)的内容变成一个真正的数据库表。
我们知道,项目(project)需要有一个名字和描述。
我们也将继续保持一些基本信息,跟踪每个记录的创建时间,更新时间以及谁创建的,谁更新的。
这些已经足够了,让我们开始达到这个目标。
基于这些所需的属性,如何创建项目(project)表,如下所示:
SQL代码:
CREATETABLEtbl_project
(
idINTEGERNOTNULLPRIMARYKEYAUTO_INCREMENT,
nameVARCHAR(128),
descriptionTEXT,
create_timeDATETIME,
create_user_idINTEGER,
update_timeDATETIME,
update_user_idINTEGER
);
如何使用第三方数据库管理工具,已经超出了本书范围。
我们也希望让你跟着使用其他可能使用到的一些其他软件。
基于这些原因,我们将简单地提供低级别的数据定义语言(DLL)。
创建数据库结构。
所以,启动Yii支持的数据库服务器,并在trackstar_dev数据库中,打开你的数据库编辑器,执行上面的DLL语句创建表。
根据你选择使用的数据库,有许有可用的工具帮助你管理和维护数据库结构,我们建议你使用这些工具,这将使事情变的更加容易。
我们实际上是使用MySQLWorkbench(进行设计,文档和管理我们的数据库结构。
我们也使用phpMyAdmin(帮助管理。
还有许多类似的工具。
花较少时间来熟悉使用这些工具将为你节省很多的时间。
命名规则
你可能已经注意到,我们定义的数据库表名,以及所有的列名都是小写。
在我们的开发中,我们将所有表名和列名都使用小写字母。
这主要是因为不同的DBMS是区分大小写的。
举个例子,PostgreSQL的列名在默认情况下是区分大小写的,但我们在一个查询条件中必须引用一列,如果该列包含大小写字母。
使用小写字母将有助于消除这个问题。
你可能还注意到,我们为项目(project)表名使用了一个tbl_前缀。
从1.1.0版本起,Yii提供了使用表前缀的支持。
表前缀是一个字符串,它是预先决定表的名称。
它通常用在共享主机的环境下,多个应用程序共享同一个数据库的情况,使用不同的表前缀加以区分。
例如,一个应用程序使用前缀tbl_而另一个可以使用yii_。
另外,一些数据库管理员把它当成一个命令规则,用来前缀标识数据库对象是什么类型,或使用前缀来进行分组。
在Yii中为了采用表前缀支持,必须设置CDbConnection:
:
tablePrefix属性为期望的表前缀。
然后在整个应用程序的SQL语句中,可以使用{{TableName}}做为参考表名,其中TableName就是表的名称,但不用前缀。
例如,如果我们需要修改这个配置,我们仍然可以使用如下代码查询所有项目(project):
PHP代码:
$sql='SELECT*FROM{{project}}';
$projects=Yii:
:
app()->db->createCommand($sql)->queryAll();
但这个问题有点超前了。
现在让我们离开我们的配置。
重新回到正题。
稍后再进入数据库查询。
创建AR模型类
现在,我们已经创建了tbl_project,我们需要创建Yii模型类来管理该表中的数据。
早在第1章,我们介绍了Yii的对象关系映射(ORM)层和ActiveRecord(AR)。
现在我们根据应用程序的上下文来看一个具体的例子。
以前,我们使用yiicshell命令来帮助我们自动生成一些代码。
如在第2章,我们正是使用shell命令来创建我们的第一个控制器,还有许多其他的shell命令可以执行,以帮助自动创建应用程序代码。
然而,从1.1.2版本起,Yii有一个新的和更复杂的界面工具Gii。
Gii是一个高度可定制和可扩展的基础于Web的代码生成平台,把yiicshell命令提升到了新的高度。
我们将使用这个新平台,创建我们的新模型类。
配置Gii
在我们开始使用Gii之前,我们必须在应用程序中配置。
此时,你可能猜到我们将要编辑我们的主应用程序配置文件protected/config/main.php。
是的,要配置Gii,打开这个文件,并添加如下的高亮代码:
PHP代码:
returnarray(
'basePath'=>dirname(__FILE__).DIRECTORY_SEPARATOR.'..',
'name'=>'MyWebApplication',
//preloading'log'component
'preload'=>array('log'),
//autoloadingmodelandcomponentclasses
'import'=>array(
'application.models.*',
'ponents.*',
),
'modules'=>array(
'gii'=>array(
'class'=>'system.gii.GiiModule',
'password'=>'[add_your_password_here]',
),
),
这为应用程序配置了Gii模块。
我们本书后面章节详细讲解Yii模块。
这里的重点是要确保这些代码添加到了配置文件,并提供你的密码。
现在,访问此工具地址:
http:
//localhost/trackstar/index.php?
r=gii。
下面的屏幕快照显示了验证表单:
使用Gii创建项目(project)AR类
首先输入您在配置文件中提供的密码,成功后将带你进入Gii的主菜单页面:
你可能还记得,这些菜单的选项都类似于第2章使用yiicshell命令行工具的帮助信息。
因为我们想要创建tbl_project表的模型,这个模型生成器选项似乎是一个正确的选择。
点击链接将带我们进入以下页面:
在创建过程中,表前缀字段域主要用于帮助Gii确定如何命名AR类。
如果您使用一个前缀,你可以在此添加。
这样,不会使用该前缀来命名新的类。
就我们而言,我们使用的是tbl_前缀,这也恰好是表单的默认值。
因此,指定此值将意味着我们新生成的AR类将被命名为Project,而不是tbl_project。
接下来的两个字段域是要求输入表名和我们希望生成的类名。
我们表的名称是tbl_project,查看模型类的名称会自动填空。
它使用表名,但没有前缀,并以大写字母开头来覆盖模型类的名称。
因此,Project为我们模型类的名称,但你也可以自己定义此名称。
接下来的几个字段域是用来进一步进行定制的。
BaseClass字段用来指定继承哪个模型类。
这个类是CActiveRecord或它的子类。
ModelPath字段类允许你指定这个模型类文件在应用程序中的位置。
默认值是protected/models/(即application.models)。
最后一个字段指定使用的生成器的模板。
我们可以自定义默认模板以应对其它可能出现的情况,比如所有的模型需要有共同的需求。
现在,这些字段的默认值已经可以满足我们的需求了。
点击Preview(预览)按钮继续,将在页面底部显示如下表格:
当你点击models/Project.php这个链接,可以预览将要生成的代码。
下面的截图显示这个预览的样子:
它提供了一个可以滚动的弹出窗口,使我们可以预览到整个文件的代码。
好了,关闭这个弹出窗口,点击生成按钮。
如果一切顺利,你应该在屏幕底部看到如下画面:
确保/protected/models(或你在ModelPath字段域填写的路径)是有Web方式写入的权限。
否则,你将收到一个权限错误信息。
Gii已经为我们创建了一个新的AR模型类。
它的名字是Project.php,默认情况下,放在protected/models/目录。
这个类封装了是我们的tbl_project表。
表中的所有字段访问是通过ProjectAR类的属性。
让我们熟悉的方式为新创建的AR类写一些测试。
测试新生成的代码
一个好的方式是为新代码或功能编写测试。
用单元测试的方式来了解AR类是如何在Yii中工作的。
由于本次迭代的重点是项目(projects)的创建,读取,更新和删除(CRUD)。
我们将针对ProjectAR类来编写有关这些操作的测试。
在我们新建的Project.php这个AR类中,已经包含了这个CRUD功能的公共方法。
所以我们不需要编写这些代码。
我们可以只专心来写测试。
创建单元测试文件
首先,需要创建一个新的单元测试文件,让我们创建这个文件在:
protected/tests/unit/ProjectTest.php,并输入如下代码:
PHP代码:
php
classProjectTestextendsCDbTestCase
{
publicfunctiontestCRUD()
{
}
}
这个类继承自CDbTestCase,这是Yii框架中单测元类的基类,最门用来测试与数据库相关的功能。
这个特定的基类提供了一些管理操作。
下面我们将介绍更多的细节。
我们将使用testCRUD()方法对ProjectAR类进行所有的CRUD操作测试。
我们将开始测试创建一个新项目(project)。
我们并没有真正从事TDD,其原因是我们进行测试的并不是我们所写的代码。
我们正在使用Yii中的AR类,帮助你熟悉这种测试方法和编写基本的测试。
由于不是真正的TDD,我们将不会完全遵循在第3章所说的TDD的步骤。
例如,由于我们测试的是Yii的核心代码,所以我们没有做到先写一个失败的测试。
测试创建(Create)
为testCRUD()方法添加代码,创建一个ProjectAR类,设置它的属性,然后保存它:
PHP代码:
publicfunctiontestCRUD()
{
//Createanewproject
$newProject=newProject;
$newProjectName='TestProject1';
$newProject->setAttributes(
array(
'name'=>$newProjectName,
'description'=>'Testprojectnumberone',
'create_time'=>'2010-01-0100:
00:
00',
'create_user_id'=>1,
'update_time'=>'2010-01-0100:
00:
00',
'update_user_id'=>1,
)
);
$this->assertTrue($newProject->save(false));
}
此代码首先创建了一个ProjectAR类实例,然后,我们使用AR类的setAttributes()方法以批量的方式传入数组来设置AR类的属性。
我们看到,类的属性是这个数组的键,具体的数据是这个数组对应键的值。
设置好属性后,我们调用Project类的save()方法保存。
我们传递给save()方法一个参数false,用来告诉它绕过属性的数据验证(我们将在数据模型验证部份介绍它,添加自己的验证字段)。
然后我们测试返回值,保存成功将返回true。
现在我们切换到命令行下执行这个新的测试,以确保成功;
SHELL代码或屏幕回显:
%cdWebroot/protected/tests
%phpunitunit/ProjectTest.php
PHPUnit3.3.17bySebastianBergmann.
.
Time:
:
:
0seconds
OK(1test,1assertion)
不错,它通过了。
因此,我们已经成功的添加了一个新的项目(project)。
你可以直接查询数据库来验证。
使用你的数据库维护工具,查询项目(project)表返回的内容,你会看到一条新记录的详细属性与ProjectAR类的属性匹配。
在下面的例子中,我们使用MySQL命令行查看:
SQL代码:
mysql>select*fromtbl_project\G
***************************1.row***************************
id:
1
name:
TestProject1
description:
Testprojectnumberone
create_time:
2010-01-0100:
00:
00
create_user_id:
1
update_time:
2010-01-0100:
00:
00
update_user_id:
1
1rowinset(0.00sec)
你可能已经注意到,当设置ProjectAR类属性时,我们没有指定id字段。
这是因为该列被定义为一个自增长主键。
当插入新行时数据库会自动分配个值。
一旦插入成功,AR类会自已设置此属性。
你可以很容易地获得id属性,方法如下:
PHP代码:
$newProject->id
我们将继续下个测试。
测试读取(Read)
现在,我们已经验证创建测试ProjectAR类的save()方法,让我们继续,添加下面高亮部份的代码,保存在testCRUD()方法中现有代码的最后。
PHP代码:
publicfunctiontestCRUD()
{
//Createanewproject
//READbackthenewlycreatedproject
$retrievedProject=Project:
:
model()->findByPk($newProject->id);
$this->assertTrue($retrievedProjectinstanceofProject);
$this->assertEquals($newProjectName,$retrievedProject->name);
}
在这里,我们使用静态方法model(),它已经定义在了每一个AR类中。
这个方法返回了ProjectAR类的实例,从而进行部访问该类的方法。
我们调用findByPk()方法来查询Project特定实例。
这种方法(正如你期望的)通过传递主键的值,返回一个相匹配的行。
我们传递的是之前新创建的Project类的实例的自增长属性id。
通过这种方式,我们试图当我们保存$newProject后,读取插入的这行。
我们有两个断言,我们首先确认返回的是否为ProjectAR类的实例。
然后我们确认项目(project)的名称是否与读取的项目(project)名称一致。
让我们再次在命令行下运行如下测试:
SHELL代码或屏幕回显:
%phpunitunit/ProjectTest.php
...
OK(1test,3assertions))))
非常好!
我们已经验证了CURD中的"R"是按着我们预期的完成了工作。
接下来让我们快速完成Update(更新)和Delete(删除)的测试。
测试更新(Update)和删除(Delete)
现在,同样在testCRUD()方法的底部,添加如下代码:
PHP代码:
//Createanewproject
...
//READbackthenewlycreatedproject
...
//UPDATEthenewlycreatedproject
$updatedProjectName='UpdatedTestProject1';
$newProject->name=$updatedProjectName;
$this->assertTrue($newProject->save(false));
//readbacktherecordagaintoensuretheupdateworked
$updatedProject=Project:
:
model()->findByPk($newProject->id);
$this->assertTrue($updatedProjectinstanceofProject);
$this->assertEquals($updatedProjectName,$updatedProject->name);
//DELETEtheproject
$newProjectId=$newProject->id;
$this->assertTrue($newProject->delete());
$deletedProject=Project:
:
model()->findByPk($newProjectId);
$this->assertEquals(NULL,$deletedProject);
在这里,我们增加了用来测试项目(project)的更新和删除的代码。
首先,我们给$newProject实例更新name属性,然后保存这个项目(project)。
由于这里的AR实例已经存在,我们知道这个AR类是更新,而不是插入新记录,当我们调用->save()后,我们再读回这行,来确定是否更新了name。
为了测试删除,我们保存$newProject实例的id属性值到一个局部变量$newProjectId。
然后,我们调用$newProject实例的->delete()方法,你可能猜到了从数据库中删除记录,将销毁AR实例。
然后我们尝试通过这个局部变量作为主键,查询Project返回这行。
由于这条记录已经被删除,我们将得到的结果为NULL。
测试断言将使用NULL比较。
让我们再测运行测试,以确保成功:
SHELL代码或屏幕回显:
%phpunitunit/ProjectTest.php
...
OK(1test,8assertions)
因此,我们已经证实了,我们的ProjectAR类的CRUD操作是可以达到预期的工作。
所有测试是真的有必要吗?
当谈到TDD的软件开发方法时,人们不停地面对测试和时间哪个更重新来作出决定,哪些部份不需要测试。
这些问题必须由你自己来回答。
提供足够的测试可使代码质量提高,但很显然测试应用程序中的每一行代码可能有些夸张。
一般的经验规则是,不要为外部库编写测试代码(除非你有特别的理由不信任它)。
我们已经对ProjectAR类编写了CRUD操作的测试,它们背后的是Yii框架的代码,而不是我们写的代码。
我们没有写这些测试,因为我们信任框架的代码,只是想让你了解怎么使用一个ActiveRecord。
这项工作只是我们产品中测试套件的一部份,然则,没有必要再去测试我们创建的每一个AR类,因为,我们不会再对创建的AR类做这件事情了。
用户允许CRUD操作
前面提到的测试向我们介绍了如何使用AR类。
它展示了如何创建新记录,查询现有的记录,更新现有的记录,并删除现有记录。
我们花了很多时间测试Project表的AR类的一些低级别的操作。
但我们的TrackStar应用还没有公开这些功能给用户(user)。
我们真正是需要让用户(user)来创建,读取,更新和删除项目(project)。
现在,我们知道了一些围绕AR操作的方法,我们可以在控制器中开始编写一些功能代码。
幸运的是,我们不用做。
通过脚手架为项目创建CRUD
让我们再次进入Gii代码生成工具帮我们我生成一个繁琐,耗时又很常见的代码。
Yii为我们提供这个明确的方式,在应用程序中开发者使用共同的CRUD进行数据库操作。
如果你已经熟悉了其他框架,你可能知道脚手架这个词。
让我们来看看在Yii中利用它的优势。
访问http:
//localhost/trackstar/index.php?
r=gii,并选择CrudGenerator链接。
你将看到如下画面:
在这里,我们看到两个表单字段域。
第一个是要求我们指定模型类,我们希望生成所有的CRUD操作。
在我们的例子中,使用Project.php这个AR类。
所以在这个字段域中填写Project。
当我们输入后,我们注意到,ControllerID字段域自动填充成了project,这是基于Yii的约定。
我们现在保持默认即可。
这两个字段域填写后,点击预览按钮,将会在页面底部看到如下表格:
我们可以看到将要生
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 06 第五 章迭代 项目 project CRUD
![提示](https://static.bdocx.com/images/bang_tan.gif)