4.1 准备好数据库

每当一件事情开始时,我总会想起高更的名言:“我是谁?我来自哪里?我将去往何方?”我会想起尼古拉斯·凯奇主演的经典电影《战争之王》的令人印象深刻的片头:一颗子弹被造出来,被抛上传送带,经过检验,装入箱子,辗转运到不知名的武装分子手中,然后被装入枪膛,漫无目标地被射出去——它朝向一个手无寸铁的孩子,毫不迟疑地射入他的脑袋,血花飞迸……这颗子弹的悲剧在于它不能掌控自己的命运,它只是一颗子弹。而高更,因为会问自己那三个问题,所以他可以离开城市,找到自己的理想家园高更晚年的大部分时间都住在南太平洋的美丽小岛塔希提。

如果我们不想让过程失控,不想让所做的努力付之东流,那么就应慎始图终阎锡山故居楹联:“思深虑远审微察渐,履中踏对慎始图终”;《左传》:“慎始而敬终,终不困”。,在事情开始时就谋划周全。一个优秀的程序员绝不仅仅是一个代码员,他会常常问自己:“我睡醒了吗?我为谁工作?我的鞋在哪里?”请记住这三个问题,它们会帮助你肩负起程序员这个职业赋予你的光荣使命,成为代达罗斯西方的鲁班,能工巧匠,著名克里特迷宫的建造者。传说他造完迷宫后,自己也找不到出路,于是用鸟羽制造了翅膀,从迷宫中飞了出来;英国一个宏大的航天计划以代达罗斯为名;如果你是一个SG(Star Gate,《星际之门》)谜,你也一定会记起《亚特兰蒂斯》季里,有一艘人类当时最先进的飞船就叫代达罗斯。一样伟大的建筑师,否则你有可能会陷入Matrix矩阵在《黑客帝国》里,Matrix矩阵(也就是母体)使用人类的大脑作为并行处理器,以使程序不断进化。的深渊,成为代码的奴隶,迷失或被累倒垮掉,发出阵阵痛苦的嗥叫这是很多程序员的真实写照。因为语涉“迷失”、“垮掉”和“嗥叫”,所以借用了一下文学典故:美国战后有“迷失的一代”、“垮掉的一代“文学流派”,“垮掉的一代”代表诗人金斯堡有著名长诗名为《嚎叫》。

所以,在开始编码之前还是先屏息静气,坐下来把数据库准备好吧,这有助于我们在进入编码阶段后没有后顾之忧,集中精力去攻克难关。准备数据库也是梳理开发思路的恰当时机,在对表及字段精心设计安排的过程中,程序结构和功能也会在我们的头脑中越来越清晰。

4.1.1 数据库的设计

本实例中最基本也是重要的内容,是对可幻教育机构的介绍和新闻文章,这些文章是官方性质的,向访问者全面、系统、权威地展示机构的概况。另外还有一个公共博客,可由机构内部人员或经过授权的作者来发表非官方的内容。介绍文章、新闻文章和博客文章虽名称和作用不同,但从数据表设计的角度来看,它们三者的本质是一样的,都是一种页面文章(page),拥有相同的字段属性,如标题、内容、创建时间、更新时间、作者,分类、星级等。所以,我们只需设计一个pages表,即可存储此类型的各种数据。在本章中,我们先来设计这个用以存放网站主要页面内容数据的表core_pages,表名加前缀core_,指明这是一个核心表,将会被整个系统使用。

图4-1是表core_pages的字段和注释说明。

图4-1 core_pages表示意图

相信有Web开发基础的读者通过字段命名和注释,就可以基本理解这个表的结构和作用了,这里就不再详述,仅做一些简单说明。

● star是区分文章级别的字段,星级设得越高表明文章越重要或越好,在程序中我们将把它们显示在相对重要的地方;同理,top可用于将页面置顶,以引起注意。

● comment字段不是存储评论内容,而是评论的开关。

● 表中的cid、uid分别对应category表和user表的主键id,关联页面分类和作者,在后面的章节中还会详加说明,这里先暂略。

本章的实例使用这一个表就够了,其他表在随后的例子中用到时再介绍,这样做是为了照顾一部分读者,好让他们尽快体验一下Zend Framework的魅力。数据库的设计是一个很重要的基础工作,要先从需求分析开始,然后将需求进行分析,归纳、综合成抽象概念,再进一步将概念转化为被数据库工具支持的逻辑模型,然后再次将其具象为各种关系表、字段和索引。这项工作本身就是一个系统工程,所以最好有全局性的考虑,整体规划并实施,而不是零零碎碎地随用随建。

4.1.2 创建数据库

