一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

PHP CodeIgniter 框架开发企业网站实录笔记

时间:2015-11-09 编辑:简简单单 来源:一聚教程网

大多数企业网站都以提供用户浏览内容的服务为主,较少需要用户输入,网站的建设目标应以提供信息并且使之简明、清晰、美观为主;而如果企业网站同时提供在线购买,则需要安全,事务等更多目标;博客或在线论坛每天都将产生大量的新数据,网站的建设目标则要考虑到内容的分类与质量评判,确保不同类别的优质内容可以展示给适当的读者。

无论是哪一种类型的网站,网站架构师都应考虑以下通用设计目标:

    选用一种动态语言,即便网站只是展示静态的内容,它将帮助您更好的完成其他目标
    选用一个合适的数据库用于存储信息
    遵循 MVC 架构,使您的网站保持灵活

以上设计目标是对网站技术层面的要求。除此之外,网站的设计要遵循对用户友好的原则。随着网站的上线,您会发现,对于那些以提供浏览为主的网站,搜索引擎可能会是网站上最为“活跃”的用户之一。对搜索引擎友好,足以成为一个网站最重要的设计目标。举例来说,一个搜索引擎“爬虫”都难以访问到的页面,可能很难被“自然人”发现。如果网站有很多不容易被访问到的页面,这个问题很有可能是网站的结构导致的,这是网站架构师不希望看到的。

为了尽力避免类似的问题产生,网站架构师应考虑以下通用设计目标:

    网站结构清晰,按照内容或服务分类,提供分类导航
    在层级较深的子页面提供面包屑导航,所有的页面都会被链接到
    URL 的层级设计与内容层级相关联
    URL 尽量简短,有意义,并包含页面关键字

这些设计目标配上实际的例子会更加容易理解。很多知名的企业网站已经做了很好的设计例子给网站架构师参考。

对于网站结构的设计目标可以参考 IBM developerWorks 网站。在页面顶部、技术主题、软件下载、社区和技术讲座四大板块的导航贯穿 IBM developerWorks 网站的所有页面。在每一个子页面,总导航下方可以看到面包屑导航。以本文为例,面包屑导航给出了本文在 IBM developerWorks 网站所在的位置是 developerWorks 中国 > 技术主题 > Web development > 文档库。这样的导航可以帮助包括搜索引擎爬虫在内的所有网站读者,随时找到自己的位置,返回或去往任何想要到达的地方。

URL 的层级设计应于内容层级相关联。例如,
IBM 的美国和中国首页分别是

    www.ibm.com/us
    www.ibm.com/cn

对比下面两个 URL

    www.example.com/index.php?lang=en_us
    www.example.com/index.php?lang=zh_cn

前者通过层级设计表现了有关联的两个不同页面,采用了更短的 URL,更易读易记,对搜索引擎也很友好。

后者则通过将语言类型以传参的方式动态传递给同一个页面来展示不同页面,使 URL 更长,可读性较差,不容易记住,对搜索引擎不太友好。

虽然绝大多数搜索引擎已经能够正常收录不同参数传递给同一页面产生的多个动态页面,但当参数个数变多的时候,搜索引擎可能无法完整探寻到每一个动态页面从而导致网站无法被完整收录。请记住,无论是人还是机器,对于 URL 参数传值的理解都不如 URL 层级的理解来得直观。

最佳的 URL 设计应当向下方的 URL 这样,没有一个多余的字符(.html 也是不必要的),让人印象深刻,即便不打开页面也很清楚页面要表达的内容

    http://en.wikipedia.org/wiki/IBM
    http://zh.wikipedia.org/wiki/IBM
    http://store.apple.com/us/buy-iphone/iphone6
    http://store.apple.com/cn/buy-iphone/iphone5s
    http://store.apple.com/cn/buy-mac/imac-retina

在 URL 的设计过程中要不断的审视每一个 URL,去掉所有不必要的字符,让 URL 更短,更明了。要相信,好的 URL 自己会说话。作为对比,下面会给出两个 URL 设计的反例供参考。

    http://www.example.com/wiki/showcontent.php?lang=en&word=IBM
    http://www.example.com/store/producthandler.php?action=buy®ion=cn&productname=xphone&productmodel=xphoneplus8


模型-视图-控制器(MVC)设计模式

MVC 是一种将应用程序的逻辑层和表现层进行分离的设计模式。

    模型(Model)代表数据控制器。数据的读取,插入,更新都是由模型来负责。
    视图(View)是展示给用户的最终页面。视图负责将数据以用户友好的形式展现出来。
    控制器(Controller)是模型,视图以及其他任何处理 HTTP 请求所必须的资源之前的中介

