新版手册我们打算用另一个教程方式,让大家能更容易体验到web开发的过程

    新的方式主要是将原始的HTML页面提供下载,大家可以先下载全部页面,跟着教程来制作程序。如果期间有不明白的地方,可以下载完整的例子程序作为参考。

    下载完整例子压缩包

    首先,解压“HTML页面压缩包”,我们可以看到一个html文件(guestbook.html)以及一个资源目录(i目录)。

    1. 把资源目录i放到之前介绍的Helloworld程序的index.php同级目录。大概会是这样子。

    2. 然后把guestbook.html文件剪切到protected/view目录下。

      第二次放

      这样图片/CSS/JS等就可以正常显示了。


    首先我们来看看,留言本的需求,也就是我们的程序将要实现什么功能:

    • 访问者可以查看留言首页。
    • 访问者可以进行留言。

    请注意,在入门教程接下来的章节里面,我们还会介绍如何分页显示留言、用户点赞、管理员管理留言等功能的实现方法,本章仅是介绍简单留言本的制作。

    大家可以发现留言本的HTML页面中,已经包含了这些功能的样式。那就努力完成本章并且接着学习吧。

    我们来看看,在上面需求中所涉及的数据有哪些?

    对,仅是留言信息。那么我们大致考虑,留言信息会包括:留言标题,留言内容,留言者名字。另外,我们留言的信息还需要包括一个唯一的标志,以区分每一条留言。好了,那么我们就可以得出,留言本程序的数据表仅有一个“留言表”(起个英文名叫guestbook),它的大致结构是:

    • 留言标题,字符串(也就是中英文)形式,大概不会多于50字。用title做数据表的字段名称。
    • 留言内容,字符串,也不会多于200字吧,用contents做字段名。
    • 留言者名字,字符串,大概在20个字以内,用username做字段名。
    • 唯一标志,一般用数字形式的ID。用id做字段名。
    • 另外还有个留言时间要记录的,一般php开发我们会用“时间戳”来记录时间。时间戳是11位的数字。

    按以上的说明,我们可以得出以下的数据表结构。

    对于数据库知识,我们提倡的是按需学习,也就是用到哪些就学哪些,毕竟“书上讲得深奥,实际没有用到”,那就是费力不讨好。并且,在实际工作中,PHP程序员所需要的,也仅仅是一小部分的数据库知识,万一遇到更复杂的数据库需求我们也有非常多的解决途径,比如同事之间讨论,SpeedPHP论坛求助,找GOOGLE大神等等。所以除非是很有必要(比如工作是程序员兼数据库管理员DBA的人员),不然数据库知识方面,我们也是浅尝辄止即可。

    初学PHP,我们建议可以了解一下以下的数据库知识就足够,不需要给自己太多的学习压力。

    • 在类似PhpMyAdmin的数据库管理工具中,如何建表。
    • CREATE,UPDATE,DELETE,SELECT四个语言的简单用法。
    • 懂得思考和想方法解决遇到的问题。
    • 使用数据库管理工具而不用纯粹SQL语句和命令行并没有什么荒废知识的问题,毕竟那会更简单快捷并且避免许多问题,这是提高开发效率的必然选择。

    在PhpMyAdmin中建好了guestbook表:

    然后,我们可以在protected/config.php文件中对程序进行数据库的配置:

    1. "localhost" => array( // 域名必须匹配
    2. 'debug' => 1,
    3. 'mysql' => array(
    4. 'MYSQL_HOST' => 'localhost', // 数据库地址
    5. 'MYSQL_PORT' => '3306', // 数据库端口,一般是3306
    6. 'MYSQL_USER' => 'root', // 数据库用户名
    7. 'MYSQL_DB' => 'test', // 数据库库名称
    8. 'MYSQL_PASS' => '', // 数据库密码
    9. 'MYSQL_CHARSET' => 'utf8', // 编码,一般utf8即可
    10. ),
    11. ),
    12. );
    1. $domain下面是域名,必须跟当前web站点的域名相同,比如说本机学习测试时,一般会用localhost;如果是发布到网上,如果你的域名是 ,那么就必须设置成”php.test.com”。否则会出现500错误。
    2. 数据库的配置资料,一般网上购买的主机空间都会提供,请联系主机提供商。

    接下来,我们打开protected/controller/MainController.php文件,把原来的

    1. function actionIndex(){
    2. echo "Hello World";
    3. }

    改成

    1. function actionIndex(){
    2. }

    打开浏览器看看http://localhost

    显示模板

    我们已经把页面给显示出来了。


    这里我们先来开发“发表留言”的功能,毕竟要先有数据,才好显示。

    还是protected/controller/MainController.php,我们加入新的方法actionWrite()

    actionWrite()方法还是以action开头,代表了这是一个页面,里面现在只是通过dump(arg())函数把提交的数据输出一下,方便我们验证表单提交是否正确。

    这种dump()提交数据的方式建议大家多用用,这是非常有益的小习惯。很多时候我们会发现表单失效首先是因为提交数据不对引起的。一开始就验证提交数据会保证数据不会错。

    接下来修改模板,打开protected/view/guestbook.html模板,大概在109行左右,我们可以看到有填写留言的表单form。

    1. <form method="POST" action="#">

    把它的action,也就是指向地址,改为我们的提交留言地址。

    1. <form method="POST" action="<{url c="main" a="write"}>">

    保存文件后打开浏览器刷新一下localhost,右键查看源代码,会发现这个地址已经变成了:

    这里是url模板函数的功能,具体可以参考手册关于url函数的介绍。

    我们点击“发布留言”,并且随便输入点什么,再点击“提交”按钮。

    顺便写点留言

    提交后会发现浏览器已经来到了

    这个地址对应的就是MainController内的actionWrite()方法。

    然后我们继续来编写actionWrite()方法:

    1. function actionWrite(){
    2. dump(arg());
    3. // 构造新建留言的数据
    4. $newrow = array(
    5. "contents" => arg("contents"),
    6. "username" => arg("username"),
    7. "createtime" => time(), // time()函数可以产生当前时间戳
    8. );
    9. // 实例化一个guestbook的模型类
    10. $guestbook = new Model("guestbook");
    11. // 使用Model的create方法把前面的数据插入到数据表中
    12. $result = $guestbook->create($newrow);
    13. // 输出一下结果,如果是1,那证明已经插入了1条新的数据
    14. dump($result);
    15. }

    我们来看看:

    1. $newrow是一个字段(key)和数据表guestbook字段对应的php数组,如title,contents等字段。
    2. $newrow各字段的值,是提交上来的值或者是时间戳。如arg(“title”)对应的就是模板中提交的title数据。

    3. time()函数会产生一个11位的时间戳,我们经常用其来存储php的时间,这里将time()的结果存到createtime字段上面去。

    4. new Model(“guestbook”)的方法可以实例化一个Model类,这个类对应的数据表是刚才我们建的guestbook表。
    5. 调用Model类的create()方法来插入新记录,create方法接收一个数组,数组是新记录的数据。
    6. create()方法返回的结果是“影响行数”,比如说新增了一行数据,那么返回就是1。这里可以把返回1当作新增记录成功的表现即可。
    7. 我们来看看数据库,发现记录已经新增了。

    接下来我们加个“留言成功”的提示上去,把dump()输出的内容删除,那么“填写留言”的功能就完成了。

    1. function actionWrite(){
    2. dump(arg());
    3. // 构造新建留言的数据
    4. $newrow = array(
    5. "title" => arg("title"), // 字段一一对应
    6. "contents" => arg("contents"),
    7. "username" => arg("username"),
    8. "createtime" => time(), // time()函数可以产生当前时间戳
    9. );
    10. $guestbook = new Model("guestbook");
    11. // 使用Model的create方法把前面的数据插入到数据表中
    12. $result = $guestbook->create($newrow);
    13. // dump($result);
    14. $this->tips("留言成功!", url("main", "index"));
    15. }

    新增记录

    $this->tips()方法是BaseController类自带的方法,只是弹出一个JS提示。如果需要更漂亮的提示,可以自行修改该方法的实现。


    接下来是显示留言列表,还是protected/controller/MainController.php,我们修改一下actionIndex()方法。

    1. function actionIndex(){
    2. // 实例化一个guestbook的模型类
    3. $guestbook = new Model("guestbook");
    4. // 用findAll()方法查询guestbook表的全部数据
    5. $this->records = $guestbook->findAll();
    6. // 输出看看
    7. dump($this->records);
    8. // 为了清楚看到输出,我们先屏蔽页面输出
    9. //$this->display("guestbook.html");
    10. }
    1. 跟actionWrite()方法一样,我们先实例化一个guestbook表的模型类。
    2. 然后调用模型类的findAll()方法,得到结果是$this->records。
    3. 输出$this->records看看。

    这里我们可以看到,变量$this->records的内容是一个多维数组,分别对应了数据表guestbooke里面的两条记录,每条记录的字段(key)是数据表的字段名称,对应值的是数据本身。

    $this->records这样的变量是控制器的成员变量,而这个写法跟普遍变量(比如说$records)不一样的地方是,$this->records可以在模板内直接使用。

    也就是说,在控制器内,通过$this->赋值的变量,都可以在模板内使用;而普通的变量并没有这样的功能。

    这也是最基础的模板引擎的用法之一。

    这里看到我们希望的数据已经出现在$this->records变量中了,那么我们在模板里面来使用这些数据吧。

    打开protected/view/guestbook.html文件,大概在27行左右,找到

    1. <div class="panel panel-default">
    2. ...
    3. </div>

    这个div和它的范围(结束的</div>大概在52行)。可以看出来下面还有一个相同的。这里一块div就是页面上显示的一块内容:

    div范围

    这里我们来做个循环,把$this->records变量的内容循环显示出来。

    请注意在模板内,$this->records变量对应的内容变量是$records。

    模板内的内容,可以通过变量进行替换输出的。所以我们主要关注用<{和}>包住的部分。

    1. 首先是一个大的<{foreach}><{/foreach}>,这里代表了整个区域的HTML代码会被“循环”输出,循环的次数根据$records的记录条数而定。(我们可以看到循环了两次,证明数据库里面guestbook表是有两条记录的)
    2. foreach的语法跟php本身的foreach是差不多的,<{foreach $records as $r}>指的是将$records循环,然后每次循环出来的值都赋值给$r。那么每次循环里面,$r实际上是代表了一个一维数据,字段(key)名对应数据表的字段名,值是数据表的记录内容。而通过点号(.)可以把值取出来显示在页面上,如<{$r.title}>就能取到title字段的值了。
    3. 然后标题,内容,用户名的位置,分别被<{$r.title}>,<{$r.contents}>,<{$r.username}>所替换,分别输出对应的值。
    4. <{date(“Y年m月d日 Hs”, $r.createtime)}>是显示时间,使用了php函数date来格式化我们的createtime存储的时间戳。

    这里我们先把MainController里面的dump()输出去掉,恢复display显示模板。

    1. function actionIndex(){
    2. // 实例化一个guestbook的模型类
    3. $guestbook = new Model("guestbook");
    4. // 用findAll()方法查询guestbook表的全部数据
    5. $this->records = $guestbook->findAll();
    6. // 输出看看
    7. // dump($this->records);
    8. $this->display("guestbook.html");

    另外把刚才的div下面的另一个div整个删除,这样我们就可以看到数据库输出的内容了。

    最终结果

    这样我们就完成了初步的留言本开发了,现在可以多发点留言上去试试了哦。

    接下来的教程,我们会继续介绍如何扩展这个留言本,让它变得更有趣。