好了,现在我们打开phpMyAdmin,创建一个名为kehuanedu_db的数据库,在其中建立core_pages表,完成以上表的设计。或者将以下代码复制到SQL命令行中执行:

        CREATE TABLE IF NOT EXISTS `core_pages` (
          `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '页面唯一id',
          `cid`  int(10)  unsigned  NOT  NULL  DEFAULT  '0'  COMMENT  '分类id,与core_categories表的id对应',
          `uid` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '用户id,与core_user表的id对应',
          `title` varchar(255) NOT NULL COMMENT '页面标题',
          `body` text NOT NULL COMMENT '内容',
          `status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '是否发布',
          `createtime` int(11) NOT NULL DEFAULT '0' COMMENT '创建页面的时间',
          `updatetime` int(11) NOT NULL DEFAULT '0' COMMENT '修改页面的时间',
          `comment` tinyint(4) NOT NULL DEFAULT '0' COMMENT '页面是否开启评论功能:0 = 否, 1 = 是',
          `star` tinyint(4) NOT NULL DEFAULT '0' COMMENT '页面的星级,共分五级,默认0为无星级',
          `top` tinyint(4) NOT NULL DEFAULT '0' COMMENT '置顶:0=否,1=是,',
          PRIMARY KEY (`id`),
          KEY `type` (`type`)
        ) ENGINE=InnoDB   DEFAULT CHARSET=utf8;

4.1.3 添加示例数据

在后面的章节里,我们会学习使用表单向数据库写入数据,目前我们需要手工向刚才创建的各表中添加一些初始的示例数据,以方便下一步代码的编写。在phpMyAdmin中打开一个表,单击“插入”标签,可以很方便地在该表中插入数据。

本例在core_pages表里插入以下一条数据,body字段内容为:

<p>学院从4月份起即开始的装修和粉刷工程,近日基本完工。包括学院办公大楼、东西两大教学区、学生宿舍、餐厅和招待所、公寓在内的全部场所,都进行了全新粉刷。现在步入学院,蓝绿相间的校舍与成荫的绿树掩映,一派盎然生机。</p> <p>办公楼里外都进行了装修,老旧的木窗被换成了塑钢门窗,楼顶重新进行了防水处理,三楼的会议室和楼道都吊了顶。</p> <p>这次施工,重点也将招待所进行了整修,门前旧砖地面全部换上了新砖,门窗也换为塑钢门窗,配套的水房、垃圾池等都得到了彻底的改造。</p>

这是一段带有<p>标签的文字,用以区分段落。以后我们会学习在前台使用在线编辑器来生成并提交内容到后台数据库,其中的分段标签会由编辑器来自动生成。在添加该条数据时,为了简便起见我们只需要输入title、body、star三个字段,title中输入“学院装修和粉刷工程完工,面貌焕然一新”,在star中输入4,标明该文章是4星级文章,这个字段值将会作为我们下一步数据库查询的条件。

继续插入一条文章数据,body字段内容为:

<p>学院自2005年开始创办以来,已走过5年历程,已积淀了很多有价值的成果,为了把这些成果珍藏并展示出来,学院正在筹划建设一个专用的展览陈列室。经过几次开会讨论,群策群力,展览室的设计已雏形初具,正在由史处长、李校长、李金宇老师负责装修布置。</p><p>建成的展览陈列室将永久性展示学院这些年来在教学方面的专业成果、优秀学生作品、荣誉和奖品等,另外还会制作视频内容多媒体设备播放,让来访者方便、快捷地了解学院的全貌。</p>

title字段输入“学院将建设展览陈列室列上日程”,star字段为4,top字段为1,表明这篇文章应该置顶显示。

4.1.4 在application.ini文件中配置数据库信息

数据库创建完成,之前我们已安装好Zend Framework并让它跑起来了,现在我们要对框架进行一些配置,让框架能连接数据库,它才能开始真正为我们工作。先来认识一下配置文件application/config/application.ini,打开它,它应该是以下样子:

        [production]
        phpSettings.display_startup_errors = 0
        phpSettings.display_errors = 0
        includePaths.library = APPLICATION_PATH "/../library"
        bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
        bootstrap.class = "Bootstrap"
        appnamespace = "Application"
        resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
        resources.frontController.params.displayExceptions = 0
        resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts/"

        [staging : production]

        [testing : production]
        phpSettings.display_startup_errors = 1
        phpSettings.display_errors = 1

        [development : production]
        phpSettings.display_startup_errors = 1
        phpSettings.display_errors = 1
        resources.frontController.params.displayExceptions = 1

提示:

在ini文件中,[]之间小节名称中的冒号表示继承,如[development : production]表示一个development小节,它继承了production小节的属性配置。

这个ini格式的文件有production、staging、testing、developmnet四个小节,分别可为生产、演示、测试、开发四个环境定义不同的配置,production小节中定义了一些基本的配置参数,逐行说明如表4-1所示。

表4-1 参数配置说明

staging、testing、development继承了production的所有属性,并且testing和development对其中显示错误和抛出异常的配置进行了改写,以使得在测试和开发过程中,能得到详细的错误提示和异常抛出信息。