MVC 模式可以让网站的代码以最小的改动,灵活应对各种变化。当业务逻辑发生变化时,模型和视图可以保持不变,仅调整控制器;当需要改动 UI 时,模型和控制器可以不做任何变化,也不受视图变化的影响。

严格的遵循 MVC 模式,可以让数据,业务逻辑和页面展示完全隔离开来。这样使问题诊断变得更加容易。

通常,一个典型的页面浏览行为在程序端的流程是这样的:

    控制器最先被调用,并被赋予外部输入
    控制器根据外部输入向模型请求数据
    模型从数据库获取数据并发送数据到控制器
    控制器处理该数据并发送封装好的数据到视图
    视图根据接到的数据最终展示页面给用户浏览

当网站的页面出现错误时,我们可以根据上面流程做正向或者逆向的诊断。以逆向诊断为例,首先确认视图接收到的数据是否是正确的,如果是数据正确,那么错误的源头就来自视图;如果数据有问题,那么向上追溯到上一步,检查控制器接收到的数据是不是正确的… 以此类推,直到找到问题出现的部分。

虽然最终用户无法直接从 MVC 设计模式中受益,采用该设计模式会为网站的开发维护带来极大的便利。

developerWorks 上有很多 MVC 设计模式的文章,您可以根据需要搜索并阅读与 MVC 设计模式相关的文章。接下来我们将正式介绍如何使用 PHP CI 框架开发一个企业网站,并实现前文提及的设计目标。


使用 CI 开发企业网站

CI 概述

CodeIgniter 是一套给 PHP 网站开发者使用的应用程序开发框架和工具包。它的特点包括且不局限于:

    小巧但性能出色
    广泛兼容各种 PHP 版本
    几乎零配置且不需使用命令行

从 CodeIgnitor 官方网站下载 CI 的安装包,解压后进行简单配置即可使用。关于 IDE,笔者使用的 IDE 是 Netbeans。Netbeans 提供了完整的 PHP 语言支持,您可以使用自己喜欢的 IDE 进行 PHP 开发。在 Netbeans 中创建一个名为 www 的 PHP 项目,并将 CI 解压缩至 www 目录。

图 1.目录结构图:
图 1.目录结构图:


默认情况下,index.php 是所有 CI 程序的入口。这意味着,所有的 URL 都将包含 index.php。我们需要设置.htaccess 文件将 index.php 从 URL 中移除。打开.htaccess 文件并添加以下四行代码,保存并退出。

.htaccess 代码

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1 [L]

让我们看一下上面每行代码的作用:

    RewriteEngine on 用于打开 Apache 的 URL 重写
    RewriteCond %{REQUEST_FILENAME} !-f 代表如果请求的文件存在,则直接访问该文件;如果文件不存在,则进行至下一步
    RewriteCond %{REQUEST_FILENAME} !-d 代表如果目录存在则直接访问目录;如果目录不存在,则进行至下一步
    RewriteRule ^(.*)$ /index.php/$1 [L] 如果所请求的路径不是存在的文件也不是存在的目录,则在路径前追加/index.php/

这样,我们在访问任何 CI 的 URL 时,就不需要指定任何 php 路径了。因为 index.php 是所有 CI 程序的入口。

至此 CI 已经准备就绪了,是时候讨论一下我们的企业网站了。

企业网站的业务需求

ABC 公司的网站主要向客户展示 ABC 公司的三个主营业务:解决方案、服务和产品。ABC 公司同样希望能够在网站为客户提供支持。ABC 的客户来自全球,所以 ABC 公司希望网站能够支持多种语言。

在看到这个需求后,网站架构师决定先从英文版本开始构建。其他语言版本将复用英文版本的设计。

按照业务的需求,网站被分为五个栏目,他们及他们对应的 URL 分别是

    Home - http://abc.com/en
    Solutions - http://abc.com/en/solutions
    Services - http:// abc.com/en/services
    Products - http:// abc.com/en/products
    Support - http:// abc.com/en/support

定义路由

当 CI 接收到一个用户请求的 URL 时,首先去路由表中查询该 URL 对应的控制器。我们首先为 Home 定义一个路由。路由文件的位置是 config/routes.php。打开路由定义,添加如下代码:

$route['en'] = 'en/home';

接下来我们将开始编写 Home 控制器。


控制器与视图 - 入门

在 controllers 目录下,创建目录 en,在 en 目录下创建 home.php,这将是我们的第一个控制器。在 home.php 中添加如下代码:
清单 1.controllelrs/en/home.php


class Home extends CI_Controller {

//Home 控制器的构造函数
public function __construct() {
parent::__construct();
}

//Home 控制器的默认入口 index()方法
public function index() {

//加载 views 目录下的/en/header.php 视图
$this->load->view('/en/header');

//加载 views 目录下的/en/home.php 视图
$this->load->view('/en/home');

//加载 views 目录下的/en/footer.php 视图
$this->load->view('/en/footer');
}

}

在 views 目录下创建目录 en,在目录 en 下分别创建 header.php、home.php、footer.php。代码如下:

清单 2.views/en/header.php

ABC.com - Header



清单 3.views/en/home.php

Welcome to ABC.com! - Body



清单 4.views/en/footer.php

Copyright - Footer



我们为 Home 控制器创建了三个视图。header 视图及 footer 视图还将被用于其他控制器。而 home 视图将仅被 Home 控制器调用。

如果您已经配置好 PHP 并已启动 Web 服务,您可以在浏览器输入 http://localhost/en 查看效果

图 2.效果图

效果图


这个简单的主页包含三部分静态的内容。分别是 Header, Body 以及 Footer。他们分别对应 views/en 目录下面的三个视图文件:header.php, home.php 及 footer.php。我们的 Home 控制器目前已经可以正常工作,而且它成功的加载了三个静态视图。

至此,我们还没有通过控制器发送任何数据到视图。接下来我们将定义控制器和视图的数据格式约定,并通过不同的控制器发送数据到 header 视图。


控制器与视图 - 进阶

目前 header 视图里面的数据(ABC.com ? Header)是由 header.php 自己定义的,我们会希望将数据由控制器发送到视图,而视图仅负责将数据展示出来。

接下来我们在控制器中定义一个$headerdata 数组,并把它发送到 header 视图。控制器 Home 的代码如下:
清单 5.controllers/en/home.php


class Home extends CI_Controller {

//定义 Header 数据数组$headerdata
protected $headerdata = array(

//定义页面标题数据
'title' => 'ABC - Home',

//定义页面导航栏数据
'nav' => array(
'Home' => array(
'url' => '/en',
'active' => TRUE
),
'Solutions' => array(
'url' => '/en/solutions',
'active' => FALSE
),
'Services' => array(
'url' => '/en/services',
'active' => FALSE
),
'Products' => array(
'url' => '/en/products',
'active' => FALSE
),
'Support' => array(
'url' => '/en/support',
'active' => FALSE
)
),
);
//Home 控制器的构造函数
public function __construct() {
parent::__construct();
}
//Home 控制器的默认入口 index()方法
public function index() {

//加载 views 目录下的/en/header.php 视图并将$headerdata 中的导航栏数据传递给 header 视图
$this->load->view('/en/header', $this->headerdata);

//加载 views 目录下的/en/home.php 视图
$this->load->view('/en/home');
//加载 views 目录下的/en/footer.php 视图
$this->load->view('/en/footer');
}
}

$headerdata 包含了 header 视图需要显示的标题及导航信息,在加载 header 视图时,我们将$headerdata 作为参数传递给了 header 视图。

接下来 header 视图将接收来自控制器的$headerdata,并展示信息给用户。header 视图的代码如下:

清单 6.views/en/header.php



<?php echo $title ?>


//遍历$nav 数组
foreach ($nav as $name => $value) {

//如果当前元素为’active’状态,则显示(Active)
if ($value['active']) {
echo "$name(Active)";
} else {
//如果当前元素为非’active’状态,则显示该页面名称,并附有该页面的链接
echo '';
echo $name;
echo '
';
}
echo ' | ';
}
?>


我们在 home 控制器中将$headerdata 传递给 header 视图,header 视图就可以直接访问$headerdata 的内部数据,无需指定数组名称。我们可以在 header.php 中,直接使用$title 来访问 home.php 中的$headerdata[‘title’];同样我们可以在 header.php 中,直接使用$nav 来访问 home.php 中的$headerdata[‘nav’]。

打开浏览器我们将看到如下页面

图 3.结果显示

结果显示

其他的控制器可以继续复用$headerdata 数组的数据定义,只需简单修改 title 的值,以及 active 的值,就可以控制导航栏动态变化;而 header 视图不需要为任何一个控制器做修改。是不是很酷!

至此我们已经看到了控制器与视图之间的动态交互,本文的最后一个部分将演示一个从 URL->控制器->模型->控制器->视图的完整流程。


URI 传参及模型-控制器-视图 - 完整流程

到目前为止,我们的 URL 中还没有传递任何参数给控制器,控制器也没有和模型交互。接下来我们要演示一个较为复杂的例子。

ABC 公司的 Support 栏目下包含 solutions, services 及 products 三个类别的支持信息,每一个类别下面有几百条支持信息。结构如下:

SUPPORT
├─products
│ issue001
│ issue002
│ issue003
│ …
├─services
│ issue001
│ issue002
│ issue003
│ …
└─solutions
issue001
issue002
issue003