注意看其中有一行resources.layout.layoutPath = APPLICATION_PATH "/layouts/ scripts/",它是我们在第3章开启layout时ZF tool工具自动添加到这里的,用以指明layout资源的路径,全部大写的APPLICATION_PATH表明这是一个常量,该常量是在public/index.php入口文件中声明的,用以指定application文件夹的绝对路径,因为public/index.php是整个项目的唯一入口和必经之路,所以我们在项目的任何地方都可以来引用这个常量以定位其他文件。

1.配置数据库信息

接下来让我们为配置文件添加数据库信息,以使框架与数据库建立连接。在application.ini中添加以下代码:

        [development : production]
        phpSettings.display_startup_errors = 1
        phpSettings.display_errors = 1
        resources.frontController.params.displayExceptions = 1

        resources.db.adapter = "PDO_MYSQL"
        resources.db.params.host = "localhost"
        resources.db.params.username = "root"
        resources.db.params.password = "root"
        resources.db.params.dbname = "khedu_db"
        resources.db.params.charset = "utf8"
        resources.db.isDefaultTableAdapter = TRUE
        resources.db.params.driver_options.1002 = “SET NAMES UTF8;”

resources.db.adapter = "PDO_MYSQL"声明数据库适配器为PDO_MYSQL。Zend Framework提供了一个PDO数据库层,可以支持包括Oracle、MySQl、SQLitet、Microsoft SQL Server、PostgreSQL、IBM DB2等在内的多种数据库。当我们使用这些数据库时,只需在配置文件中指定resources.db.adapte(数据库适配器)即可,以后如果要更换数据库,也只需更改配置文件,无须改动程序代码。我使用的是MySQL数据库,如果你用其他类型的数据库,将resources.db.adapter = "PDO_MYSQL"中的MYSQL换成你的数据库类型就行了。

接下来的5行分别配置了数据库服务器(localhost)、使用数据库的用户(root)和密码(root),数据库名称(khedu_db)、数据库编码方式(utf8),resources.db.isDefaultTable Adapter= TRUE指定本适配器为项目的默认数据库适配器,这样如果在项目中使用了不止一个数据库,则调用DefaultTableAdapter即可方便地使用本数据库。最后resources.db. params.driver_options.1002 = "SET NAMES UTF8;"可以使数据在页面、表单间输入输出都以utf8的编码方式进行,如果这里加了这条配置,应确保你的项目里所有页面的编码方式也是utf8,以防出现乱码。

2.修改命名空间

如果我们习惯用ZF tool来创建文件,那么必须在根目录下的.zfproject.xml这个文件里找到以下这一行代码:

<applicationDirectory classNamePrefix="Application_">

将其修改为:

<applicationDirectory classNamePrefix="Kh_">

.zfproject.xml是ZF tool工具相关的配置文件,classNamePrefix(类名前缀)预定义未来要创建的控制器、模型、表单等的名称前缀。这里如果做了改动,那么配置文件application.ini中也要做出相应修改,以便让Zend Framework自动加载类时能正确识别类名称。

打开application/configs/application.ini,找到下面的一行:

appnamespace = "Application"

将其改为:

appnamespace = "Kh_"

以上两处修改也可以由以下zf命令来实现:

zf change application.class-name-prefix Kh

3.让框架运行在开发环境中

默认框架运行在生产环境中,所以我们在开发环境(development)中设置的错误显示、异常信息和以上配置的数据库信息都不起作用,我们需要将框架改为运行在开发环境中。打开public/index.php,找到以下代码:

        defined('APPLICATION_ENV')
            || define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv ('APPLICATION_ENV') : 'production'));

将其中的'production'改为'development'。这样一来,当前项目就将运行在开发环境中,它将使用application.ini里面development节段的参数来运行框架,包括使用我们刚刚定义好的数据库信息,以及打开开发调试的错误提示显示开关。网站上线时,应在application.ini中把实际生产环境的数据库配置改放到[production]小节中,然后再到此index.php中将'development'改回为'production'。

4.利用ZF tool进行快捷配置

以上配置也可以用ZF tool的命令来实现,可以更简便快捷,方法如下:

使用ZF tool的命令进入项目文件夹中执行以下命令(注意,本书中是在Linux下给的命例,在Windows的CMD下执行时,要把参数里的单引号改成双引号,否则会报错):

        zf configure db-adapter
        "adapter=PDO_MYSQL&host=localhost&username=    root&password=root&dbname=khedu_db&charset=utf8" development;

参数解释如下。

● adapter:适配器,如MySQL为PDO_MYSQL,还有SQL_LITE等。

● host:数据库所在服务器地址,如本机为localhost。

● username :数据库用户名。

● password:密码。

● dbname:数据库名。

● charset:数据库编码,如utf8。

打开application/configs/application.ini文件,会看到development段中,数据库的相关信息已经配置好了。如果以上命令的结尾是production,则数据库的信息会配置在production小节中。

注意以下这两行无法通过ZF tool创建,需要手工添加一下:

        resources.db.isDefaultTableAdapter =TRUE
        resources.db.params.driver_options.1002="SET NAMES UTF8;"