由于这些支持信息的显示页面都是类似的,我们希望通过一个控制器负责显示所有的页面。一个常见的 URL 可能会是这样:

http://abc.com/en/support/show.php?category=products&id=issue001

如上文所述,这样的 URL 对用户是不太友好的,因此利用 CI 的 URI 路由特性,我们采用下面的 URL 来显示 products 的 issue001 页面

http://abc.com/en/support/products/issue001

此 URL 的定义如下

    第一段 abc.com 代表域名
    第二段 en 代表控制器的目录
    第三段 support 代表控制器的名称
    第四段 products 代表控制器的函数名
    第五段 issue001 代表传递给控制器的参数

接下来让我们来创建 support 控制器。在 en 目录下创建 support.php。代码如下:

清单 7.controllers/en/support.php

1
class Support extends CI_Controller {

//为 Support 控制器定义 Header 数据
protected $headerdata = array(

//定义 Support 页面标题
'title' => 'ABC - Support',
//定义 Support 页面导航栏
'nav' => array(
'Home' => array(
'url' => '/en',
'active' => FALSE
),
'Solutions' => array(
'url' => '/en/solutions',
'active' => FALSE
),
'Services' => array(
'url' => '/en/services',
'active' => FALSE
),
'Products' => array(
'url' => '/en/products',
'active' => FALSE
),
'Support' => array(
'url' => '/en/support',
'active' => TRUE
)
),
);
//定义 Support 页面的数据元素
protected $supportdata = array(
'type' => '',
'issue' => '',
'info' => ''
);
//Home 控制器的构造函数
public function __construct() {

//构造函数
parent::__construct();



//加载 Support 的数据模型
$this->load->model("support_model");
}



//Support 控制器的默认入口
public function index() {



//加载 header 视图并将 header 数据传递给视图
$this->load->view('/en/header', $this->headerdata);



//加载 footer 视图
$this->load->view('/en/footer');
}



//Support 控制器的 products 入口
public function products($issue) {



//定义 support 的数据为 Products 类型,存入$supportdata
$this->supportdata['type'] = 'Products';



//将 URL 传过来的$issue 参数存入$supportdata
$this->supportdata['issue'] = $issue;



//从 Support 模型中取出$issue 数据并存入$supportdata
$this->supportdata['info'] = $this->support_model->get_product($issue);



//加载 header 视图并将 header 数据传递给视图
$this->load->view('/en/header', $this->headerdata);



//加载 support 视图并将 supportdata 数据传递给视图
$this->load->view('/en/support', $this->supportdata);



//加载 footer 视图
$this->load->view('/en/footer');
}



}

相比 Home 控制器,support 控制器增加了以下内容:

    新定义了$supportdata 数组,用于传递给 support 视图
    在构造 support 控制器的同时,加载了 support 模型
    处理 support 模型返回的信息并封装成$supportdata

虽然我们在 Support 控制器中调用了 support 模型,但是到目前为止我们还没有编写它。接下来,我们来定义 support 模型。在 model 目录下创建 support_model.php。代码如下:

清单 8.models/support_model.php


class Support_model extends CI_Model {

//Support 模型的构造函数
public function __construct() {
parent::__construct();
}
//Support 模型的 get_product 方法,用于返回$issue 所代表的数据
public function get_product($issue) {

//返回$issue 的 support 信息
return "This is the support information for $issue";
}
}

这里我们略去了数据库访问操作,当 get_product()被调用时,support 模型直接将返回一条信息。至此,support 控制器已经可以从 support 模型拿到信息了。support 控制器把拿到的信息封装成$supportdata,并发送给 support 视图。

至此,我们已经定义了 Support 控制器和模型,最后让我们定义 support 视图。在 views/en 下创建 support.php,代码如下:

清单 9.views/en/support.php

Support - Body


echo "Type: $type
";
echo "Issue: $issue
";
echo "Information: $info
";

至此,support 控制器,模型和视图都已经准备就绪了。我们在浏览器里输入 URL 我们将看到:
图 4.最终结果
最终结果


结束语

本文简要介绍了网站的架构设计和目标,并使用 CodeIgniter 演示了 ABC 公司网站的开发过程。在实际的开发过程中,我们还需要考虑数据库设计及前端设计。

PHP 及 CodeIgnitor 支持多种数据库,笔者推荐采用 MySQL 数据库。最新的 MySQL 默认采用 InnoDB 模式,以更好的支持事务。如果网站没有事务需求,为了更好的性能,应采用 MyISAM 模式。

前端设计可以考虑使用前端框架,以减轻前端设计人员的工作量。Bootstrap 来自 Twitter,是目前最受欢迎的前端框架。

热门栏目