17.06.2015 Views

封面

封面

封面

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

封 面<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 1/85


卷 首 语<br />

《PHPer》<br />

卷 首 语<br />

2009 PHP 开 源 发 展 与 人 才 发 展 状 况 调 查 正 式 启 动<br />

PHP 作 为 一 种 广 泛 使 用 的 通 用 编 程 语 言 , 在 全 球 互 联 网 社 区 应 用 领 域 的 使 用 量 在<br />

同 类 产 品 中 已 经 位 居 第 一 。 在 中 国 , 由 于 近 年 来 SNS( 社 会 性 网 络 服 务 ) 的 兴 起 , 大<br />

批 互 联 网 公 司 进 军 SNS 市 场 , 他 们 中 的 大 多 数 又 都 是 以 PHP 作 为 开 发 工 具 , 这 就 给<br />

PHP 造 就 了 更 广 阔 的 应 用 前 景 。 经 初 步 估 计 , 中 国 目 前 已 有 几 十 万 的 PHP 爱 好 者 和 从<br />

业 人 员 , 他 们 虽 然 身 在 不 同 地 区 , 但 都 是 PHP、 开 源 的 忠 实 追 随 者 。<br />

虽 然 PHP 在 国 内 发 展 态 势 良 好 , 但 整 个 IT 行 业 对 PHP 在 国 内 具 体 的 发 展 情 况 并<br />

不 是 十 分 了 解 。PHP 在 国 内 的 应 用 处 于 什 么 水 平 ? 市 场 对 PHP 开 发 人 员 的 需 求 到 底 有<br />

多 大 ? 这 些 都 是 亟 需 解 决 的 问 题 。 针 对 上 述 情 况 ,PHPChina 网 站 展 开 了 09 年 PHP 开<br />

源 发 展 与 人 才 状 况 调 查 。 此 次 调 查 着 重 对 PHP 爱 好 者 的 分 布 、PHP 语 言 的 使 用 发 展 情<br />

况 、PHP 应 用 方 向 以 及 培 训 等 方 面 进 行 深 入 的 研 究 。 据 了 解 , 发 起 调 查 网 站 PHPChina<br />

作 为 一 家 国 内 开 源 社 区 的 门 户 网 站 , 专 注 于 PHP 在 中 国 的 推 广 和 应 用 并 为 广 大 的 PHP<br />

爱 好 者 和 从 业 者 提 供 学 习 和 交 流 的 平 台 , 是 中 国 PHP 相 关 方 面 的 权 威 网 站 。 而<br />

PHPChina 网 站 每 年 都 会 定 期 发 布 国 内 PHP 开 源 发 展 及 相 关 人 才 状 况 调 查 结 果 , 其 调<br />

查 结 果 已 经 成 为 目 前 国 内 互 联 网 企 业 了 解 中 国 PHP 技 术 发 展 及 人 才 状 况 的 重 要 途 径 。<br />

2009 年 , 社 区 和 SNS 在 国 内 如 火 如 荼 的 发 展 。PHP 在 国 内 的 技 术 应 用 提 高 多 少 ?<br />

PHP 爱 好 者 增 长 多 少 ?PHPer 的 需 求 有 多 大 ?PHPChina 展 开 09 年 PHP 开 源 发 展 与 人<br />

才 状 况 调 查 , 着 重 对 PHP 爱 好 者 的 分 布 、PHP 语 言 的 使 用 发 展 情 况 、PHP 应 用 方 向<br />

以 及 培 训 等 方 面 进 行 详 实 的 调 查 ; 通 过 不 同 等 级 的 调 查 , 我 们 可 以 对 PHP 爱 好 者 有 一<br />

个 较 全 面 和 深 入 的 了 解 ; 通 过 对 人 才 需 求 的 调 查 , 我 们 可 以 对 国 内 应 用 PHP 的 企 业 在<br />

PHP 人 才 的 需 求 有 一 个 更 直 观 数 据 分 析 。<br />

调 查 地 址 :http://phpchina.com/2009php/。<br />

刘 昊<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 2/85


PHPer 贡 献 者 名 单<br />

《PHPer》<br />

PHPer 贡 献 者 名 单<br />

2009 年 6 月 1 日 第 20 期<br />

主 管 :PHPChina.com<br />

主 办 :PHPChina 网 站 会 员<br />

网 址 :http://www.phpchina.com<br />

总 编 :PHPChina<br />

副 总 编 : 廖 宇 雷<br />

编 辑 :leehui1983 casual0402<br />

卷 首 语 : 刘 昊<br />

应 用<br />

知 识 库<br />

招 聘 : 王 志 军<br />

新 手 乐 园 : 尹 君<br />

扩 展 与 框 架 : 廖 宇 雷 、 高 洛 峰<br />

企 业 解 决 方 案 : 郭 欣<br />

高 级 应 用 : 蜗 牛<br />

项 目 管 理 : 李 桂 杰<br />

安 全 优 化 : 机 械 工 业 出 版 社<br />

LAMP 大 讲 堂 :Richard Petersen<br />

职 场 人 生 : 张 大 志<br />

校 验 排 版 :PHPChina<br />

后 期 制 作 : 兔 石 尾<br />

另 外 , 欢 迎 广 大 PHP 程 序 员 踊 跃 投 稿 !<br />

请 将 稿 件 发 送 至<br />

phper@phpchina.com<br />

请 注 明 所 投 栏 目 , 并 附 上 作 者 简 介 。<br />

PHP 中 国 开 源 社 区 感 谢 您 的 参 与 !<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 3/85


目 录<br />

《PHPer》<br />

目 录<br />

封 面 ........................................................................................................................................1<br />

卷 首 语 ....................................................................................................................................2<br />

PHPER 贡 献 者 名 单 ..............................................................................................................3<br />

目 录 ......................................................................................................................................4<br />

PHP 新 闻 ...............................................................................................................................6<br />

2009 年 9 月 语 言 排 行 榜 PHP 超 越 C++ .........................................................................6<br />

PHP 企 业 招 聘 .......................................................................................................................8<br />

新 手 乐 园 ..............................................................................................................................10<br />

探 讨 WEB 命 令 行 模 式 的 应 用 .......................................................................................10<br />

扩 展 与 框 架 ..........................................................................................................................16<br />

PHP 的 模 板 技 术 SMARTY( 一 ) ..................................................................................16<br />

1 什 么 是 模 板 引 擎 ........................................................... 16<br />

2 编 写 自 己 的 模 板 引 擎 ...................................................... 17<br />

2.1 创 建 自 己 的 模 板 引 擎 类 ................................................... 17<br />

2.2 使 用 自 己 的 模 板 引 擎 ..................................................... 20<br />

2.3 自 定 义 模 板 的 使 用 示 例 分 析 ............................................... 21<br />

3 选 择 Smarty 模 板 引 擎 ..................................................... 24<br />

4 安 装 Smarty 及 初 始 化 配 置 ................................................. 25<br />

4.1 安 装 Smarty ............................................................. 26<br />

4.2 初 始 化 Smarty 类 库 的 默 认 设 置 ............................................ 26<br />

4.3 第 一 个 Smarty 的 简 单 示 例 ................................................ 28<br />

QEEPHP 快 速 入 门 ( 七 )—— 实 现 任 务 管 理 ..............................................................30<br />

1 添 加 任 务 ................................................................. 30<br />

1.1 完 善 task 模 型 .......................................................... 30<br />

1.2 创 建 表 单 ............................................................... 31<br />

1.3 添 加 控 制 器 动 作 ......................................................... 32<br />

2 测 试 创 建 任 务 ............................................................. 33<br />

2.1 添 加 任 务 查 看 页 面 ....................................................... 34<br />

3 修 改 和 删 除 任 务 ........................................................... 35<br />

4 删 除 任 务 ................................................................ 38<br />

5 分 页 与 最 后 的 完 善 ........................................................ 39<br />

5.1 学 会 偷 懒 ............................................................... 39<br />

5.2 完 善 列 表 页 面 ........................................................... 40<br />

5.3 修 改 默 认 控 制 器 ......................................................... 40<br />

企 业 解 决 方 案 ......................................................................................................................42<br />

WEB 站 点 性 能 监 控 .........................................................................................................42<br />

1 实 时 监 控 ................................................................. 42<br />

2 监 控 代 理 ................................................................. 44<br />

3 系 统 监 控 ................................................................. 45<br />

4 服 务 监 控 ................................................................. 48<br />

5 响 应 时 间 监 控 ............................................................. 50<br />

项 目 管 理 ..............................................................................................................................54<br />

为 什 么 领 导 力 以 信 任 为 基 础 ( 二 ) ..............................................................................54<br />

努 力 去 争 取 挣 得 型 权 力 ........................................................ 54<br />

说 服 比 发 号 施 令 更 有 力 ........................................................ 54<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 4/85


目 录<br />

《PHPer》<br />

必 要 时 独 裁 专 制 .............................................................. 55<br />

相 信 别 人 .................................................................... 55<br />

信 任 是 灾 祸 的 保 险 ............................................................ 56<br />

榜 样 、 问 题 和 冲 突 ............................................................ 57<br />

领 导 者 要 规 范 信 息 反 馈 程 序 .................................................... 57<br />

高 级 应 用 ..............................................................................................................................59<br />

UCHOME2.0 登 录 验 证 机 制 分 析 .......................................................................................59<br />

1 登 录 ..................................................................... 59<br />

2 验 证 ..................................................................... 60<br />

UCHOME2.0 权 限 机 制 分 析 ...............................................................................................62<br />

1 隐 私 机 制 ................................................................. 62<br />

2 用 户 权 限 组 ............................................................... 63<br />

安 全 优 化 ..............................................................................................................................66<br />

WINDOWS 安 全 ( 二 ) .....................................................................................................66<br />

3 如 何 执 行 安 全 检 查 ......................................................... 66<br />

4 在 客 户 端 / 服 务 器 程 序 中 传 播 标 识 ............................................ 66<br />

4.1 远 程 认 证 与 安 全 支 持 提 供 者 接 口 ............................................ 67<br />

4.2 模 拟 级 别 ................................................................ 68<br />

5 系 统 边 界 上 的 安 全 检 查 ..................................................... 69<br />

LAMP 大 讲 堂 .....................................................................................................................71<br />

WEB 服 务 器 ( 二 ) .........................................................................................................71<br />

5 Apache 配 置 和 指 示 符 ...................................................... 71<br />

5.1 全 局 配 置 ............................................................... 72<br />

5.2 服 务 器 配 置 ............................................................. 73<br />

5.3 目 录 级 别 的 配 置 :.htaccess 和 ................................. 74<br />

5.4 访 问 控 制 ............................................................... 75<br />

5.5 URL 路 径 名 .............................................................. 75<br />

5.6 MIME 类 型 ............................................................... 76<br />

5.7 CGI 文 件 ................................................................ 76<br />

5.8 自 动 目 录 索 引 ........................................................... 77<br />

5.9 认 证 ................................................................... 77<br />

5.10 日 志 文 件 .............................................................. 78<br />

职 场 人 生 ..............................................................................................................................80<br />

大 学 生 求 职 七 大 昏 招 —— 说 谎 ( 四 ) ..........................................................................80<br />

关 键 问 题 , 具 实 回 答 .......................................................... 80<br />

回 答 对 自 己 不 利 的 问 题 要 有 策 略 ................................................ 80<br />

私 人 问 题 , 可 以 不 回 答 ........................................................ 81<br />

LAMP 新 书 .........................................................................................................................82<br />

《 构 建 高 性 能 WEB 站 点 》 ............................................................................................82<br />

《 大 道 PHP》 .................................................................................................................83<br />

《LINUX 命 令 速 查 手 册 》 ...............................................................................................84<br />

封 底 ......................................................................................................................................85<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 5/85


目 录<br />

《PHPer》<br />

PHP 新 闻<br />

2009 年 9 月 语 言 排 行 榜 PHP 超 越 C++<br />

PHPChina<br />

TIOBE 世 界 编 程 语 言 排 行 榜 展 现 了 编 程 语 言 的 流 行 趋 势 。 每 个 月 , 都 有 最 新 的 数<br />

据 被 更 新 。 这 份 排 行 榜 的 数 据 取 样 来 源 于 互 联 网 上 富 有 经 验 的 程 序 员 、 商 业 应 用 、<br />

著 名 的 搜 索 引 擎 ( 诸 如 谷 歌 、 MSN 、 雅 虎 ) 的 关 键 字 排 名 、 Alexa 上 的 排 名 等 。 请<br />

注 意 这 个 排 行 榜 只 是 反 映 了 某 个 编 程 语 言 的 热 门 程 度 , 这 并 不 代 表 它 是 一 个 最 好 的 编<br />

程 语 言 或 是 可 以 写 出 某 些 令 人 称 赞 的 好 程 序 。TIOBE 公 布 了 最 新 的 语 言 排 行 榜 PHP<br />

果 然 不 失 所 望 。 超 过 了 C++, 排 在 了 前 三 的 位 置 。<br />

Java 和 C 稳 居 榜 首 ,Java 依 然 是 最 热 门 的 编 程<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 6/85


目 录<br />

《PHPer》<br />

位 居 前 十 位 的 编 程 语 言 曲 线 变 化 图<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 7/85


PHP 企 业 招 聘<br />

《PHPer》<br />

PHP 企 业 招 聘<br />

Web 应 用 软 件 开 发 经 理<br />

招 聘 信 息<br />

公 司 名 称 : 北 京 热 酷 科 技 有 限 公 司<br />

招 聘 人 数 :1 名<br />

工 作 地 点 : 北 京<br />

薪 水 待 遇 :10k++ / month<br />

职 位 描 述 :<br />

1、 三 年 或 以 上 PHP Web 应 用 程 序 开 发 经 验 ;<br />

2、 熟 悉 SQL 数 据 库 应 用 开 发 , 能 熟 练 使 用 MYSQL 数 据 库 , 熟 悉 HTML/CSS 及<br />

Web 标 准 ;<br />

3、 具 有 良 好 的 敬 业 精 神 和 快 速 的 学 习 能 力 , 热 爱 软 件 开 发 , 擅 于 思 考 、 肯 钻<br />

研 ;<br />

4、 国 内 重 点 大 学 计 算 机 、 工 程 、 数 学 或 物 理 专 业 本 科 毕 业 。 如 果 你 渴 望 创 业 ,<br />

这 就 是 你 施 展 才 华 的 舞 台 。 你 将 获 得 丰 厚 的 公 司 的 原 始 股 票 , 你 的 经 验 和<br />

财 富 将 和 公 司 一 起 成 长 。<br />

任 职 资 格 :<br />

1 、 精 通 php+mysql, 要 求 至 少 有 1 年 以 上 的 php 开 发 经 验 ( 必 须 );<br />

2、 熟 悉 html,css,js,div 及 网 页 设 计 模 板 技 术 ;<br />

3、 熟 悉 SQL 语 言 , 能 熟 练 使 用 MYSQL 数 据 库 ;<br />

4、 具 有 良 好 的 敬 业 精 神 和 快 速 的 学 习 能 力 , 热 爱 软 件 开 发 , 擅 于 思 考 、 肯 钻<br />

研 ;<br />

5、 有 项 目 开 发 管 理 经 验 ( 必 须 )。<br />

联 系 方 式 :<br />

公 司 介 绍<br />

联 系 人 :PH PC hina 伯 乐<br />

电 子 邮 箱 :wangzhijun@comsenz.com<br />

联 系 电 话 :13146612015<br />

QQ: 752719295<br />

北 京 热 酷 科 技 有 限 公 司 是 一 家 新 兴 的 B2C 电 子 商 务 和 开 放 平 台 应 用 软 件 开 发 公 司 ,<br />

公 司 创 新 性 地 将 传 统 电 子 商 务 与 淘 宝 、 校 内 等 开 放 平 台 应 用 有 机 结 合 , 从 而 创 造 了 一<br />

种 全 新 的 运 营 和 推 广 模 式 。<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 8/85


PHP 企 业 招 聘<br />

《PHPer》<br />

PHP Web 应 用 软 件 开 发 工 程 师<br />

招 聘 信 息<br />

公 司 名 称 : 北 京 热 酷 科 技 有 限 公 司<br />

招 聘 人 数 : 若 干 名<br />

工 作 地 点 : 北 京<br />

薪 水 待 遇 :5k++ / month<br />

职 位 描 述 :<br />

1 、 一 年 或 以 上 PHP Web 应 用 程 序 开 发 经 验 ;<br />

2、 熟 悉 SQL 数 据 库 应 用 开 发 , 能 熟 练 使 用 MYSQL 数 据 库 , 熟 悉 HTML/CSS 及<br />

Web 标 准 ;<br />

3、 具 有 良 好 的 敬 业 精 神 和 快 速 的 学 习 能 力 , 热 爱 软 件 开 发 , 擅 于 思 考 、 肯 钻<br />

研 。<br />

任 职 资 格 :<br />

1、 精 通 php+mysql, 要 求 至 少 有 1 年 以 上 的 php 开 发 经 验 ( 必 须 );<br />

2、 熟 悉 html,css,js,div 及 网 页 设 计 模 板 技 术 ;<br />

3、 熟 悉 SQL 语 言 , 能 熟 练 使 用 MYSQL 数 据 库 ;<br />

4、 具 有 良 好 的 敬 业 精 神 和 快 速 的 学 习 能 力 , 热 爱 软 件 开 发 , 擅 于 思 考 、 肯 钻<br />

研 ;<br />

5、 有 项 目 开 发 经 验 ( 必 须 )。<br />

联 系 方 式 :<br />

公 司 介 绍<br />

联 系 人 :PH PC hina 伯 乐<br />

电 子 邮 箱 :wangzhijun@comsenz.com<br />

联 系 电 话 :13146612015<br />

QQ: 752719295<br />

北 京 热 酷 科 技 有 限 公 司 是 一 家 新 兴 的 B2C 电 子 商 务 和 开 放 平 台 应 用 软 件 开 发 公 司 ,<br />

公 司 创 新 性 地 将 传 统 电 子 商 务 与 淘 宝 、 校 内 等 开 放 平 台 应 用 有 机 结 合 , 从 而 创 造 了 一<br />

种 全 新 的 运 营 和 推 广 模 式 。<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 9/85


PHP 企 业 招 聘<br />

《PHPer》<br />

新 手 乐 园<br />

探 讨 WEB 命 令 行 模 式 的 应 用<br />

伊 君<br />

在 上 一 期 杂 志 上 看 到 于 安 老 师 的 文 章 , 颇 有 感 触 , 目 前 网 络 应 用 平 台 中 后 台 管 理<br />

功 能 非 常 强 大 , 但 是 有 的 很 复 杂 , 对 于 网 络 不 好 的 管 理 员 来 说 , 管 理 系 统 是 一 件 非 常<br />

头 疼 的 事 情 , 实 现 每 个 功 能 , 都 要 加 载 很 多 用 于 美 化 的 HTML 和 CSS 代 码 , 使 得 整<br />

个 网 线 上 交 互 的 信 息 中 大 多 数 是 无 用 信 息 。<br />

最 近 一 段 时 间 , 我 根 据 于 安 老 师 的 想 法 , 又 加 入 了 一 些 我 个 人 的 想 法 , 模 仿 Linux<br />

下 的 Bashell 的 命 令 行 习 惯 制 作 了 一 个 小 例 子 。 毕 竟 Linux 远 程 管 理 的 高 效 性 是 众 所 周<br />

之 的 , 熟 悉 Shell 命 令 的 管 理 员 对 此 程 序 会 非 常 快 的 上 手 。<br />

首 先 要 考 虑 的 问 题 :<br />

管 理 员 如 何 很 方 便 的 打 开 和 关 闭 命 令 行 窗 口 ;<br />

必 须 要 使 窗 口 可 以 拖 拽 , 以 保 证 不 会 遮 住 管 理 员 需 要 的 某 些 数 据 ;<br />

为 了 提 高 系 统 兼 容 性 , 系 统 同 样 应 用 jquery1.3 进 行 开 发 。 把 jquery 加 载 到 html 页 面<br />

中 下 面 是 command.html 的 运 行 效 果 , 管 理 员 可 以 通 过 点 击 键 盘 上 的 `( 大 键 盘 数 字 键<br />

1 左 边 的 键 ) 键 进 行 打 开 和 关 闭 对 话 框 。<br />

为 了 更 好 的 模 仿 shell 命 令 行 , 布 局 采 用 了 div 来 进 行 模 仿 , 并 通 过 一 个 简 单 的 js<br />

函 数 来 实 现 DIV 中 滚 动 条 的 自 动 跟 随 。<br />

主 要 功 能 :<br />

模 仿 bashell 的 命 令 , 实 现 web 系 统 的 相 关 操 作 ;<br />

模 仿 bashell 命 令 中 的 命 令 回 调 功 能 , 用 户 可 以 通 过 按 下 向 上 和 向 下 键 来 回 调 以 前 输 入<br />

过 的 命 令 ;<br />

加 入 清 屏 命 令 cls;<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 10/85


PHP 企 业 招 聘<br />

《PHPer》<br />

加 入 开 启 和 关 闭 面 板 的 功 能 ;<br />

实 现 面 板 的 可 拖 拽 功 能 ;<br />

下 面 是 整 个 web 命 令 行 的 结 构 :<br />

在 commandbox 中 显 示 输 入 的 命 令 和 系 统 返 回 的 结 果 。 用 户 在 command 中 输 入 命 令 ,<br />

并 敲 击 回 车 出 发 AJAX 事 件 。 用 户 在 command 中 敲 击 上 和 下 触 发 回 调 函 数 , 对 以 前<br />

输 入 过 的 命 令 进 行 回 调 。<br />

下 面 我 们 来 分 析 command.html<br />

代 码 片 段<br />

<br />

<br />

<br />

<br />

Jshell 管 理 系 统 <br />

<br />

<br />

<br />

<br />

Jshell 2009 [ 版 本 :0.1.400][C] 版 权 所 有 2009-2015 阿 呆 吧<br />

([url]www.adai8.cn[/url])<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 11/85


PHP 企 业 招 聘<br />

《PHPer》<br />

<br />

<br />

&nbsp;&gt;<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

//*********************************************************************<br />

// 触 发 接 口 , 页 面 加 载 即 触 发 函 数<br />

//**********************************************************************<br />

document.onkeydown=open_jshell;// 根 据 用 户 敲 击 键 盘 , 判 断 输 入 是 否 是 `, 并 触 发 open_jshell<br />

函 数 。<br />

var m_x;<br />

// 鼠 标 的 x 坐 标<br />

var m_y;<br />

// 鼠 标 的 y 坐 标<br />

var d_x;<br />

// 鼠 标 的 x 坐 标 和 容 器 x 坐 标 的 差 值<br />

var d_y;<br />

// 鼠 标 的 y 坐 标 和 容 器 y 坐 标 的 差 值<br />

var is_drag;<br />

// 判 断 是 否 在 左 键 按 下 的 情 况 下 移 动<br />

//***********************<br />

// 开 关 函 数 , 打 开 和 关 闭 box 窗 口<br />

//***********************<br />

function open_jshell(e){<br />

if ($.browser.msie) {<br />

var key=event.keyCode;<br />

}<br />

else{<br />

var key=e.which;<br />

}<br />

if(key==192){<br />

$("#box").slideToggle(200,function(){ $("#command").focus();});<br />

event.returnValue=false;<br />

}<br />

}<br />

//************************************************************************<br />

// 初 始 化 拖 拽 参 数 , 获 得 鼠 标 的 x,y 坐 标 , 并 负 值 is_drag 为 1<br />

// 并 且 获 取 容 器 的 x,y 轴 坐 标 , 计 算 差 值 。<br />

//************************************************************************<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 12/85


PHP 企 业 招 聘<br />

《PHPer》<br />

function initd(){<br />

is_drag=1;<br />

m_x=window.event.clientX;<br />

m_y= window.event.clientY;<br />

var offset=$("#box").offset();<br />

var b_x=offset.left;<br />

var b_y=offset.top;<br />

d_x=m_x-b_x;<br />

d_y=m_y-b_y;<br />

//$("#show").html("x is:"+d_x+" y is:"+d_y);<br />

}<br />

//************************************************************************<br />

// 拖 拽 函 数 , 根 据 用 户 的 鼠 标 点 击 并 移 动<br />

// 来 设 置 容 器 的 x,y 轴 的 距 离 , 实 现 拖 拽<br />

//************************************************************************<br />

function follow(){<br />

m_x=window.event.clientX;<br />

m_y= window.event.clientY;<br />

if(is_drag==1){<br />

$("#box").css("left",m_x-d_x);<br />

$("#box").css("top",m_y-d_y);<br />

}<br />

}<br />

//************************************************************************<br />

// 停 止 拖 拽 函 数 , 当 鼠 标 左 键 被 松 开 的 时 候 , 定 义 is_drag 为 0, 停 止 拖 拽 效 果<br />

//************************************************************************<br />

function stay(){<br />

is_drag=0;<br />

}<br />

//************************************************************************<br />

// 处 理 函 数 , 根 据 用 户 的 键 盘 输<br />

// 入 , 判 断 是 否 提 交 命 令 , 并 利<br />

// 用 ajax 进 行 异 步 处 理 和 显 示 。<br />

//************************************************************************<br />

function cprocess(e){<br />

if ($.browser.msie) {<br />

var skey=event.keyCode;<br />

}<br />

else{<br />

var skey=e.which;<br />

}<br />

if(skey==13){ // 根 据 命 令 , 利 用 ajax 提 交 给 process 页 面 进 行 处 理 。<br />

// 根 据 是 否 是 首 行 , 进 行 判 断 是 否 需 要 先 换 行 再 输 出 。<br />

if($("#res").html()==""){<br />

changeline="";<br />

}<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 13/85


PHP 企 业 招 聘<br />

《PHPer》<br />

else {<br />

changeline="";<br />

}<br />

// 如 果 提 交 命 令 , 则 视 为 回 调 命 令 指 针 还 原 为 默 认 值<br />

$("#record_seek").val("-1");<br />

var icommand=$("#command").val();<br />

// 过 滤 空 命 令 并 提 示 错 误<br />

if(icommand==""){ alert(" 命 令 行 不 能 为 空 !"); $("#command").focus(); return null;}<br />

// 执 行 清 屏 命 令<br />

if(icommand=="cls"){<br />

$("#res").html("Jshell 2009 [ 版 本 :0.1.400] [C] 版 权 所 有 2009-2015 阿 呆 吧<br />

([url=http://www.adai8.cn/]www.adai8.cn[/url])");<br />

$.post("process.php",{command:icommand});<br />

$("#command").val("");<br />

return null;<br />

}<br />

// 执 行 退 出 命 令 , 支 持 exit 和 quit 两 种 写 法<br />

if(icommand=="exit" || icommand=="quit"){<br />

$("#box").slideToggle(200,function(){ $("#command").focus();});<br />

changeline="";<br />

}<br />

$.get("process.php",{command: icommand},function(data){ $("#res").append(changeline+"<br />

>"+icommand+changeline+data);});<br />

$("#command").val("");<br />

}<br />

// 当 出 发 向 上 按 键 的 时 候 , 回 调 上 一 条 命 令 记 录 。<br />

else if(skey==38){<br />

var record_seek=$("#record_seek").val();<br />

$.post("process.php",{command: "getrecord" , seek: parseInt(record_seek)+1 },<br />

function(data){<br />

if(data!=="false"){<br />

$("#record_seek").val(parseInt($("#record_seek").val())+1);<br />

$("#command").val(data);<br />

}<br />

});<br />

}<br />

// 当 出 发 向 下 按 键 的 时 候 , 回 调 下 一 条 命 令 记 录 。<br />

else if(skey==40){<br />

var record_seek=$("#record_seek").val();<br />

if(record_seek


PHP 企 业 招 聘<br />

《PHPer》<br />

//************************************************************************<br />

// 滚 屏 函 数 , 实 现 DIV 中 滚 动 条<br />

// 实 时 跟 随 滚 动<br />

//************************************************************************<br />

function c_scrolling(){<br />

var scrollh=document.getElementById("res").scrollHeight;<br />

$("#res").scrollTop(scrollh);<br />

}<br />

<br />

大 家 来 看 看 效 果 :<br />

具 体 程 序 大 家 可 以 到 icms.adai8.cn/jshell/jshell.rar 下 载<br />

演 示 地 址 :icms.adai8.cn/jshell<br />

作 者 简 介 :<br />

伊 君 765i 社 区 负 责 人 (www.765i.com), PHPChina Training professional<br />

培 训 青 岛 地 区 学 员 , 从 2005 年 开 始 接 触 PHP,2009 年 6 月 毕 业 于 青 岛 科 技 大 学 计 算<br />

机 与 国 际 贸 易 双 专 业 。<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 15/85


扩 展 与 框 架 :<br />

《PHPer》<br />

扩 展 与 框 架<br />

PHP 的 模 板 技 术 Smarty( 一 )<br />

高 洛 峰<br />

如 果 你 正 在 设 计 一 个 交 互 式 的 网 站 , 你 一 定 会 关 注 两 个 主 要 的 问 题 , 就 是 界 面 美<br />

工 和 应 用 程 序 。 在 大 多 数 的 项 目 组 中 , 开 发 一 个 Web 程 序 都 会 出 现 这 样 的 流 程 : 计 划<br />

文 档 提 交 之 后 , 界 面 设 计 者 ( 美 工 ) 制 作 了 网 站 的 外 观 模 型 , 然 后 把 它 交 给 后 台 程 序<br />

员 。 程 序 员 使 用 PHP 实 现 程 序 逻 辑 , 同 时 使 用 外 观 模 型 做 成 基 本 架 构 , 然 后 工 程 被 返<br />

回 到 HTML 页 面 设 计 者 继 续 完 善 。 就 这 样 工 程 可 能 在 后 台 程 序 员 和 页 面 设 计 者 之 间 来<br />

来 回 回 好 几 次 。 由 于 后 台 程 序 员 不 喜 欢 干 预 任 何 有 关 HTML 标 签 , 同 时 也 不 需 要 美 工<br />

们 和 PHP 代 码 鬼 混 在 一 起 。 美 工 设 计 者 只 需 要 配 置 文 件 , 动 态 区 块 和 其 他 的 界 面 部 分 ,<br />

不 必 要 去 接 触 那 些 错 综 复 杂 的 PHP 代 码 。 因 此 , 这 时 候 有 一 个 很 好 的 模 板 支 持 就 显 得<br />

很 重 要 了 。<br />

1 什 么 是 模 板 引 擎<br />

PHP 是 一 种 HTML 内 嵌 式 的 在 服 务 器 端 执 行 的 脚 本 语 言 , 所 以 大 部 分 PHP 开 发<br />

出 来 的 Web 应 用 , 初 始 的 开 发 模 板 就 是 混 合 层 的 数 据 编 程 。 虽 然 通 过 MVC 设 计 模 式<br />

可 以 把 程 序 应 用 逻 辑 与 网 页 呈 现 逻 辑 强 制 性 分 离 , 但 也 只 是 将 应 用 程 序 的 输 入 、 处 理<br />

和 输 出 分 开 , 网 页 呈 现 逻 辑 ( 视 图 ) 还 会 有 HTML 代 码 和 PHP 程 序 强 耦 合 在 一 起 。<br />

PHP 脚 本 的 编 写 者 必 须 既 是 网 页 设 计 者 , 又 是 PHP 开 发 者 。 但 实 际 情 况 是 , 多 数 Web<br />

开 发 人 员 要 么 是 精 通 网 页 设 计 , 能 够 设 计 出 漂 亮 的 网 页 外 观 , 但 是 编 写 的 PHP 代 码 很<br />

糟 糕 ; 要 么 仅 熟 悉 PHP 编 程 , 能 够 写 出 健 壮 的 PHP 代 码 , 但 是 设 计 的 网 页 外 观 很 难<br />

看 。 具 备 两 种 才 能 的 开 发 人 员 很 少 见 。<br />

现 在 已 经 有 很 多 解 决 方 案 , 可 以 将 网 站 的 页 面 设 计 和 PHP 应 用 程 序 几 乎 完 全 分 离 。<br />

这 些 解 决 方 案 称 为 “ 模 板 引 擎 ”, 它 们 正 在 逐 步 消 除 由 于 缺 乏 层 次 分 离 而 带 来 的 难 题 。<br />

模 板 引 擎 的 目 的 , 就 是 要 达 到 上 述 提 到 的 逻 辑 分 离 的 功 能 。 它 能 让 程 序 开 发 者 专 注 于<br />

资 料 的 控 制 或 是 功 能 的 达 成 ; 而 网 页 设 计 师 则 可 专 注 于 网 页 排 版 , 让 网 页 看 起 来 更 具<br />

有 专 业 感 。 因 此 , 模 化 引 擎 很 适 合 公 司 的 Web 开 发 团 队 使 用 , 使 每 个 人 都 能 发 挥 其 专<br />

长 。<br />

模 板 引 擎 技 术 的 核 心 比 较 简 单 。 只 要 将 美 工 页 面 ( 不 包 含 任 何 的 PHP 代 码 ) 指 定<br />

为 模 板 文 件 , 并 将 这 个 模 板 文 件 中 有 活 动 的 内 容 , 如 数 据 库 输 出 、 用 户 交 互 等 部 分 ,<br />

定 义 成 使 用 特 殊 “ 定 界 符 ” 包 含 的 “ 变 量 ”, 然 后 放 在 模 板 文 件 中 相 应 的 位 置 。 当 用<br />

户 浏 览 时 , 由 PHP 脚 本 程 序 打 开 该 模 板 文 件 , 并 将 模 板 文 件 中 定 义 的 变 量 进 行 替 换 。<br />

这 样 , 模 板 中 的 特 殊 变 量 被 替 换 为 不 同 的 动 态 内 容 时 , 就 会 输 出 需 要 的 页 面 , 如 图 16-1<br />

所 示 。<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 16/85


扩 展 与 框 架 :<br />

《PHPer》<br />

图 1 一 般 的 模 版 引 擎 的 示 意 图<br />

通 过 图 1 中 展 示 的 内 容 , 我 们 可 以 打 个 比 方 。 例 如 , 玩 橡 皮 泥 时 , 用 不 同 的 模 子<br />

按 上 去 , 就 可 以 做 出 需 要 的 形 状 。 如 果 我 们 假 设 PHP 中 的 动 态 数 据 就 是 一 块 大 橡 皮 泥 ,<br />

模 板 文 件 就 像 是 一 个 模 子 , 玩 家 就 好 比 是 PHP 程 序 , 模 板 引 擎 比 作 成 使 用 模 子 的 工 具 。<br />

当 玩 家 创 建 了 一 个 使 用 模 子 的 工 具 , 并 在 工 具 中 将 模 子 安 装 上 , 然 后 用 力 将 橡 皮 泥 按<br />

下 , 这 样 就 做 出 需 要 的 形 状 来 了 。<br />

在 Web 开 发 中 分 离 应 用 程 序 的 业 务 逻 辑 和 表 现 逻 辑 , 是 我 们 使 用 模 板 引 擎 的 主 要<br />

目 的 。 这 是 因 为 有 以 下 两 个 重 要 原 因 :<br />

• 美 工 设 计 人 员 可 以 与 应 用 程 序 开 发 人 员 独 立 工 作 , 因 为 应 用 的 表 现 和 逻 辑 并 非<br />

密 不 可 分 地 纠 缠 在 一 起 。 此 外 , 因 为 大 多 数 模 板 引 擎 使 用 的 表 现 逻 辑 一 般 比 应<br />

用 程 序 所 使 用 编 程 语 言 的 语 法 更 简 单 , 所 以 , 美 工 设 计 人 员 不 需 要 为 完 成 其 工<br />

作 而 在 程 序 语 言 上 花 费 太 多 精 力 。<br />

• 可 以 使 用 同 样 的 代 码 基 于 不 同 目 标 生 成 数 据 , 例 如 生 成 打 印 的 数 据 、 生 成 Web<br />

页 面 或 生 成 电 子 数 据 表 等 。 如 果 不 使 用 模 板 引 擎 , 则 需 要 针 对 每 种 输 出 目 标 复<br />

制 并 修 改 代 码 , 这 会 带 来 非 常 严 重 的 代 码 冗 余 , 极 大 地 降 低 了 可 管 理 性 。<br />

目 前 , 可 以 在 PHP 中 应 用 的 并 且 比 较 成 熟 的 模 板 有 很 多 , 例 如 Smarty、PHPLIB、<br />

IPB 等 几 十 种 。 使 用 这 些 通 过 PHP 编 写 的 模 板 引 擎 , 可 以 让 你 的 代 码 脉 络 更 加 清 晰 ,<br />

结 构 更 加 合 理 化 。 也 可 以 让 网 站 的 维 护 和 更 新 变 得 更 容 易 , 创 造 一 个 更 加 良 好 的 开 发<br />

环 境 , 让 开 发 和 设 计 工 作 更 容 易 结 合 在 一 起 。 但 是 , 对 于 一 个 PHP 程 序 员 来 说 , 没 有<br />

哪 一 个 PHP 模 板 对 他 是 最 合 适 、 最 完 美 的 。 因 为 PHP 模 板 就 是 大 众 化 的 东 西 , 并 不<br />

是 针 对 某 个 人 开 发 的 。 如 果 能 在 对 模 板 的 特 点 、 应 用 有 清 楚 的 认 识 基 础 上 , 充 分 认 识<br />

到 模 板 的 优 势 劣 势 , 就 可 以 知 道 是 否 选 择 使 用 模 板 或 选 择 使 用 哪 个 模 板 。<br />

2 编 写 自 己 的 模 板 引 擎<br />

因 为 PHP 需 要 继 承 、 创 新 , 做 一 个 自 己 的 PHP 模 板 一 步 一 步 地 实 现 , 并 及 时 融 入<br />

最 新 的 思 想 和 理 念 , 尤 其 对 于 公 司 而 言 尤 为 实 用 。 最 重 要 的 是 , 属 于 自 己 的 PHP 模 板<br />

引 擎 永 远 不 是 固 定 不 变 的 , 可 以 根 据 项 目 的 需 要 为 其 量 身 定 制 。<br />

2.1 创 建 自 己 的 模 板 引 擎 类<br />

在 下 面 的 示 例 中 , 通 过 前 面 介 绍 的 模 板 引 擎 概 念 创 建 了 属 于 自 己 的 一 个 简 单 模 板<br />

引 擎 , 可 以 用 来 完 成 处 理 模 板 的 基 本 功 能 。 例 如 , 变 量 替 换 、 分 支 结 构 、 数 组 循 环 遍<br />

历 , 以 及 模 板 之 间 相 互 嵌 套 等 。 在 文 件 MyTpl.php 中 自 定 义 的 模 板 MyTpl 类 代 码 , 如<br />

下 所 示 :<br />

代 码 片 段<br />


扩 展 与 框 架 :<br />

《PHPer》<br />

/* 通 过 该 类 对 象 加 载 模 板 文 件 并 解 析 , 将 解 析 后 的 结 果 输 出 */<br />

class MyTpl {<br />

/* 该 类 的 构 造 方 法 , 创 建 对 象 时 初 始 化 成 员 属 性 */<br />

/* 参 数 template_dir: 指 定 存 放 模 板 文 件 的 位 置 目 录 */<br />

/* 参 数 compile_dir: 指 定 存 放 编 译 后 的 模 板 文 件 位 置 */<br />

function __construct($template_dir='./templates/', $compile_dir='./templates_c/') {<br />

$this->template_dir=rtrim($template_dir,'/').'/'; // 将 ./templates/ 目 录 作 为 模 板 存 放 目 录<br />

$this->compile_dir=rtrim($compile_dir,'/').'/'; // 初 始 化 解 析 后 的 模 板 存 放 目 录<br />

$this->tpl_vars=array();<br />

// 为 成 员 属 性 tpl_vars 赋 值 为 空 数 组<br />

}<br />

*/<br />

件<br />

/* 调 用 该 方 法 是 用 来 将 值 分 配 给 模 板 中 对 应 的 变 量 */<br />

/* 参 数 tpl_val: 需 要 一 个 字 符 串 参 数 , 要 和 模 板 中 的 变 量 名 对 应 */<br />

/* 参 数 value: 需 要 一 个 标 量 类 型 的 值 , 用 来 分 配 给 模 板 中 变 量 的 值 */<br />

function assign($tpl_var, $value = null) {<br />

if ($tpl_var != '') // 如 果 第 一 个 参 数 $tpl_var 不 是 一 个 空 字 符 串<br />

$this->tpl_vars[$tpl_var] = $value; // 将 第 二 个 参 数 提 供 的 值 添 加 到 数 组 tpl_var 中<br />

}<br />

/* 加 载 指 定 目 录 下 的 模 板 文 件 , 并 将 解 析 后 的 内 容 存 放 到 另 一 个 指 定 目 录 下 的 文 件 中<br />

/* 参 数 fileName: 提 供 模 板 文 件 的 文 件 名 */<br />

function display($fileName) {<br />

$tplFile=$this->template_dir.$fileName; // 到 指 定 的 目 录 中 寻 找 模 板 文 件<br />

if(!file_exists($tplFile)) { // 如 果 需 要 处 理 的 模 板 文 件 不 存 在<br />

return false;<br />

// 结 果 该 函 数 执 行 返 回 FALSE<br />

}<br />

// 获 取 编 译 过 的 模 板 文 件 , 该 文 件 中 的 内 容 都 是 被 替 换 过 的<br />

$comFileName=$this->compile_dir."com_".basename($tplFile).'.php';<br />

// 判 断 替 换 后 的 文 件 是 否 存 在 或 是 存 在 但 有 改 动 , 都 需 要 重 新 创 建<br />

if(!file_exists($comFileName) || filemtime($comFileName) < filemtime($tplFile)) {<br />

$repContent=$this->tpl_replace(file_get_contents($tplFile)); // 调 用 内 部 替 换 模 板 方 法<br />

$handle=fopen($comFileName, 'w+'); // 打 开 一 个 用 来 保 存 编 译 过 的 文<br />

fwrite($handle, $repContent); // 向 文 件 中 写 入 内 容<br />

fclose($handle);<br />

// 关 闭 打 开 的 文 件<br />

}<br />

include($comFileName); // 包 含 处 理 后 的 模 板 文 件 输 出 给 客 户 端<br />

}<br />

/* 该 方 法 使 用 正 则 表 达 式 将 模 板 文 件 '' 中 的 语 句 替 换 为 对 应 的 值 或 PHP 代 码 */<br />

/* 参 数 content: 提 供 从 模 板 文 件 中 读 入 的 全 部 内 容 字 符 串 */<br />

private function tpl_replace($content){<br />

$pattern=array( // 匹 配 模 板 中 各 种 标 识 符 的 正 则 表 达 式 的 模 式 数 组<br />

'//i', // 匹 配 模 板 中 变 量<br />

'/(.+?)/ies', // 匹 配 模 板 中 if 标 识 符<br />

'//ies',<br />

// 匹 配 elseif 标 识 符<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 18/85


扩 展 与 框 架 :<br />

《PHPer》<br />

'//is',<br />

// 匹 配 else 标 识 符<br />

'/(.+?)/is', // 用 来 匹 配 模 板 中 的 loop 标 识 符 , 用 来 遍 历 数 组 中 的 值<br />

'/\s*\$(\S+)\s*\}>(.+?)/is', // 用 来 匹 配 模 板 中 的 loop 标 识 符 , 用 来 遍 历 数 组 中 的 键 和 值<br />

'/


扩 展 与 框 架 :<br />

《PHPer》<br />

2.2 使 用 自 己 的 模 板 引 擎<br />

使 用 自 己 的 模 板 引 擎 比 较 容 易 , 都 是 自 己 定 义 的 语 法 格 式 。 但 要 记 住 , 所 有 流 行<br />

的 模 板 引 擎 解 决 方 案 都 遵 循 同 样 的 一 组 相 同 的 核 心 实 现 原 则 , 就 是 与 编 程 语 言 一 样 ,<br />

学 习 了 一 种 语 言 就 可 以 更 容 易 地 掌 握 其 他 语 言 。 使 用 模 板 引 擎 最 主 要 的 原 因 就 是 将 页<br />

面 设 计 者 ( 美 工 ) 和 PHP 程 序 员 的 工 作 分 开 , 所 以 模 板 引 擎 不 仅 PHP 程 序 员 需 要 使<br />

用 , 页 面 设 计 者 也 需 要 使 用 。<br />

1.PHP 程 序 员 对 模 板 引 擎 的 使 用<br />

• 在 PHP 脚 本 中 包 含 模 板 引 擎 类 所 在 的 文 件 。 如 下 所 示 :<br />

require("MyTpl_class.php"); // 包 含 模 板 引 擎 类 , 相 当 于 模 板 引 擎 安 装<br />

• 创 建 模 板 引 擎 类 的 对 象 并 对 一 些 成 员 属 性 进 行 初 始 化 赋 值 。 如 下 所 示 :<br />

$tpl=new MyTpl(); // 创 建 模 板 引 擎 类 的 对 象 , 也 可 以 根 据 参 数 对 成 员 初 始 化<br />

• 将 动 态 数 据 ( 包 括 标 量 和 数 组 类 型 的 数 据 , 例 如 从 数 据 库 的 表 中 获 得 的 数 据 数 组 )<br />

使 用 模 板 引 擎 对 象 中 的 assign() 方 法 分 配 给 模 板 文 件 , 这 个 方 法 可 以 使 用 多 次 , 将<br />

任 意 多 个 变 量 分 配 给 模 板 。 如 下 所 示 :<br />

$tpl->assign("var", "this is a value"); // 可 以 分 配 标 量 类 型 数 据 , 可 以 使 用 多 次<br />

$tpl->assign("arr", array(array(1, 2), array(“a”, “b”))); // 也 可 以 分 配 数 组 包 括 多 维 数 组<br />

• 在 PHP 脚 本 中 通 过 调 用 模 板 对 象 中 的 display() 方 法 , 并 将 模 板 文 件 名 作 为 参 数 传<br />

入 , 就 会 加 载 指 定 目 录 中 对 应 的 模 板 文 件 到 PHP 脚 本 中 。 再 通 过 模 板 引 擎 中 的 替<br />

换 方 法 对 模 板 中 自 定 义 的 语 法 进 行 解 析 , 然 后 输 出 处 理 后 的 模 板 。 如 下 所 示 :<br />

$tpl->display("test.tpl");<br />

// 参 数 “test.tpl” 为 特 定 目 录 下 的 模 板 文 件<br />

2. 页 面 设 计 者 的 使 用 说 明<br />

• 页 面 设 计 者 需 要 将 编 写 的 模 板 文 件 存 放 到 指 定 的 目 录 中 , 这 个 目 录 是 通 过 在 模 板<br />

对 象 中 使 用 $template_dir 属 性 指 定 的 , 默 认 的 设 置 是 当 前 目 录 下 的 “templates” 目 录 。<br />

另 外 , 模 板 文 件 的 命 名 以 及 后 缀 名 的 设 置 可 以 随 意 , 例 如 index.tpl、test.htm 等 。<br />

• 模 板 文 件 是 通 过 使 用 HTML、CSS 以 及 JavaScript 等 Web 前 台 语 言 编 写 的 纯 静 态<br />

页 面 。 但 可 以 在 模 板 文 件 中 使 用 “” 两 个 分 隔 符 中 间 定 义 一 个 变 量 ( 类 似<br />

PHP 中 的 变 量 格 式 ), 该 变 量 可 以 接 受 并 输 出 由 PHP 脚 本 中 分 配 过 来 的 动 态 数 据 。<br />

在 模 板 中 使 用 的 “” 两 个 分 隔 符 号 对 , 也 可 以 根 据 个 人 爱 好 在 模 板 引 擎 类<br />

中 修 改 。 如 下 所 示 :<br />

姓 名 :, 年 龄 :, 性 别 : // 模 板 中 使 用 占 位 符<br />

• 如 果 在 PHP 脚 本 中 是 将 数 组 分 配 给 模 板 , 也 可 以 在 模 板 中 进 行 遍 历 , 还 可 以 通 过<br />

嵌 套 的 方 式 遍 历 多 维 数 组 。 使 用 的 是 在 模 板 引 擎 中 定 义 的 “” 标 记 对 , 使<br />

用 的 方 式 和 PHP 中 foreach 结 构 的 语 法 格 式 相 同 。 如 下 所 示 :<br />

代 码 片 段<br />

// 遍 历 数 组 $arr 中 的 元 素 值<br />

数 组 中 的 元 素 值 <br />

// 每 次 遍 历 输 出 元 素 中 的 值<br />

// 在 模 板 中 遍 历 数 组 的 结 束 标 记<br />

$value }> // 遍 历 数 组 $arr 中 的 元 素 下 标 和 元 素 值<br />

数 组 中 元 素 的 键 <br />

// 输 出 每 次 循 环 中 元 素 的 下 标<br />

数 组 中 元 素 的 值 <br />

// 输 出 每 次 循 环 中 元 素 的 值<br />

// 在 模 板 中 遍 历 数 组 的 结 束 标 记<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 20/85


扩 展 与 框 架 :<br />

《PHPer》<br />

// 在 模 板 中 遍 历 从 PHP 中 分 配 过 来 的 多 维 数 组<br />

// 使 用 嵌 套 标 记 遍 历 二 维 数 组<br />

数 组 中 元 素 的 值 // 循 环 输 出 多 维 数 组 中 的 每 个 元 素 值<br />

// 在 模 板 中 遍 历 数 组 的 内 层 结 束 标 记<br />

// 在 模 板 中 遍 历 数 组 的 外 层 结 束 标 记<br />

• 模 板 引 擎 还 可 以 解 析 在 模 板 文 件 中 使 用 特 殊 标 记 编 写 的 分 支 结 构 , 语 法 风 格 也 是 和 PHP 的 分<br />

支 结 构 类 似 。 是 通 过 在 模 板 文 件 中 使 用 “” 标 记 对 实 现 选 择 结 构 , 也 可 以 实 现 多 路 分<br />

支 和 嵌 套 分 支 的 选 择 结 构 。 如 下 所 示 :<br />

代 码 片 段<br />

<br />

// 在 模 板 中 判 断 变 量 $var 的 值 是 否 为 red<br />

这 是 “ 红 色 ” 的 字 // 如 果 条 件 成 立 则 输 出 红 色 的 字<br />

<br />

// 在 模 板 中 判 断 $var 的 值 是 否 为 green<br />

这 是 “ 绿 色 ” 的 字 // 如 果 条 件 成 立 则 输 出 绿 色 的 字<br />

// 如 果 条 件 都 不 成 立<br />

// 嵌 套 形 式 判 断 变 量 $size 是 否 等 于 7<br />

这 是 “7 号 ” 的 字 // 如 果 条 件 成 功 则 输 出 7 号 大 小 字 体<br />

// 内 层 嵌 套 的 条 件 标 记 结 束<br />

<br />

// 外 层 的 条 件 标 记 结 束<br />

• 在 自 定 义 的 模 板 引 擎 中 , 也 添 加 了 在 模 板 文 件 中 包 含 其 他 模 板 文 件 的 功 能 。 可 以 使 用<br />

“” 标 记 将 子 模 板 包 含 到 当 前 模 板 中 , 还 支 持 在 子 模 板 中 再 次 包<br />

括 另 外 的 子 模 板 。 如 下 所 示 :<br />

代 码 片 段<br />

// 在 当 前 的 模 板 文 件 中 包 含 其 他 模 板 文 件 , 也 可 以 使 用 单 引 号 包 含<br />

2.3 自 定 义 模 板 的 使 用 示 例 分 析<br />

这 节 内 容 主 要 是 演 示 自 定 义 模 板 的 使 用 示 例 , 通 过 在 程 序 中 加 载 模 板 引 擎 可 以 将<br />

PHP 与 前 台 HTML 等 语 言 的 代 码 设 计 分 开 。 首 先 在 PHP 程 序 中 获 取 数 据 库 中 存 储 的<br />

数 据 , 再 通 过 加 载 模 板 引 擎 将 数 据 分 配 出 去 , 然 后 将 模 板 文 件 再 通 过 模 板 引 擎 加 载 并<br />

处 理 后 输 出 。 所 以 PHP 程 序 只 是 创 建 动 态 数 据 , 加 载 模 板 引 擎 并 将 动 态 数 据 分 配 给 模<br />

板 , 完 成 了 PHP 程 序 的 工 作 。 而 模 板 的 设 计 也 只 需 要 页 面 设 计 人 员 独 立 完 成 , 使 用<br />

HTML、CSS 及 JavaScript 等 前 台 页 面 设 计 语 言 编 写 。 另 外 , 在 模 板 文 件 中 还 需 要 使<br />

用 模 板 引 擎 可 以 解 析 的 标 记 , 将 PHP 中 分 配 过 来 的 动 态 数 据 在 模 板 中 引 用 。<br />

1. 数 据 库 的 设 计<br />

假 设 数 据 库 服 务 器 在 “localhost” 主 机 上 , 连 接 的 用 户 名 和 密 码 分 别 为 “mysql_user”<br />

和 “mysql_pwd”, 在 该 服 务 器 上 创 建 一 个 名 为 “mydb” 的 数 据 库 , 并 在 该 数 据 库 中 创 建<br />

一 个 名 为 “User” 的 用 户 表 。 创 建 该 表 的 SQL 查 询 语 句 如 下 所 示 :<br />

CREATE TABLE User (<br />

// 创 建 一 名 为 User 的 用 户 表<br />

id SMALLINT(3) NOT NULL AUTO_INCREMENT, //User 表 中 自 动 增 加 的 记 录 ID<br />

name VARCHAR(10) NOT NULL DEFAULT '',<br />

// 存 储 用 户 名 的 字 段<br />

sex VARCHAR(4) NOT NULL DEFAULT '',<br />

// 存 储 用 户 性 别 的 字 段<br />

age SMALLINT(2) NOT NULL DEFAULT '0',<br />

// 存 储 用 户 年 龄 的 字 段<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 21/85


扩 展 与 框 架 :<br />

《PHPer》<br />

email VARCHAR(20) NOT NULL DEFAULT '', // 存 储 用 户 电 子 邮 件 的 字 段<br />

PRIMARY KEY (id)<br />

// 将 用 户 ID 设 置 为 主 键<br />

) ;<br />

用 户 表 User 创 建 完 成 以 后 , 接 着 可 以 向 该 表 中 插 入 一 些 数 据 作 为 示 例 演 示 使 用 ,<br />

SQL 查 询 语 句 如 下 所 示 :<br />

INSERT INTO User(name, sex, age, email) VALUES // 向 表 User 中 插 入 4 条 记 录<br />

(" 高 某 某 ", " 男 ", 27, "gao@lampbrother.net"), // 第 一 条 记 录<br />

(" 洛 某 某 ", " 女 ", 22, "luo@lampbrother.net"), // 第 二 条 记 录<br />

(" 峰 某 某 ", " 男 ", 30, "feng@lampbrother.net"), // 第 三 条 记 录<br />

(" 书 某 某 ", " 女 ", 24, "shu@lampbrother.net"); // 第 四 条 记 录<br />

2. 模 板 的 设 计<br />

模 板 的 设 计 不 要 出 现 任 何 的 PHP 代 码 , 可 以 由 纯 美 工 的 人 员 来 完 成 。 在 自 定 义 的<br />

模 板 引 擎 中 , 规 定 了 要 到 指 定 的 目 录 中 去 寻 找 模 板 文 件 , 这 个 特 定 的 目 录 可 以 在 创 建<br />

模 板 引 擎 对 象 时 指 定 , 也 可 以 使 用 默 认 的 目 录 设 置 , 默 认 可 以 将 模 板 文 件 存 放 在 当 前<br />

目 录 中 的 “templates” 目 录 下 。 本 例 共 需 要 三 个 模 板 文 件 main.tpl、header.tpl 和 footer.tpl,<br />

都 存 放 在 这 个 默 认 的 目 录 设 置 中 。 这 三 个 模 板 文 件 的 代 码 如 下 所 示 :<br />

主 模 板 文 件 main.tpl<br />

代 码 片 段<br />

<br />

<br />

<br />

<br />

编 号 姓 名 性 别 年 龄 电 子 邮 件 <br />

<br />

<br />

<br />

$colValue }><br />

<br />

<br />

<br />

<br />

<br />

<br />

未 知 <br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

共 查 找 到 条 记 录 <br />

<br />

模 板 的 头 部 文 件 header.tpl<br />

代 码 片 段<br />

<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 22/85


扩 展 与 框 架 :<br />

《PHPer》<br />

<br />

<br />

<br />

<br />

代 码 片 段<br />

<br />

模 板 的 尾 部 文 件 footer.tpl<br />

############### 作 者 : ############## <br />

<br />

文 件 main.tpl 是 主 模 板 文 件 , 在 该 文 件 中 使 用 和 两 个 标 记 分 别 在 该 文 件 的 顶 部 和 底 部 , 将 独 立 的 头 部 和 尾 部 模 板 文 件 包 含<br />

到 这 个 主 模 板 文 件 中 。 并 在 该 文 件 中 使 用 标 记 获 取 从 PHP 中 动 态 分<br />

配 过 来 的 表 名 , 以 及 使 用 双 层 标 记 嵌 套 , 遍 历 从 PHP 中 动 态 分 配 过 来 的 在<br />

数 据 库 中 获 取 到 的 二 维 数 组 $Users, 还 在 标 记 中 使 用 条 件 选 择 标 记 <br />

组 合 , 将 数 据 中 性 别 为 “ 男 ” 的 表 格 背 景 设 置 为 红 色 和 一 些 其 他 判 断 。 又 在 main.tpl 模<br />

板 文 件 中 , 使 用 标 记 输 出 从 PHP 程 序 中 动 态 分 配 过 来 的 数 据 记 录 的 个<br />

数 。 被 包 含 进 来 的 头 部 模 板 文 件 header.tpl 和 尾 部 模 板 文 件 footer.tpl 也 同 样 可 以 获 取<br />

从 PHP 中 动 态 分 配 给 模 板 的 数 据 。<br />

3.PHP 程 序 设 计<br />

通 过 模 板 引 擎 的 使 用 ,PHP 程 序 员 在 编 写 代 码 时 , 只 需 要 PHP 一 种 语 言 就 可 以 了 ,<br />

不 用 再 去 使 用 HTML、CSS 以 及 JavaScript 前 页 面 设 计 语 言 完 成 美 工 的 工 作 了 。 下 面<br />

是 一 个 文 件 名 为 index.php 的 PHP 脚 本 文 件 , 和 模 板 引 擎 类 所 在 的 文 件<br />

MyTpl_class.php 在 同 一 个 目 录 下 。 代 码 如 下 所 示 :<br />

代 码 片 段<br />


扩 展 与 框 架 :<br />

《PHPer》<br />

$tpl->assign("author", " 高 洛 峰 ");<br />

$tpl->assign("users", $users);<br />

$tpl->assign("rowNum", $rowNum);<br />

$tpl->display("main.tpl");<br />

?><br />

// 分 配 作 者 变 量 给 尾 部 模 板 footer.tpl<br />

// 分 配 存 有 表 User 的 二 维 数 组 给 主 模 板<br />

// 分 配 所 取 的 数 据 行 数 变 量 给 主 模 板<br />

// 包 括 替 换 模 板 中 的 变 量 输 出 模 板 页 面<br />

在 上 面 的 PHP 脚 本 文 件 中 , 通 过 mysqli 对 象 连 接 MySQL 服 务 器 , 并 获 取 用 户 表<br />

User 中 的 全 部 记 录 , 并 以 PHP 的 二 维 数 组 变 量 形 式 保 存 在 变 量 $users 中 。 接 着 使 用 包<br />

含 进 来 的 当 前 目 录 下 的 “MyTpl_ clss.php” 文 件 , 创 建 并 初 始 化 模 板 引 擎 类 的 对 象 $tpl。<br />

再 通 过 该 对 象 中 的 assign() 方 法 向 模 板 分 配 一 些 数 据 , 然 后 使 用 该 对 象 中 的 display()<br />

方 法 载 入 模 板 文 件 main.tpl。 并 将 模 板 中 标 记 的 特 殊 变 量 替 换 为 从 PHP 中 分 配 的 动 态<br />

数 据 , 处 理 完 毕 以 后 输 出 模 板 页 面 。 页 面 的 输 出 结 果 如 图 2 所 示 。<br />

图 2 自 定 义 模 板 的 演 示 示 例<br />

限 于 各 种 不 同 的 条 件 限 制 , 比 如 时 间 、 经 验 , 做 一 个 自 己 的 PHP 模 板 引 擎 是 非 常<br />

困 难 的 。 其 实 , 你 需 要 的 并 不 是 重 新 构 造 一 个 PHP 模 板 , 而 是 选 择 一 个 最 贴 近 自 己 的<br />

PHP 模 板 加 以 改 造 。<br />

3 选 择 Smarty 模 板 引 擎<br />

一 般 的 模 板 引 擎 ( 如 PHPLib) 都 是 在 建 立 模 板 对 象 时 取 得 要 解 析 的 模 板 , 然 后 把<br />

变 量 套 入 后 , 透 过 parse() 这 个 方 法 来 解 析 模 板 , 最 后 再 将 网 页 输 出 。 对 Smarty 的 使<br />

用 者 来 说 , 程 序 里 也 不 需 要 做 任 何 解 析 的 动 作 了 , 这 些 Smarty 自 动 会 帮 我 们 做 。 而<br />

且 已 经 编 译 过 的 网 页 , 如 果 模 板 没 有 变 动 的 话 ,Smarty 就 自 动 跳 过 编 译 的 动 作 , 直 接<br />

执 行 编 译 过 的 网 页 , 以 节 省 编 译 的 时 间 。smarty 模 板 引 擎 运 作 示 意 图 如 3 所 示 。<br />

模 板 文 件<br />

( 美 工 页 面 )<br />

解 析 模 板 嵌<br />

读 取 模 板 文 件<br />

入 变 量 内 容<br />

第 一 次 或 模 板<br />

改 变 时 被 执 行<br />

PHP 程 序<br />

建 立 模 板 引 擎<br />

Smarty<br />

模 板 引 擎<br />

输 出 网 页 内 容<br />

显 示 结 果<br />

编 译 执 行<br />

已 编 译 过 的 内 嵌<br />

PHP 的 HTM L 网 页<br />

如 果 已 经 有 编 译 过 的<br />

内 容 , 而 且 模 板 没 有<br />

任 何 改 变 , 就 直 接 执<br />

行 编 译 过 的 内 容<br />

图 3 smarty 模 版 引 擎 运 作 示 意 图<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 24/85


扩 展 与 框 架 :<br />

《PHPer》<br />

对 PHP 来 说 , 有 很 多 模 板 引 擎 可 供 选 择 , 但 Smarty 是 一 个 使 用 PHP 编 写 出 来 的 ,<br />

是 目 前 业 界 最 著 名 、 功 能 最 强 大 的 一 种 PHP 模 板 引 擎 。Smarty 像 PHP 一 样 拥 有 丰 富<br />

的 函 数 库 , 从 统 计 字 数 到 自 动 缩 进 、 文 字 环 绕 以 及 正 则 表 达 式 都 可 以 直 接 使 用 , 如 果<br />

觉 得 不 够 ,SMARTY 还 有 很 强 的 扩 展 能 力 , 可 以 通 过 插 件 的 形 式 进 行 扩 充 。 另 外 ,<br />

Smarty 也 是 一 种 自 由 软 件 , 用 户 可 以 自 由 使 用 、 修 改 , 以 及 重 新 分 发 该 软 件 。Smarty<br />

的 优 点 概 括 如 下 。<br />

• 速 度 : 相 对 于 其 他 的 模 板 引 擎 技 术 而 言 , 采 用 Smarty 编 写 的 程 序 可 以 获 得 最 大<br />

速 度 的 提 高 。<br />

• 编 译 型 : 采 用 Smarty 编 写 的 程 序 在 运 行 时 要 编 译 成 一 个 非 模 板 技 术 的 PHP 文 件 ,<br />

这 个 文 件 采 用 了 PHP 与 HTML 混 合 的 方 式 , 在 下 一 次 访 问 模 板 时 将 Web 请 求<br />

直 接 转 换 到 这 个 文 件 中 , 而 不 再 进 行 模 板 重 新 编 译 ( 在 源 程 序 没 有 改 动 的 情 况<br />

下 ), 使 用 后 续 的 调 用 速 度 更 快 。<br />

• 缓 存 技 术 :Smarty 提 供 了 一 种 可 选 择 使 用 的 缓 存 技 术 , 它 可 以 将 用 户 最 终 看 到<br />

的 HTML 文 件 缓 存 成 一 个 静 态 的 HTML 页 。 当 用 户 开 启 Smarty 缓 存 时 , 并 在<br />

设 定 的 时 间 内 , 将 用 户 的 Web 请 求 直 接 转 换 到 这 个 静 态 的 HTML 文 件 中 来 , 这<br />

相 当 于 调 用 一 个 静 态 的 HTML 文 件 。<br />

• 插 件 技 术 :Smarty 模 板 引 擎 是 采 用 PHP 的 面 向 对 象 技 术 实 现 , 不 仅 可 以 在 原 代<br />

码 中 修 改 , 还 可 以 自 定 义 一 些 功 能 插 件 ( 就 是 一 些 按 规 则 自 定 义 的 函 数 )。<br />

• 强 大 的 表 现 逻 辑 : 在 Smarty 模 板 中 能 够 通 过 条 件 判 断 以 及 迭 代 地 处 理 数 据 , 它<br />

实 际 上 就 是 一 种 程 序 设 计 语 言 , 但 语 法 简 单 , 设 计 人 员 在 不 需 要 预 备 的 编 程 知<br />

识 前 提 下 就 可 以 很 快 学 会 。<br />

当 然 , 也 有 不 适 合 使 用 Smarty 的 地 方 。 例 如 , 需 要 实 时 更 新 的 内 容 , 需 要 经 常 重<br />

新 编 译 模 板 , 所 以 这 类 型 的 程 序 使 用 Smarty 会 使 模 板 处 理 速 度 变 慢 。 另 外 , 在 小 项 目<br />

中 也 不 适 合 使 用 Smarty 模 板 , 小 项 目 因 为 项 目 简 单 而 美 工 与 程 序 员 兼 于 一 人 的 项 目 ,<br />

使 用 Smarty 会 在 一 定 程 度 上 丧 失 PHP 开 发 迅 速 的 优 点 。<br />

4 安 装 Smarty 及 初 始 化 配 置<br />

Smarty 的 安 装 比 较 容 易 , 因 为 它 是 采 用 PHP 的 面 向 对 象 思 想 编 写 的 软 件 , 只 要 在<br />

我 们 的 PHP 脚 本 中 加 载 Smarty 类 , 并 创 建 一 个 Smarty 对 象 , 就 可 以 使 用 Smarty 模<br />

板 引 擎 了 。 像 Smarty 这 类 使 用 PHP 语 言 编 写 的 软 件 , 并 在 PHP 的 项 目 中 应 用 时 , 通<br />

常 都 有 两 种 安 装 方 式 :<br />

• 依 照 官 方 的 方 式 安 装 , 可 以 只 在 Web 服 务 器 的 主 机 上 安 装 一 次 , 然 后 提 供 给 该<br />

主 机 下 所 有 设 计 者 开 发 不 同 程 序 时 直 接 引 用 , 而 不 会 重 复 安 装 太 多 的 Smarty 复<br />

本 。 通 常 这 种 安 装 方 法 是 将 Smarty 类 库 放 置 到 Web 文 档 根 目 录 之 外 的 某 个 目 录<br />

中 , 再 在 PHP 的 配 置 文 件 中 将 这 个 位 置 包 含 在 include_path 指 令 中 。 但 如 果 某<br />

个 PHP 项 目 在 多 个 Web 服 务 器 之 间 迁 移 时 , 每 个 Web 服 务 器 都 必 须 有 同 样 的<br />

Smarty 类 库 配 置 。<br />

• 使 用 Smarty 和 使 用 其 他 类 库 一 样 , 如 果 在 每 个 PHP 项 目 中 都 使 用 独 立 的 Smarty<br />

类 库 , 只 需 要 将 Smarty 软 件 放 置 到 项 目 中 的 某 个 目 录 中 , 再 在 程 序 中 包 含 这 个<br />

目 录 中 的 Smarty 类 文 件 , 就 可 以 使 用 Smarty 模 板 引 擎 了 。 这 样 ,PHP 在 多 个<br />

Web 服 务 器 之 间 移 植 时 都 会 带 着 Smarty 库 , 就 不 需 要 再 改 变 Web 服 务 器 的 配<br />

置 了 。<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 25/85


扩 展 与 框 架 :<br />

《PHPer》<br />

4.1 安 装 Smarty<br />

通 过 前 面 的 介 绍 , 选 用 第 二 种 安 装 方 式 比 较 适 合 我 们 , 就 是 在 自 己 的 PHP 项 目<br />

中 包 含 Smarty 类 库 。 安 装 步 骤 如 下 :<br />

(1) 需 要 到 Smarty 官 方 网 站 http://www.smarty.net/download.php 下 载 最 新 的 稳 定<br />

版 本 , 所 有 版 本 的 Smarty 类 库 都 可 以 在 Unix 和 Windows 服 务 器 上 使 用 。 例 如 , 下 载<br />

的 软 件 包 为 Smarty-2.6.18.tar.gz。<br />

(2) 然 后 解 压 压 缩 包 , 解 开 后 会 看 到 很 多 文 件 , 其 中 有 个 名 称 为 libs 的 文 件 夹 ,<br />

就 是 存 有 Smarty 类 库 的 文 件 夹 。 安 装 Smarty 只 需 要 这 一 个 文 件 夹 , 其 他 的 文 件 都 没<br />

有 必 要 使 用 。<br />

(3) 在 libs 中 应 该 会 有 三 个 class.php 文 件 、1 个 debug.tpl、1 个 plugin 文 件 夹 和<br />

1 个 core 文 件 夹 , 直 接 将 libs 文 件 夹 复 制 到 您 的 程 序 主 文 件 夹 下 。<br />

(4) 在 执 行 的 PHP 脚 本 中 , 通 过 require() 语 句 将 libs 目 录 中 的 Smarty.class.php<br />

类 文 件 加 载 进 来 ,Smarty 类 库 就 可 以 使 用 了 。<br />

上 面 提 供 的 安 装 方 式 适 合 给 程 序 被 带 过 来 移 过 去 的 开 发 者 使 用 , 这 样 就 不 用 再 考 虑 主<br />

机 有 没 有 安 装 Smarty 了 。<br />

4.2 初 始 化 Smarty 类 库 的 默 认 设 置<br />

通 过 前 面 对 Smarty 类 库 安 装 的 介 绍 , 调 用 require() 方 法 将 Smarty.class.php 文 件 包<br />

含 到 执 行 脚 本 中 , 并 创 建 Smarty 类 的 对 象 就 可 以 使 用 了 。 但 如 果 需 要 改 变 Smarty 类<br />

库 中 一 些 成 员 的 默 认 值 , 不 仅 可 以 直 接 在 Smarty 源 文 件 中 修 改 , 也 可 以 在 创 建 Smarty<br />

对 象 以 后 重 新 为 Smarty 对 象 设 置 新 值 。Smarty 类 中 一 些 需 要 注 意 的 成 员 属 性 如 表 1<br />

所 示 。<br />

表 1 Smarty 类 中 需 要 关 注 的 成 员 属 性<br />

成 员 属 性 名 描 述<br />

$template_dir<br />

$compile_dir<br />

$config_dir<br />

网 站 中 的 所 有 模 板 文 件 都 需 要 放 置 在 该 属 性 所 指 定 的 目 录 或 子 目 录 中 。 当 包 含 模 板 文 件 时 , 如 果 不 提 供 一 个 源 地<br />

址 , 那 么 将 会 到 这 个 模 板 目 录 中 寻 找 。 默 认 情 况 下 , 目 录 是 :“./templates”, 也 就 是 说 他 将 会 在 和 PHP 执 行 脚 本 相 同<br />

的 目 录 下 寻 找 模 板 目 录 。 建 议 将 该 属 性 指 定 的 目 录 放 在 Web 服 务 器 文 档 根 之 外 的 位 置<br />

Smarty 编 译 过 的 所 有 模 板 文 件 都 会 被 存 储 到 这 个 属 性 所 指 定 的 目 录 中 。 默 认 目 录 是 :“./templates_c”, 也 就 是 说 它<br />

将 会 在 和 PHP 执 行 脚 本 相 同 的 目 录 下 寻 找 编 译 目 录 。 除 了 创 建 此 目 录 外 , 在 Linux 服 务 器 上 还 需 要 修 改 权 限 , 使<br />

Web 服 务 器 的 用 户 能 够 对 这 个 目 录 有 写 的 权 限 。 建 议 将 该 属 性 指 定 的 目 录 放 在 Web 服 务 器 文 档 根 之 外 的 位 置<br />

该 变 量 定 义 用 于 存 放 模 板 特 殊 配 置 文 件 的 目 录 , 默 认 情 况 下 , 目 录 是 :“./configs”, 也 就 是 说 它 将 会 在 和 PHP 执<br />

行 脚 本 相 同 的 目 录 下 寻 找 配 置 目 录 。 建 议 将 该 属 性 指 定 的 目 录 放 在 Web 服 务 器 文 档 根 之 外 的 位 置<br />

$left_delimiter 用 于 模 板 语 言 中 的 左 结 束 符 变 量 , 默 认 是 "{"。 但 这 个 默 认 设 置 会 和 模 板 中 使 用 的 JavaScript 代 码 结 构 发 生 冲 突 ,<br />

通 常 需 要 修 改 其 默 认 行 为 。 例 如 :""<br />

告 诉 Smarty 是 否 缓 存 模 板 的 输 出 。 默 认 情 况 下 , 它 设 为 0 或 无 效 。 你 也 可 以 为 同 一 个 模 板 设 有 多 个 缓 存 , 当 值 为<br />

1 或 2 时 启 动 缓 存 。1 告 诉 Smarty 使 用 当 前 的 $cache_lifetime 变 量 判 断 缓 存 是 否 过 期 。2 告 诉 Smarty 使 用 生 成 缓 存 时<br />

的 cache_lifetime 值 。 用 这 种 方 式 你 正 好 可 以 在 获 取 模 板 之 前 设 置 缓 存 生 存 时 间 , 以 便 较 精 确 地 控 制 缓 存 何 时 失 效 。<br />

建 议 在 项 目 开 发 过 程 中 关 闭 缓 存 , 将 值 设 计 为 0<br />

在 启 动 缓 存 的 特 性 情 况 下 , 这 个 属 性 所 指 定 的 目 录 中 放 置 Smarty 缓 存 的 所 有 模 板 。 默 认 情 况 下 , 它 是 :"./cache",<br />

也 就 是 说 你 可 以 在 和 php 执 行 脚 本 相 同 目 录 下 寻 找 缓 存 目 录 。 你 也 可 以 用 你 自 己 的 自 定 义 缓 存 处 理 函 数 来 控 制 缓 存<br />

文 件 , 它 将 会 忽 略 这 项 设 置 。 除 了 创 建 此 目 录 外 , 在 Linux 服 务 器 上 还 需 要 修 改 权 限 , 使 Web 服 务 器 的 用 户 能 够 对<br />

这 个 目 录 有 写 的 权 限 。 建 议 将 该 属 性 指 定 的 目 录 放 在 Web 服 务 器 文 档 根 之 外 的 位 置<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 26/85


扩 展 与 框 架 :<br />

《PHPer》<br />

$cache_lifetime<br />

该 变 量 定 义 模 板 缓 存 有 效 时 间 段 的 长 度 ( 单 位 秒 )。 一 旦 这 个 时 间 失 效 , 则 缓 存 将 会 重 新 生 成 。 如 果 要 想 实 现 所 有<br />

效 果 ,$caching 必 须 因 $cache_lifetime 需 要 而 设 为 "true"。 值 为 −1 时 , 将 强 迫 缓 存 永 不 过 期 。0 值 将 导 致 缓 存 总 是 重<br />

新 生 成 ( 仅 有 利 于 测 试 , 一 个 更 有 效 的 使 缓 存 无 效 的 方 法 是 设 置 $caching = 0)<br />

如 果 我 们 不 修 改 Smarty 类 中 的 默 认 行 为 , 也 需 要 创 建 表 16-1 中 介 绍 的 几 个 Smarty<br />

路 径 , 因 为 Smarty 将 会 在 和 php 执 行 脚 本 相 同 的 目 录 下 寻 找 这 些 配 置 目 录 。 但 为 了 系<br />

统 安 全 , 通 常 建 议 将 这 些 目 录 放 在 Web 服 务 器 文 档 根 目 录 之 外 的 位 置 上 , 这 样 就 只 有<br />

通 过 Smarty 引 擎 使 用 这 些 目 录 中 的 文 件 了 , 而 不 能 再 通 过 Web 服 务 器 在 远 程 访 问 它<br />

们 。 为 了 避 免 重 复 地 配 置 路 径 , 可 以 在 一 个 文 件 里 配 置 这 些 变 量 , 并 在 每 个 需 要 使 用<br />

Smarty 的 脚 本 中 包 含 这 个 文 件 即 可 。 将 以 下 这 个 文 件 命 名 为 main.inc.php, 并 放 置 到<br />

主 文 件 夹 下 , 和 Smarty 类 库 所 在 的 文 件 夹 libs 在 同 一 个 目 录 中 。 如 下 所 示 :<br />

初 始 化 Smarty 成 员 属 性 的 公 用 文 件 main.inc.php<br />

代 码 片 段<br />

<br />

在 Smarty 类 中 并 没 有 对 成 员 属 性 使 用 private 封 装 , 所 以 创 建 Smarty 类 的 对 象 以<br />

后 就 可 以 直 接 为 成 员 属 性 赋 值 。 按 照 上 面 文 件 方 式 设 定 的 用 意 在 于 , 程 序 如 果 要 移 植<br />

到 其 他 地 方 , 只 要 改 变 SITE_ROOT 值 就 可 以 了 。 如 果 以 Windows 系 统 上 安 装 Appserv<br />

为 例 ,PHP 项 目 的 主 文 件 夹 是 C:\Appserv\ww\project\, 在 上 面 介 绍 的 main.inc.tpl 文 件<br />

中 将 SITE_ROOT 的 值 也 设 置 为 C:\Appserv\ww\project 目 录 。 目 录 结 构 如 图 4 所 示 。<br />

图 4 使 用 Smarty 的 项 目 目 录 结 构<br />

通 过 图 4 中 提 供 的 一 个 项 目 的 目 录 结 构 , 可 以 清 晰 地 了 解 在 使 用 模 板 时 各 种 模 块<br />

存 放 的 位 置 。 我 们 一 定 要 按 这 种 规 定 的 目 录 结 构 去 存 放 数 据 , 例 如 所 有 的 模 板 文 件 都<br />

存 放 在 templates 目 录 中 , 在 需 要 使 用 模 板 文 件 时 , 模 板 引 擎 会 自 动 到 该 目 录 中 去 寻 找<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 27/85


扩 展 与 框 架 :<br />

《PHPer》<br />

对 应 的 模 板 文 件 ; 如 果 在 模 板 文 件 中 需 要 加 载 特 殊 的 配 置 文 件 , 也 会 到 configs 目 录<br />

中 去 寻 找 ; 如 果 模 板 文 件 有 改 动 或 是 第 一 次 使 用 , 会 通 过 模 板 引 擎 将 编 译 过 的 模 板 文<br />

件 自 动 写 入 到 templates_c 目 录 中 建 立 的 一 个 文 件 中 ; 如 果 在 启 动 缓 存 的 特 性 情 况 下 ,<br />

Smarty 缓 存 的 所 有 模 板 还 会 被 自 动 存 储 到 cache 目 录 中 的 一 个 文 件 或 多 个 文 件 中 。 需<br />

要 Smarty 引 擎 去 主 动 修 改 的 cache 和 templates_c 两 个 目 录 , 一 定 要 让 PHP 脚 本 的 执<br />

行 用 户 有 写 的 权 限 。<br />

4.3 第 一 个 Smarty 的 简 单 示 例<br />

通 过 前 面 的 介 绍 , 如 果 了 解 了 Smarty 并 学 会 了 安 装 , 就 可 以 通 过 一 个 简 单 的 示 例<br />

测 试 一 下 , 使 用 Smarty 模 板 编 写 的 大 型 项 目 也 会 有 同 样 的 目 录 结 构 。 按 照 上 一 节 的<br />

介 绍 我 们 需 要 创 建 一 个 项 目 的 主 目 录 Project, 并 将 存 放 Smarty 类 库 的 文 件 夹 libs 复<br />

制 这 个 目 录 中 , 还 需 要 在 该 目 录 中 分 别 创 建 Smarty 引 擎 所 需 要 的 各 个 目 录 。 如 果 需<br />

要 修 改 一 些 Smarty 类 中 常 用 成 员 属 性 的 默 认 行 为 , 可 以 在 该 目 录 中 编 写 一 个 类 似 上<br />

一 节 中 介 绍 的 main.inc.php 文 件 。<br />

在 这 个 例 子 中 , 唯 一 的 动 作 就 是 在 PHP 程 序 中 替 代 模 板 文 件 中 特 定 的 Smarty 变<br />

量 。 首 先 在 项 目 主 目 录 下 的 templates 目 录 中 创 建 一 个 模 板 文 件 , 这 个 模 板 文 件 的 扩 展<br />

名 叫 什 么 都 无 所 谓 。 注 意 , 在 模 板 中 声 明 了 $title 和 $conten 两 个 Smarty 变 量 , 都 放 在<br />

大 括 号 “{}” 中 , 大 括 号 是 Smarty 的 默 认 定 界 符 , 但 为 了 在 模 板 中 嵌 入 CSS 及 JavaScript<br />

的 关 系 , 最 好 是 将 它 换 掉 , 例 如 将 默 认 定 界 符 修 改 为 “” 的 形 式 。 这 些 定<br />

界 符 只 能 在 模 板 文 件 中 使 用 , 并 告 诉 Smarty 要 对 定 界 符 所 包 围 的 内 容 完 成 某 些 操 作 。<br />

在 templates 目 录 中 创 建 一 个 名 为 “test.tpl” 的 模 板 文 件 , 代 码 如 下 所 示 :<br />

简 单 的 Smarty 设 计 模 板 (templates/test.tpl)<br />

代 码 片 段<br />

<br />

<br />

<br />

{ $title } <br />

<br />

<br />

{ $content }<br />

<br />

<br />

还 要 注 意 ,Smarty 这 个 模 板 一 定 要 位 于 templates 目 录 或 它 的 子 目 录 内 , 除 非 通 过<br />

Smarty 类 中 的 $template_dir 属 性 修 改 了 模 板 目 录 。 另 外 , 模 板 文 件 只 是 一 个 表 现 层 界<br />

面 , 还 需 要 PHP 应 用 程 序 逻 辑 , 将 适 当 的 变 量 值 传 入 Smarty 模 板 。 直 接 在 项 目 的 主<br />

目 录 中 创 建 一 个 名 为 index.php 的 PHP 脚 本 文 件 , 作 为 templates 目 录 中 test.tpl 模 板 的<br />

应 用 程 序 逻 辑 。 代 码 如 下 所 示 :<br />

在 项 目 的 主 目 录 中 创 建 index.php<br />

代 码 片 段<br />


扩 展 与 框 架 :<br />

《PHPer》<br />

$smarty->assign("content", " 测 试 用 的 网 页 内 容 "); // 也 属 于 第 四 步 , 分 配 其 他 变 量 置 入 模 板<br />

里<br />

// 在 第 四 步 中 可 以 向 模 板 中 置 入 任 何 类 型 的 变 量<br />

$smarty->display("test.tpl");<br />

// 利 用 Smarty 的 display() 方 法 将 网 页 输 出<br />

?><br />

这 个 示 例 展 示 了 Smarty 能 够 完 全 分 离 Web 应 用 程 序 逻 辑 层 和 表 现 层 。 用 户 通 过<br />

浏 览 器 直 接 访 问 项 目 目 录 中 的 index.php 文 件 , 就 会 将 模 板 文 件 test.tpl 中 的 变 量 替 换<br />

后 显 示 出 来 , 如 图 5 所 示 。<br />

图 5 使 用 Smarty 的 简 单 示 例 输 出 结 果<br />

看 到 输 出 结 果 以 后 , 再 到 项 目 主 目 录 下 的 templates_c 目 录 底 下 , 我 们 会 看 到 一 个<br />

文 件 名 比 较 奇 怪 的 文 件 ( 例 如 :%%6D^6D7^6D7C5625%%test.tpl.php)。 打 开 该 文 件<br />

后 的 代 码 如 下 所 示 :<br />

Smarty 编 译 过 的 文 件 (templates_c/%%6D^6D7^6D7C5625%%test.tpl.php)<br />

代 码 片 段<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

<br />

这 就 是 Smarty 编 译 过 的 文 件 , 是 在 第 一 次 使 用 模 板 文 件 test.tpl 时 由 Smarty 引 擎<br />

自 动 创 建 的 , 它 将 我 们 在 模 板 中 由 特 殊 定 界 符 声 明 的 变 量 转 换 成 了 PHP 的 语 法 来 执 行 。<br />

下 次 再 读 取 同 样 的 内 容 时 ,Smarty 就 会 直 接 抓 取 这 个 文 件 来 执 行 了 , 直 到 模 板 文 件<br />

test.tpl 有 改 动 时 , 该 文 件 内 容 才 会 跟 着 更 新 。<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 29/85


扩 展 与 框 架 :<br />

《PHPer》<br />

QeePHP 快 速 入 门 ( 七 )—— 实 现 任 务 管 理<br />

1 添 加 任 务<br />

廖 宇 雷<br />

添 加 任 务 的 功 能 实 现 和 前 面 实 现 用 户 功 能 的 流 程 完 全 一 致 :<br />

• 根 据 需 求 完 善 模 型<br />

• 创 建 需 要 的 表 单<br />

• 编 写 控 制 器 代 码<br />

1.1 完 善 task 模 型<br />

打 开 app/model/task.php( 如 果 没 有 则 用 WebSetup 创 建 ), 修 改 下 面 几 个 地 方 :<br />

属 性 和 关 联 的 定 义 :<br />

代 码 片 段<br />

'props' => array<br />

(<br />

.....<br />

'is_completed' => array('readonly' => true),<br />

'completed_at' => array('readonly' => true),<br />

'owner' => array(QDB::BELONGS_TO => 'User', 'source_key' => 'owner_id'),<br />

),<br />

验 证 规 则 :<br />

代 码 片 段<br />

'validations' => array<br />

(<br />

'subject' => array<br />

(<br />

array('not_empty', ' 任 务 主 题 不 能 为 空 '),<br />

array('max_length', 180, ' 任 务 主 题 不 能 超 过 60 个 汉 字 或 180 个 字 符 '),<br />

),<br />

),<br />

自 动 填 充 规 则 :<br />

代 码 片 段<br />

'create_autofill' => array<br />

(<br />

.....<br />

// 新 建 任 务 的 is_completed 状 态 总 是 为 false<br />

'is_completed' => false,<br />

// 新 建 任 务 的 completed_at 值 总 是 为 null<br />

'completed_at' => null,<br />

),<br />

create_autofill 设 置 可 以 在 创 建 对 象 时 将 指 定 的 数 值 设 置 为 特 定 值 。 例 如 “ 新 建 任<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 30/85


扩 展 与 框 架 :<br />

《PHPer》<br />

务 的 状 态 是 未 完 成 ” 这 个 逻 辑 就 可 以 通 过 简 单 的 指 定 create_autofill 来 实 现 。<br />

最 后 再 加 上 安 全 性 设 置 :<br />

代 码 片 段<br />

'attr_accessible' => 'subject, description',<br />

attr_accessible 设 置 会 在 构 造 对 象 时 产 生 作 用 :<br />

代 码 片 段<br />

$task = new Task($form->values());<br />

$task->save();<br />

上 述 代 码 构 造 了 一 个 新 的 task 模 型 实 例 , 并 且 以 表 单 的 值 作 为 对 象 初 始 值 。 这 种<br />

方 式 很 方 便 , 但 存 在 一 个 安 全 隐 患 。<br />

假 设 用 户 在 客 户 端 构 造 一 个 包 含 “task_id” 字 段 值 的 表 单 , 并 提 交 到 服 务 器 , 那 么<br />

此 时 构 造 出 来 的 $task 对 象 就 包 含 了 task_id 属 性 值 。 由 于 task_id 属 性 也 是 task 对<br />

象 存 储 在 tasks 表 中 的 主 键 字 段 , 那 么 在 接 下 来 调 用 save() 方 法 时 , 实 际 完 成 的 操 作<br />

不 是 “ 新 建 一 个 task 对 象 ”, 而 是 “ 更 新 一 个 已 有 的 task 对 象 ”。 因 此 我 们 务 必 要 堵 上<br />

这 样 的 漏 洞 。<br />

设 置 attr_accessible 选 项 , 可 以 指 定 哪 些 属 性 可 以 通 过 构 造 函 数 来 赋 值 , 这 样 上<br />

面 的 代 码 中 即 便 表 单 包 含 task_id 值 , 也 不 会 被 存 入 新 建 的 对 象 , 实 现 了 安 全 性 。<br />

1.2 创 建 表 单<br />

添 加 app/form/task.php 和 app/form/task_form.yaml 文 件 , 内 容 分 别 是 :<br />

代 码 片 段<br />

class Form_Task extends QForm<br />

{<br />

function __construct($action)<br />

{<br />

// 调 用 父 类 的 构 造 函 数<br />

parent::__construct('form_task', $action);<br />

}<br />

}<br />

// 从 配 置 文 件 载 入 表 单<br />

$filename = rtrim(dirname(__FILE__), '/\\') . DS . 'task_form.yaml';<br />

$this->loadFromConfig(Helper_YAML::loadCached($filename));<br />

$this->addValidations(Task::meta());<br />

~form:<br />

_subject: " 添 加 任 务 "<br />

subject:<br />

_ui: textbox<br />

_label: " 任 务 主 题 "<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 31/85


扩 展 与 框 架 :<br />

《PHPer》<br />

description:<br />

_ui: memo<br />

_label: " 任 务 描 述 "<br />

1.3 添 加 控 制 器 动 作<br />

修 改 tasks 控 制 器 ( 如 果 没 有 则 通 过 WebSetup 创 建 ), 添 加 actionCreate() 动 作<br />

方 法 :<br />

代 码 片 段<br />

function actionCreate()<br />

{<br />

$form = new Form_Task(url('tasks/create'));<br />

}<br />

if ($this->_context->isPOST() && $form->validate($_POST))<br />

{<br />

// 通 过 应 用 程 序 对 象 获 得 当 前 用 户 对 象<br />

$user = $this->_app->currentUserObject();<br />

}<br />

// 通 过 用 户 对 象 创 建 任 务<br />

$task = $user->createTask($form['subject']->value, $form['description']->value);<br />

// 保 存 并 重 定 向 浏 览 器<br />

$task->save();<br />

return $this->_redirect(url('tasks/index'));<br />

$this->_view['form'] = $form;<br />

以 及 对 应 的 视 图 app/view/tasks/create.php:<br />

代 码 片 段<br />

<br />

<br />

<br />

<br />

这 里 我 们 用 到 了 应 用 程 序 对 象 的 一 个 新 方 法 currentUserObject()。 但 这 个 方 法 还 需<br />

要 添 加 到 app/myapp.php 中 , 代 码 如 下 :<br />

代 码 片 段<br />

/**<br />

* 获 得 当 前 用 户 对 应 的 User 模 型 对 象 实 例<br />

*<br />

* @return User<br />

*/<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 32/85


扩 展 与 框 架 :<br />

《PHPer》<br />

function currentUserObject()<br />

{<br />

$data = $this->currentUser();<br />

$user = User::find('user_id = ?', $data['id'])->query();<br />

}<br />

if ($user->id())<br />

{<br />

return $user;<br />

}<br />

else<br />

{<br />

throw new MyAppException(' 当 前 访 问 用 户 没 有 对 应 的 User 对 象 ');<br />

}<br />

currentUserObject() 方 法 不 但 通 过 查 询 操 作 获 得 User 模 型 对 象 实 例 , 而 且 通 过 检<br />

查 其 ID 来 确 保 这 个 对 象 是 肯 定 存 在 的 。 这 种 做 法 从 根 本 上 保 证 了 后 续 数 据 的 有 效 性 。<br />

保 证 逻 辑 的 正 确 性 和 数 据 的 有 效 性 是 应 用 程 序 的 核 心 使 命 !<br />

2 测 试 创 建 任 务<br />

通 过 浏 览 器 访<br />

问 http://localhost/todo/public/index.php?controller=tasks&action=create 就 可 以 看 到 添<br />

加 任 务 表 单 :<br />

添 加 任 务 表 单<br />

输 入 有 效 数 据 后 提 交 , 可 以 通 过 phpMyAdmin 看 到 数 据 已 经 成 功 添 加 :<br />

成 功 保 存 到 数 据 库 的 任 务 数 据<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 33/85


扩 展 与 框 架 :<br />

《PHPer》<br />

2.1 添 加 任 务 查 看 页 面<br />

修 改 tasks 控 制 器 的 actionIndex() 动 作 方 法 :<br />

代 码 片 段<br />

function actionIndex()<br />

{<br />

$tasks = Task::find('owner_id = ?', $this->_app->currentUserObject()->id())->getAll();<br />

$this->_view['tasks'] = $tasks;<br />

}<br />

以 及 对 应 的 视 图 app/view/tasks/index.php:<br />

代 码 片 段<br />

<br />

<br />

<br />

我 的 任 务 <br />

<br />


扩 展 与 框 架 :<br />

《PHPer》<br />

.tasks h2 {<br />

font-size: 18px;<br />

font-weight: bold;<br />

}<br />

.tasks p {<br />

font-size: 14px;<br />

color: #333;<br />

font-weight: normal;<br />

}<br />

.tasks p.meta {<br />

font-size: 12px;<br />

font-weight: normal;<br />

color: #666;<br />

}<br />

现 在 添 加 任 务 后 就 可 以 看 到 任 务 列 表 了 :<br />

3 修 改 和 删 除 任 务<br />

任 务 列 表 页 面<br />

修 改 工 作 非 常 简 单 , 在 tasks 控 制 器 中 添 加 如 下 代 码 即 可 :<br />

代 码 片 段<br />

function actionEdit()<br />

{<br />

// 查 询 指 定 ID, 并 且 其 所 有 者 是 当 前 用 户 的 任 务 ( 禁 止 修 改 他 人 的 任 务 )<br />

$task = Task::find('task_id = ? AND [owner.user_id] = ?',<br />

$this->_context->task_id,<br />

$this->_app->currentUserObject()->id())->query();<br />

if (!$task->id())<br />

{<br />

// 如 果 任 务 的 ID 无 效 , 视 图 修 改 的 任 务 不 存 在 或 者 不 是 当 前 用 户 创 建 的<br />

return $this->_redirect(url('tasks/index'));<br />

}<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 35/85


扩 展 与 框 架 :<br />

《PHPer》<br />

// 构 造 表 单 对 象<br />

$form = new Form_Task(url('tasks/edit'));<br />

// 修 改 表 单 标 题<br />

$form->_subject = ' 编 辑 任 务 ';<br />

// 添 加 一 个 checkbox 到 表 单<br />

$form->add(QForm::ELEMENT, 'is_completed', array(<br />

'_ui' => 'checkbox',<br />

'checked_by_value' => true,<br />

'caption' => ' 该 任 务 已 完 成 ',<br />

));<br />

// 添 加 一 个 隐 藏 字 段 到 表 单<br />

$form->add(QForm::ELEMENT, 'task_id', array('_ui' => 'hidden'));<br />

if ($this->_context->isPOST() && $form->validate($_POST))<br />

{<br />

// changeProps() 方 法 可 以 批 量 修 改 task 对 象 的 属 性 , 但 不 会 修 改 只 读 属 性 的 值<br />

$task->changeProps($form->values());<br />

// 根 据 是 否 选 中 “ 已 完 成 ” 检 查 框 来 设 置 任 务 的 状 态<br />

$task->completed($form['is_completed']->value);<br />

// 保 存 并 重 定 向 浏 览 器<br />

$task->save();<br />

return $this->_redirect(url('tasks/index'));<br />

}<br />

elseif (!$this->_context->isPOST())<br />

{<br />

// 如 果 不 是 POST 提 交 , 则 把 对 象 值 导 入 表 单<br />

$form->import($task);<br />

}<br />

$this->_view['form'] = $form;<br />

// 重 用 create 动 作 的 视 图<br />

$this->_viewname = 'create';<br />

}<br />

这 个 方 法 完 成 下 列 工 作 :<br />

• 首 先 根 据 指 定 的 task_id 和 当 前 用 户 ID 查 询 任 务 对 象 , 如 果 失 败 则 重 定 向 浏<br />

览 器 。 这 可 以 有 效 阻 止 用 户 尝 试 编 辑 不 属 于 自 己 的 任 务 。<br />

• 如 果 是 POST 提 交 , 并 且 表 单 通 过 了 验 证 , 则 更 新 任 务 信 息 , 并 且 根 据 是 否<br />

选 中 了 “ 已 完 成 ” 检 查 框 来 修 改 任 务 状 态 。 最 后 保 存 修 改 并 重 定 向 浏 览 器 。<br />

• 不 是 POST 提 交 , 则 将 任 务 对 象 数 据 导 入 表 单 , 以 便 在 表 单 中 显 示 要 编 辑 的<br />

内 容 。<br />

上 述 代 码 中 , 之 所 以 修 改 任 务 状 态 必 须 调 用 completed() 方 法 , 是 为 了 因 为 task<br />

模 型 的 is_completed 属 性 非 常 重 要 , 不 应 该 “ 无 意 ” 中 被 修 改 。 明 确 的 completed() 方<br />

法 调 用 就 可 以 避 免 此 问 题 。 而 且 当 任 务 状 态 改 变 为 “ 已 完 成 ” 时 , 还 需 要 设 置 任 务 的<br />

completed_at 属 性 , 以 记 录 任 务 完 成 的 时 刻 ,completed() 方 法 可 以 同 时 完 成 这 项 修 改 。<br />

所 以 我 们 还 要 在 task 模 型 中 添 加 completed() 方 法 :<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 36/85


扩 展 与 框 架 :<br />

《PHPer》<br />

代 码 片 段<br />

/**<br />

* 明 确 修 改 任 务 的 状 态<br />

*<br />

* @param boolean $completed<br />

*<br />

* @return Task<br />

*/<br />

function completed($completed)<br />

{<br />

$completed = (bool)$completed;<br />

if ($completed && !$this->is_completed)<br />

{<br />

// 如 果 任 务 状 态 从 “ 未 完 成 ” 变 成 “ 已 完 成 ”, 则 保 存 完 成 任 务 的 时 刻<br />

// changePropForce() 可 以 强 制 改 变 一 个 只 读 属 性 的 值<br />

$this->changePropForce('completed_at', time());<br />

}<br />

elseif (!$completed)<br />

{<br />

// 如 果 任 务 状 态 设 置 为 “ 未 完 成 ”, 则 清 理 掉 completed_at 记 录 的 时 间<br />

$this->changePropForce('completed_at', null);<br />

}<br />

$this->changePropForce('is_completed', $completed);<br />

return $this;<br />

}<br />

相 比 传 统 的 做 法 , 面 向 对 象 的 方 式 在 初 期 会 需 要 更 多 的 代 码 。 但 是 这 些 代 码 保 证<br />

了 逻 辑 的 严 密 性 和 数 据 的 有 效 性 , 应 用 软 件 规 模 越 大 , 这 种 做 法 带 来 的 好 处 就 越 多 。<br />

而 且 随 着 应 用 规 模 的 逐 渐 增 长 , 面 向 对 象 充 分 重 用 逻 辑 与 代 码 的 优 势 就 会 体 现 出 来 ,<br />

最 终 可 以 获 得 一 个 更 健 壮 、 内 部 更 整 洁 的 系 统 。<br />

实 际 运 行 效 果 :<br />

修 改 状 态 后 的 任 务<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 37/85


扩 展 与 框 架 :<br />

《PHPer》<br />

4 删 除 任 务<br />

删 除 任 务 功 能 非 常 简 单 :<br />

代 码 片 段<br />

function actionDelete()<br />

{<br />

// destroyWhere() 方 法 的 参 数 和 find() 方 法 完 全 一 致<br />

Task::meta()->destroyWhere('task_id = ? AND [owner.user_id] = ?',<br />

$this->_context->task_id,<br />

$this->_app->currentUserObject()->id());<br />

}<br />

return $this->_redirectMessage(<br />

' 删 除 成 功 ',<br />

' 您 已 经 成 功 删 除 了 一 个 任 务 ',<br />

url('tasks/index'));<br />

修 改 一 下 app/tasks/index.php 视 图 , 将 删 除 任 务 的 连 接 加 进 去 :<br />

代 码 片 段<br />

<br />

<br />

已 经 在 完 成 该 任 务 <br />

<br />

添 加 日 期 :<br />

<br />

,


扩 展 与 框 架 :<br />

《PHPer》<br />

5 分 页 与 最 后 的 完 善<br />

成 功 删 除<br />

随 着 我 们 往 应 用 程 序 中 添 加 了 越 来 越 多 的 任 务 , 分 页 显 示 就 势 在 必 行 了 。QeePHP<br />

对 分 页 有 各 种 内 置 的 方 法 , 而 且 可 以 使 用 现 成 的 分 页 导 航 插 件 来 减 少 工 作 量 。<br />

5.1 学 会 偷 懒<br />

当 你 需 要 往 应 用 程 序 中 添 加 一 个 新 功 能 时 , 请 首 先 查 看 http://qeephp.com/projects,<br />

也 许 惊 喜 就 在 等 着 你 。<br />

这 里 我 们 使 用 http://qeephp.com/projects/pagination 这 个 分 页 导 航 插 件 。 按 照 这 个<br />

控 件 的 说 明 把 控 件 文 件 和 样 式 表 加 入 到 应 用 程 序 中 后 , 修 改 tasks 控 制 器 的<br />

actionIndex() 方 法 为 :<br />

代 码 片 段<br />

function actionIndex()<br />

{<br />

// 分 页 查 询<br />

$page = intval($this->_context->page);<br />

if ($page < 1) $page = 1;<br />

// 构 造 查 询 对 象<br />

$select = Task::find('owner_id = ?', $this->_app->currentUserObject()->id());<br />

$select->limitPage($page, 5);<br />

// 将 分 页 信 息 和 查 询 到 的 数 据 传 递 到 视 图<br />

$this->_view['pagination'] = $select->getPagination();<br />

$this->_view['tasks'] = $select->getAll();<br />

}<br />

最 后 修 改 app/view/tasks/index.php 视 图 , 在 最 后 一 行 前 加 入 :<br />

代 码 片 段<br />

<br />

刷 新 浏 览 器 :<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 39/85


扩 展 与 框 架 :<br />

《PHPer》<br />

分 页 控 件<br />

多 页 效 果<br />

5.2 完 善 列 表 页 面<br />

经 过 一 番 努 力 ,todo 应 用 已 经 比 较 完 善 了 , 我 们 再 补 充 一 个 小 功 能 : 在 列 表 页 面<br />

直 接 创 建 任 务 。<br />

修 改 app/view/tasks/index.php 视 图 , 在 最 后 一 行 前 加 入 :<br />

代 码 片 段<br />

<br />

现 在 在 列 表 页 面 就 可 以 直 接 添 加 任 务 了 。<br />

5.3 修 改 默 认 控 制 器<br />

当 前 , 查 看 任 务 列 表 需 要 我 们 在 URL 中 明 确 指 定 访 问 tasks 控 制 器 , 这 显 然 很 不<br />

友 好 。 所 以 我 们 对 默 认 的 default 控 制 器 做 一 点 小 手 术 ,<br />

修 改 app/controller/default_controller.php 文 件 的 内 容 为 :<br />

代 码 片 段<br />

class Controller_Default extends Controller_Abstract<br />

{<br />

function actionIndex()<br />

{<br />

if ($this->_app->currentUserRoles())<br />

{<br />

// 如 果 已 经 登 录 , 就 转 到 任 务 列 表 页 面<br />

return $this->_redirect(url('tasks/index'));<br />

}<br />

else<br />

{<br />

// 未 登 录 则 转 到 登 录 页 面<br />

return $this->_redirect(url('users/login'));<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 40/85


扩 展 与 框 架 :<br />

《PHPer》<br />

}<br />

}<br />

}<br />

修 改 后 ,todo 应 用 的 功 能 就 算 齐 备 了 。<br />

框 架 介 绍<br />

QeePHP 是 新 一 代 敏 捷 开 发 框 架<br />

QeePHP 是 全 球 第 一 个 遵 循 “ 领 域 驱<br />

动 ­ 开 发 ” 思 想 设 计 和 实 现 的 PHP 开 发 框<br />

架 。 在 保 持 易 学 易 用 、 ­ 快 速 稳 定 的 同 时 ,<br />

QeePHP 为 创 建 具 有 复 杂 内 在 逻 辑 的<br />

Web 应 用 提 供 了 全 方 位 的 支 持 。<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 41/85


企 业 解 决 方 案 :<br />

《PHPer》<br />

企 业 解 决 方 案<br />

Web 站 点 性 能 监 控<br />

郭 欣<br />

我 们 需 要 通 过 监 控 的 手 段 来 洞 察 站 点 性 能 的 变 化 , 它 会 带 给 你 优 化 的 理 由 , 也 会<br />

告 诉 你 瓶 颈 的 真 相 , 更 重 要 的 是 , 它 让 你 拥 有 敏 锐 的 直 觉 , 没 有 它 , 你 可 能 根 本 无 法<br />

知 道 你 的 站 点 是 否 健 康 , 因 为 你 不 可 能 每 天 都 去 费 力 地 阅 读 日 志 。<br />

没 有 人 会 认 为 站 点 的 性 能 一 成 不 变 , 的 确 , 它 时 时 刻 刻 都 在 变 化 , 各 种 各 样 的 原<br />

因 会 导 致 站 点 不 能 保 持 我 们 预 期 的 性 能 , 不 论 我 们 做 了 多 少 努 力 , 你 总 是 不 知 道 下 一<br />

刻 会 发 生 什 么 , 性 能 监 控 在 某 种 程 度 上 就 像 是 晴 雨 表 , 它 能 反 映 一 定 的 性 能 变 化 规 律<br />

和 趋 势 , 所 以 , 能 够 快 速 从 监 控 数 据 和 图 表 中 找 到 线 索 是 你 必 须 具 备 的 本 领 。<br />

事 实 上 , 在 前 面 的 章 节 中 我 们 已 经 或 多 或 少 地 用 到 了 一 些 监 控 数 据 和 图 表 , 可 见 ,<br />

这 些 内 容 和 性 能 分 析 是 不 可 分 割 的 , 这 一 章 我 们 将 主 要 介 绍 一 些 提 供 性 能 监 控 的 工 具<br />

和 系 统 , 你 可 以 通 过 它 们 快 速 搭 建 监 控 中 心 。<br />

1 实 时 监 控<br />

Nmon 是 一 款 工 作 在 服 务 器 本 地 的 实 时 监 控 软 件 , 它 可 以 提 供 时 间 间 隔 为 秒 的 系<br />

统 监 控 , 我 们 来 看 它 的 监 控 界 面 , 如 图 1 所 示 。<br />

这 还 只 是 Nmon 所 能 监 控 的 一 部 分 , 它 还 可 以 监 控 内 核 状 态 、 系 统 负 载 、 虚 拟 内<br />

存 、NFS 等 , 只 要 有 足 够 大 的 显 示 器 , 你 可 以 把 它 们 都 添 加 到 主 界 面 中 , 服 务 器 的 一<br />

切 活 动 尽 收 眼 底 , 你 可 以 在 最 短 的 时 间 内 知 道 服 务 器 现 在 在 忙 什 么 。<br />

除 此 之 外 , 你 还 可 以 用 Nmon 来 录 制 数 据 , 并 通 过 另 一 个 分 析 工 具 Nmon Analyser<br />

生 成 监 控 统 计 报 告 , 如 图 2 及 图 3 所 示 , 我 们 生 成 了 间 隔 为 1 秒 的 监 控 报 告 , 其 中 包<br />

括 CPU 使 用 率 和 磁 盘 I/O。<br />

图 1 通 过 Nmon 来 进 行 系 统 监 控<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 42/85


企 业 解 决 方 案 :<br />

《PHPer》<br />

图 2 通 过 Nmon Analyser 获 得 CPU 使 用 率 统 计 报 表<br />

通 常 , 我 们 只 是 在 一 些 必 要 的 时 候 进 行 实 时 监 控 , 主 要 包 括 :<br />

• 快 速 查 看 系 统 某 组 件 的 状 态 , 比 如 进 行 网 络 结 构 调 整 后 需 要 快 速 知 道 当 前 时<br />

刻 的 网 络 流 量 变 化 , 而 通 过 MRTG 等 方 法 你 可 能 需 要 等 待 几 分 钟 后 的 图 表 更<br />

新 。<br />

• 观 察 一 些 底 层 的 系 统 状 态 , 比 如 内 核 切 换 、 进 程 队 列 、 中 断 次 数 等 , 这 些 状<br />

态 通 常 无 法 通 过 其 他 监 控 系 统 获 得 。<br />

• 根 据 最 小 时 间 间 隔 的 状 态 变 化 来 进 行 一 些 诊 断 , 比 如 通 常 的 监 控 系 统 会 将 5<br />

分 钟 内 的 状 态 进 行 平 均 计 算 , 那 么 5 分 钟 内 的 变 化 情 况 我 们 并 不 知 道 , 也 许<br />

对 于 一 些 系 统 组 件 来 说 , 这 5 分 钟 内 的 变 化 曲 线 隐 藏 着 重 要 的 线 索 。<br />

• 你 喜 欢 快 节 奏 的 工 作 方 式 , 喜 欢 看 到 屏 幕 快 速 刷 新 。<br />

图 3 通 过 Nmon Analyser 获 得 磁 盘 I/O 统 计 报 表<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 43/85


企 业 解 决 方 案 :<br />

《PHPer》<br />

除 此 之 外 , 你 可 能 并 不 需 要 经 常 进 行 实 时 监 控 , 毕 竟 这 需 要 你 通 过 SSH 登 录 到 服<br />

务 器 上 进 行 操 作 , 而 如 果 你 要 兼 顾 很 多 台 服 务 器 的 话 , 这 样 做 显 然 很 不 现 实 , 其 实 ,<br />

大 多 数 时 候 , 我 们 更 希 望 通 过 远 程 来 对 服 务 器 实 施 监 控 , 并 且 建 立 统 一 入 口 的 监 控 中<br />

心 , 同 时 , 也 可 以 放 慢 监 控 的 节 奏 , 因 为 过 于 实 时 的 监 控 对 服 务 器 本 身 来 说 也 存 在 一<br />

定 的 开 销 。<br />

2 监 控 代 理<br />

一 旦 我 们 需 要 通 过 远 程 来 监 控 服 务 器 , 那 么 监 控 代 理 程 序 便 必 不 可 少 , 它 负 责 将<br />

服 务 器 本 地 的 各 种 状 态 定 期 上 报 给 监 控 中 心 , 或 者 响 应 来 自 监 控 中 心 的 请 求 , 这 使 得<br />

远 程 监 控 成 为 可 能 。<br />

你 可 以 为 站 点 服 务 器 开 发 专 用 的 监 控 代 理 程 序 , 并 从 本 地 文 件 中 获 取 状 态 数 据 ,<br />

在 Linux 中 , 一 切 都 是 文 件 , 当 然 也 包 括 各 种 系 统 状 态 , 比 如 我 们 可 以 在 这 里 看 到 详<br />

细 的 内 存 使 用 情 况 :<br />

s-200:~ # cat /proc/meminfo<br />

MemTotal: 4142240 kB<br />

MemFree: 344428 kB<br />

Buffers:<br />

598264 kB<br />

Cached:<br />

2067336 kB<br />

SwapCached: 4 kB<br />

Active:<br />

2598232 kB<br />

Inactive:<br />

1024660 kB<br />

HighTotal: 3272000 kB<br />

HighFree: 333912 kB<br />

LowTotal: 870240 kB<br />

LowFree: 10516 kB<br />

SwapTotal: 1196800 kB<br />

SwapFree: 1196672 kB<br />

Dirty: 500 kB<br />

Writeback: 0 kB<br />

Mapped:<br />

1086088 kB<br />

Slab:<br />

146180 kB<br />

CommitLimit: 3267920 kB<br />

Committed_AS: 6955560 kB<br />

PageTables: 11908 kB<br />

VmallocTotal: 112632 kB<br />

VmallocUsed: 17640 kB<br />

VmallocChunk: 94496 kB<br />

HugePages_Total: 0<br />

HugePages_Free: 0<br />

HugePages_Rsvd: 0<br />

Hugepagesize: 2048 kB<br />

也 可 以 看 到 系 统 负 载 和 进 程 队 列 状 态 :<br />

s-200:~ # cat /proc/loadavg<br />

0.02 0.03 0.00 1/894 21407<br />

这 样 一 来 , 你 只 需 要 将 这 些 数 据 打 包 , 按 照 你 定 义 的 格 式 上 报 给 监 控 中 心 即 可 。<br />

不 过 , 如 果 只 是 监 控 这 些 系 统 状 态 , 你 完 全 可 以 利 用 SNMP 来 完 成 这 些 工 作 ,SNMP<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 44/85


企 业 解 决 方 案 :<br />

《PHPer》<br />

服 务 器 端 本 身 便 是 一 个 出 色 的 监 控 代 理 程 序 , 它 已 经 逐 渐 成 为 标 准 , 并 且 支 持 很 多 异<br />

构 平 台 。<br />

比 如 , 我 们 通 过 SNMP 来 获 取 另 一 台 服 务 器 的 所 有 设 备 状 态 , 如 下 所 示 :<br />

s-200:~ # snmpwalk -c public -v 2c 10.0.1.201<br />

SNMPv2-MIB::sysDescr.0 = STRING: Linux s-mat 2.6.16.21-0.8-bigsmp #1 SMP Mon Jul<br />

3 18:25:39 UTC 2006 i686<br />

SNMPv2-MIB::sysObjectID.0 = OID: NET-SNMP-MIB::netSnmpAgentOIDs.10<br />

DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (68135977) 7 days, 21:15:59.77<br />

SNMPv2-MIB::sysContact.0 = STRING: Sysadmin (root@localhost)<br />

SNMPv2-MIB::sysName.0 = STRING: s-mat<br />

SNMPv2-MIB::sysLocation.0 = STRING: Server Room<br />

SNMPv2-MIB::sysORLastChange.0 = Timeticks: (0) 0:00:00.00<br />

SNMPv2-MIB::sysORID.1 = OID: SNMPv2-MIB::snmpMIB<br />

SNMPv2-MIB::sysORID.2 = OID: TCP-MIB::tcpMIB<br />

SNMPv2-MIB::sysORID.3 = OID: IP-MIB::ip<br />

SNMPv2-MIB::sysORID.4 = OID: UDP-MIB::udpMIB<br />

SNMPv2-MIB::sysORID.5 = OID: SNMP-VIEW-BASED-ACM-MIB::vacmBasicGroup<br />

SNMPv2-MIB::sysORID.6 = OID:<br />

SNMP-FRAMEWORK-MIB::snmpFrameworkMIBComp liance<br />

......<br />

这 里 仅 仅 列 出 了 其 中 很 少 的 一 部 分 , 事 实 上 整 个 结 果 集 非 常 庞 大 , 一 般 我 们 要 限<br />

定 需 要 获 取 状 态 的 设 备 名 称 , 可 以 通 过 MIB 来 描 述 它 , 比 如 这 里 我 们 要 获 取 一 台<br />

Windows 服 务 器 的 运 行 时 间 , 如 下 所 示 :<br />

s-200:~ # snmpwalk -c public -v 2c 10.0.1.210 hrSystemUptime<br />

HOST-RESOURCES-MIB::hrSystemUptime.0 = Timeticks: (630851406) 73 days,<br />

0:21:54.06<br />

包 括 MRTG、Cacti 以 及 Nagios 在 内 的 很 多 监 控 工 具 都 利 用 SNMP 来 监 控 远 程 服<br />

务 器 , 而 你 只 需 要 在 被 监 控 的 服 务 器 上 开 启 SNMP 服 务 , 同 时 对 监 控 来 源 进 行 授 权 配<br />

置 即 可 。<br />

当 然 ,SNMP 并 不 是 万 能 的 , 有 一 些 我 们 希 望 监 控 的 服 务 并 没 有 提 供 相 应 的 SNMP<br />

支 持 , 比 如 我 们 要 监 控 Nginx 服 务 器 当 前 的 HTTP 并 发 连 接 数 , 该 怎 么 做 呢 ? 是 否 需<br />

要 自 己 开 发 监 控 代 理 程 序 呢 ? 幸 运 的 是 ,Nginx 提 供 了 必 要 的 HTTP 监 控 接 口 , 你 可<br />

以 直 接 在 监 控 中 心 请 求 它 即 可 , 比 如 我 们 通 过 请 求 以 下 URL:<br />

http://10.0.1.200/status<br />

便 可 以 看 到 Nginx 当 前 的 运 行 状 态 :<br />

Active connections: 3020<br />

server accepts handled requests<br />

5440803 5440803 7336362<br />

Reading: 471 Writing: 2340 Waiting: 209<br />

总 之 , 通 过 监 控 代 理 程 序 , 我 们 可 以 更 加 轻 松 地 了 解 服 务 器 的 各 种 状 态 , 所 以 ,<br />

不 论 你 希 望 监 控 服 务 器 的 何 种 状 态 , 只 需 要 考 虑 开 发 相 应 的 监 控 代 理 程 序 即 可 , 你 甚<br />

至 可 以 监 控 CPU 的 温 度 , 前 提 是 你 的 内 核 能 够 支 持 。<br />

3 系 统 监 控<br />

通 常 情 况 下 , 我 们 通 过 SNMP 便 可 以 很 容 易 地 对 服 务 器 进 行 一 些 常 规 的 系 统 监 控 ,<br />

这 包 括 CPU 使 用 率 、 系 统 负 载 、 内 存 使 用 率 、 网 络 I/O、 磁 盘 I/O、 磁 盘 使 用 率 等 ,<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 45/85


企 业 解 决 方 案 :<br />

《PHPer》<br />

这 些 是 我 们 比 较 关 心 的 。 当 然 , 我 们 还 需 要 建 立 监 控 中 心 , 对 这 些 状 态 数 据 进 行 统 计<br />

和 呈 现 。 幸 运 的 是 , 有 很 多 开 源 产 品 可 以 帮 助 我 们 , 这 里 我 们 主 要 以 Cacti 为 例 , 它<br />

完 全 可 以 支 持 刚 刚 提 到 的 这 些 系 统 监 控 , 并 且 绘 制 出 相 应 的 图 表 , 便 于 我 们 浏 览 。<br />

Cacti 采 用 RRDtool 作 为 监 控 数 据 的 存 储 引 擎 , 它 是 一 种 专 门 针 对 绘 制 坐 标 图 而 设<br />

计 的 存 储 格 式 , 相 对 于 其 他 存 储 结 构 来 说 要 节 省 很 多 存 储 空 间 , 这 为 我 们 长 期 监 控 大<br />

量 服 务 器 提 供 了 可 能 。 相 对 于 本 书 的 主 题 来 说 , 我 们 不 打 算 花 大 量 的 篇 幅 从 运 维 工 作<br />

的 角 度 来 介 绍 监 控 系 统 本 身 的 使 用 , 你 可 以 查 阅 大 量 相 关 的 在 线 文 档 。<br />

对 于 刚 刚 提 到 的 CPU 使 用 率 等 状 态 监 控 , 其 数 据 和 图 表 背 后 的 含 义 , 我 们 在 前 面 的<br />

章 节 中 已 经 有 过 详 细 介 绍 , 所 以 , 接 下 来 我 们 只 会 对 图 表 本 身 进 行 简 单 的 介 绍 , 当 你<br />

实 际 浏 览 这 些 监 控 图 表 时 , 应 该 充 分 结 合 前 面 的 内 容 以 及 站 点 的 实 际 情 况 来 具 体 分 析<br />

它 们 的 含 义 。<br />

作 为 服 务 器 的 心 脏 ,CPU 的 使 用 率 是 我 们 非 常 关 注 的 一 项 系 统 状 态 , 如 图 18-4 所<br />

示 , 这 是 一 台 运 行 着 MySQL 的 专 用 数 据 库 服 务 器 , 图 上 清 晰 地 呈 现 出 CPU 在 用 户 空<br />

间 和 内 核 空 间 的 时 间 开 销 , 可 以 看 得 出 , 用 户 空 间 进 程 花 费 了 大 量 的 CPU 时 间 , 这<br />

正 符 合 数 据 库 应 用 的 特 点 , 如 果 希 望 更 加 深 入 地 了 解 数 据 库 内 部 的 具 体 开 销 , 你 同 样<br />

可 以 对 MySQL 进 行 监 控 , 随 后 我 们 会 介 绍 这 方 面 的 内 容 。<br />

图 4 CPU 使 用 率 监 控<br />

另 外 , 不 难 看 出 , 这 里 的 图 表 采 用 了 常 见 的 累 积 图 方 式 , 它 的 好 处 是 可 以 直 接 呈<br />

现 出 累 加 结 果 , 比 如 这 里 的 累 加 结 果 便 是 CPU 使 用 率 总 和 。<br />

通 过 前 面 的 介 绍 , 我 们 已 经 了 解 了 系 统 负 载 的 意 义 , 它 的 监 控 图 表 如 图 5 所 示 , 我 们<br />

可 以 看 到 1 分 钟 、5 分 钟 、15 分 钟 的 平 均 负 载 变 化 情 况 , 但 是 , 它 们 的 累 加 结 果 没 有<br />

太 多 实 际 意 义 。<br />

图 5 系 统 负 载 监 控<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 46/85


企 业 解 决 方 案 :<br />

《PHPer》<br />

如 图 6 所 示 , 这 是 一 台 运 行 着 Apache 的 Web 服 务 器 , 可 以 看 到 它 的 内 存 使 用 率<br />

并 不 饱 和 , 事 实 上 , 它 的 httpd 进 程 并 不 多 , 所 以 并 没 有 消 耗 太 多 的 物 理 内 存 。<br />

而 对 于 以 下 的 MySQL 服 务 器 , 我 们 为 它 最 大 程 度 地 分 配 了 物 理 内 存 作 为 Innodb 缓 存 ,<br />

可 以 看 到 内 存 使 用 率 已 经 接 近 饱 和 , 如 图 7 所 示 。<br />

图 6 Web 服 务 器 的 内 存 使 用 率 监 控<br />

图 7 数 据 库 服 务 器 的 内 存 使 用 率 监 控<br />

在 前 面 的 章 节 中 我 们 多 次 提 到 磁 盘 I/O, 那 么 , 通 过 磁 盘 I/O 监 控 , 我 们 可 以 了 解<br />

磁 盘 是 否 繁 忙 , 包 括 读 操 作 和 写 操 作 , 如 图 8 所 示 。<br />

图 8 磁 盘 I/O 监 控<br />

磁 盘 空 间 也 是 我 们 关 注 的 另 一 个 方 面 , 通 过 磁 盘 使 用 率 监 控 , 我 们 可 以 更 好 地 了<br />

解 磁 盘 空 间 的 使 用 情 况 和 变 化 趋 势 , 如 图 9 所 示 。<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 47/85


企 业 解 决 方 案 :<br />

《PHPer》<br />

图 9 磁 盘 使 用 率 监 控<br />

网 络 流 量 监 控 可 以 帮 助 我 们 了 解 服 务 器 的 通 信 数 据 量 , 包 括 流 入 和 流 出 两 部 分 ,<br />

如 图 10 所 示 , 对 于 提 供 HTTP 服 务 的 服 务 器 来 说 , 流 出 的 数 据 量 要 大 于 流 入 的 数 据<br />

量 , 因 为 HTTP 响 应 数 据 长 度 通 常 大 于 请 求 数 据 长 度 。 另 一 方 面 , 对 于 流 量 情 况 的 了<br />

解 , 可 以 帮 我 们 更 好 地 把 握 带 宽 的 使 用 情 况 。<br />

4 服 务 监 控<br />

图 10 网 络 I/O 监 控<br />

除 了 基 本 的 系 统 监 控 之 外 , 我 们 还 非 常 关 心 应 用 层 服 务 的 状 态 , 它 们 更 加 直 接 地<br />

反 映 了 Web 应 用 的 性 能 。Cacti 中 支 持 插 件 机 制 , 我 们 可 以 通 过 一 些 第 三 方 模 板 来 监<br />

控 这 些 服 务 , 同 时 , 我 们 还 需 要 相 应 的 监 控 代 理 , 幸 运 的 是 , 一 些 常 用 的 服 务 已 经 考<br />

虑 到 这 一 点 , 它 们 提 供 了 一 定 的 监 控 访 问 接 口 , 比 如 Apache 中 基 于 HTTP 的 mod_status<br />

模 块 , 在 httpd.conf 中 配 置 如 下 :<br />

ExtendedStatus On<br />

<br />

SetHandler server-status<br />

Order deny,allow<br />

Deny from all<br />

Allow from all<br />

<br />

这 样 一 来 , 我 们 便 可 以 通 过 /server-status 的 URL 来 查 看 Apache 的 当 前 状 态 , 这 相<br />

当 于 Apache 的 监 控 代 理 , 有 了 它 以 后 , 我 们 在 Cacti 中 通 过 相 应 的 第 三 方 模 板 , 生 成<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 48/85


企 业 解 决 方 案 :<br />

《PHPer》<br />

了 如 图 11 所 示 的 监 控 图 表 。<br />

图 11 Apache 状 态 监 控<br />

同 样 ,Lighttpd 和 Nginx 也 可 以 按 照 类 似 的 方 式 进 行 状 态 监 控 , 这 里 就 不 再 详 细 介<br />

绍 。<br />

除 了 Web 服 务 器 之 外 , 我 们 还 可 能 需 要 对 反 向 代 理 服 务 器 进 行 监 控 , 在 前 面 介 绍<br />

Varnish 的 时 候 , 我 们 已 经 介 绍 了 它 的 监 控 图 表 , 我 们 比 较 关 心 的 是 它 的 缓 存 命 中 率 等<br />

参 数 。<br />

另 外 , 你 或 许 也 需 要 对 Memcached 进 行 监 控 , 在 介 绍 分 布 式 缓 存 的 时 候 我 们 曾 经<br />

介 绍 过 这 方 面 的 内 容 , 包 括 I/O 数 据 量 、 缓 存 命 中 率 、 空 间 使 用 率 等 。<br />

同 样 , 在 数 据 库 性 能 优 化 的 章 节 中 , 我 们 了 解 了 数 据 库 的 性 能 对 于 站 点 应 用 来 说 何 等<br />

重 要 , 所 以 , 数 据 库 的 监 控 必 不 可 少 , 我 们 在 Cacti 中 可 以 对 MySQL 进 行 各 种 监 控 ,<br />

如 图 12~ 图 14 所 示 。<br />

图 12 MySQL 的 锁 定 和 慢 查 询 监 控<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 49/85


企 业 解 决 方 案 :<br />

《PHPer》<br />

图 13 MySQL 的 临 时 表 监 控<br />

图 14 MySQL 的 查 询 统 计 监 控<br />

这 几 项 监 控 图 表 所 表 达 的 意 义 , 我 们 同 样 在 前 面 的 章 节 中 有 过 详 细 介 绍 , 通 过 监<br />

控 , 你 能 够 更 加 自 如 地 运 用 各 种 优 化 策 略 。<br />

5 响 应 时 间 监 控<br />

的 确 , 以 上 这 些 监 控 措 施 可 以 帮 助 我 们 直 观 地 了 解 系 统 和 服 务 本 身 的 运 行 状 况 ,<br />

但 是 , 从 另 一 个 角 度 来 看 , 位 于 网 络 另 一 端 的 最 终 用 户 只 关 心 响 应 时 间 , 你 知 道 它 们<br />

的 真 实 体 验 吗 ? 我 很 想 知 道 。 同 时 , 用 户 访 问 多 种 不 同 的 Web 应 用 , 比 如 站 点 首 页 、<br />

购 物 车 、 查 找 好 友 等 , 它 们 执 行 不 同 的 商 业 逻 辑 。 当 然 , 我 们 希 望 了 解 这 些 不 同 Web<br />

应 用 的 真 实 服 务 品 质 , 尽 管 它 们 可 能 都 运 行 在 一 个 Web 服 务 器 上 , 但 是 我 们 对 这 些 应<br />

用 的 性 能 要 求 并 不 相 同 , 显 然 , 通 过 以 上 这 些 监 控 手 段 已 经 力 不 从 心 。<br />

所 以 , 这 时 候 我 们 需 要 借 助 一 些 第 三 方 工 具 , 这 里 推 荐 监 控 宝<br />

(www.jiankongbao.com), 它 像 Cacti 一 样 提 供 基 于 Web 的 服 务 界 面 , 但 你 不 用 花 时<br />

间 去 安 装 和 部 署 , 只 需 要 注 册 和 添 加 监 控 任 务 便 可 以 快 速 使 用 。<br />

由 于 监 控 宝 拥 有 独 立 的 监 控 点 , 所 有 它 可 以 定 时 模 拟 用 户 来 请 求 你 指 定 的 多 个<br />

URL, 并 且 记 录 详 细 的 响 应 时 间 , 如 图 15~ 图 17 所 示 。<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 50/85


企 业 解 决 方 案 :<br />

《PHPer》<br />

图 15 HTTP 请 求 结 果 快 照<br />

图 16 HTTP 请 求 过 程 的 详 细 时 间 统 计 表<br />

图 17 HTTP 请 求 过 程 的 详 细 时 间 展 示 图<br />

可 以 看 到 , 在 这 一 系 列 时 间 中 ,DNS 域 名 解 析 所 消 耗 的 时 间 实 际 上 取 决 于 DNS<br />

服 务 器 的 性 能 以 及 用 户 到 DNS 服 务 器 的 网 络 状 况 。 除 此 之 外 ,DNS 记 录 还 可 能 会 缓<br />

存 在 互 联 网 接 入 服 务 商 的 各 级 DNS 服 务 器 上 , 这 取 决 于 DNS 记 录 的 TTL 值 。<br />

建 立 连 接 的 时 间 体 现 了 Web 服 务 器 能 否 快 速 地 接 入 用 户 的 请 求 。 在 通 常 情 况 下 ,<br />

当 Web 服 务 器 的 同 时 连 接 数 达 到 预 设 限 制 时 ,Web 服 务 器 可 能 会 拒 绝 新 的 接 入 请 求 ,<br />

而 对 于 Apache 这 样 的 多 进 程 模 型 , 当 进 程 数 不 断 增 多 时 , 由 于 上 下 文 切 换 的 时 间 开<br />

销 也 随 之 增 加 , 所 以 建 立 连 接 的 平 均 时 间 也 逐 渐 开 始 延 长 。<br />

接 下 来 的 服 务 器 计 算 时 间 很 容 易 理 解 , 对 于 静 态 文 件 的 访 问 , 这 部 分 时 间 主 要 用<br />

于 文 件 的 定 位 , 如 果 是 较 小 的 文 件 , 那 么 还 会 包 括 文 件 读 取 时 间 ; 而 如 果 是 较 大 的 文<br />

件 , 前 面 章 节 曾 提 到 过 Web 服 务 器 会 使 用 sendfile 来 直 接 传 送 文 件 内 容 到 网 络 设 备 ,<br />

所 以 读 取 文 件 的 时 间 并 没 有 算 入 这 里 的 服 务 器 计 算 时 间 , 而 是 归 入 内 容 下 载 时 间 。<br />

对 于 动 态 内 容 的 访 问 , 这 里 的 服 务 器 计 算 时 间 具 有 非 常 重 要 的 参 考 价 值 , 这 些 时 间 意<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 51/85


企 业 解 决 方 案 :<br />

《PHPer》<br />

味 着 什 么 , 你 一 定 比 我 更 加 清 楚 。 事 实 上 , 这 本 书 的 大 部 分 篇 幅 都 在 介 绍 如 何 减 少 这<br />

部 分 时 间 。<br />

最 后 的 内 容 下 载 时 间 从 根 本 上 来 说 取 决 于 用 户 和 服 务 器 两 端 的 带 宽 。 如 果 你 希 望<br />

减 少 这 部 分 时 间 , 在 前 面 关 于 数 据 网 络 传 输 的 章 节 中 你 会 找 到 部 分 答 案 。<br />

另 外 , 监 控 宝 还 提 供 了 报 告 视 图 , 你 可 以 查 看 一 段 时 间 范 围 的 响 应 时 间 变 化 曲 线 ,<br />

如 图 18 所 示 。<br />

图 18 某 时 间 范 围 的 响 应 时 间 变 化 曲 线<br />

同 时 , 还 可 以 按 照 响 应 时 间 范 围 的 次 数 和 百 分 比 进 行 统 计 , 你 可 以 直 观 地 了 解 服<br />

务 质 量 , 如 图 19 所 示 。<br />

图 19 响 应 时 间 范 围 的 次 数 和 百 分 比 统 计<br />

当 然 , 可 用 性 统 计 也 必 不 可 少 , 如 图 20 所 示 。<br />

除 此 之 外 , 监 控 宝 还 提 供 了 一 些 其 他 的 工 具 ( 如 故 障 报 警 ), 并 且 支 持 HTTP 以 外<br />

的 其 他 协 议 ( 如 DNS 服 务 器 的 监 控 ), 这 里 就 不 详 细 介 绍 了 。<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 52/85


企 业 解 决 方 案 :<br />

《PHPer》<br />

图 20 可 用 性 统 计 报 告<br />

作 者 简 介 :<br />

郭 欣 曾 在 腾 讯 网 基 础 平 台 研 发 团 队 , 负 责 诸 多 Web 应 用 的 开 发 和 技 术 管 理 ,<br />

并 致 力 于 性 能 研 究 和 实 践 推 广 。 在 加 入 腾 讯 之 前 , 获 得 国 家 系 统 分 析 师 职 称 。 目 前 在<br />

工 作 之 余 从 事 独 立 研 究 , 其 中 包 括 高 性 能 Web 架 构 和 Web 敏 捷 开 发 框 架 , 并 且 积 极 投<br />

身 开 源 事 业 , 同 时 在 为 Smart Developer 系 列 进 行 创 作 。<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 53/85


项 目 管 理<br />

《PHPer》<br />

项 目 管 理<br />

为 什 么 领 导 力 以 信 任 为 基 础 ( 二 )<br />

著 :Berkun.S<br />

译 : 李 桂 杰<br />

努 力 去 争 取 挣 得 型 权 力<br />

几 个 星 期 下 来 , 我 逐 渐 赢 得 了 Bill 的 信 任 。 开 始 的 时 候 , 非 常 令 人 痛 苦 。 为 了 让<br />

他 能 够 协 助 我 , 我 必 须 得 证 明 我 有 能 力 , 能 够 从 小 做 大 。 我 发 现 , 当 我 承 认 对 于 某 事<br />

他 知 道 得 比 我 要 多 时 , 就 很 容 易 从 他 那 里 得 到 不 错 的 建 议 。 当 我 做 出 承 诺 , 并 且 兑 现<br />

时 , 他 变 得 非 常 大 度 。 虽 然 我 要 做 出 正 确 的 决 策 , 用 有 力 的 论 据 来 证 明 我 的 观 点 , 但<br />

是 , 最 终 我 们 培 养 出 一 种 稳 固 的 工 作 关 系 。Bill 赋 予 我 权 力 做 出 对 他 有 重 大 影 响 的 决<br />

策 。 他 只 是 需 要 我 表 明 我 值 得 他 付 出 信 心 。<br />

如 果 一 开 始 , 我 就 运 用 我 所 拥 有 的 授 予 型 权 力 , 那 么 我 将 失 去 赢 得 权 力 的 机 会 。<br />

第 一 天 ,Bill 可 能 会 屈 服 于 我 , 但 是 , 因 为 他 只 对 我 的 权 力 做 出 回 应 , 就 很 难 越 过 这<br />

一 点 , 以 一 种 更 加 易 于 合 作 的 方 式 来 共 同 工 作 。 如 果 我 继 续 依 赖 那 种 权 力 ( 当 你 开 始<br />

运 用 这 种 权 力 时 , 就 会 倾 向 于 一 直 这 样 ), 渐 渐 地 , 它 就 变 得 不 再 那 么 有 效 。 每 次 当<br />

经 理 或 者 领 导 说 ,“ 应 为 我 这 么 说 ”, 他 们 就 会 终 止 讨 论 , 封 杀 可 能 产 生 的 好 建 议 。 他<br />

们 周 围 任 何 精 明 和 有 激 情 的 人 , 都 不 会 尽 全 力 去 工 作 , 对 于 他 们 所 扮 演 的 有 限 角 色 ,<br />

也 不 会 感 到 高 兴 。<br />

从 组 织 的 立 场 来 看 , 独 裁 专 制 的 行 为 , 会 把 善 于 思 考 的 人 推 到 一 边 。 同 时 , 也 会<br />

鼓 励 那 些 习 惯 于 按 命 令 办 事 的 人 留 在 周 围 。 暴 君 创 造 了 一 种 只 有 奴 才 才 可 以 忍 受 的 环<br />

境 , 反 之 亦 然 。 更 糟 糕 的 是 , 暴 君 把 底 下 的 人 也 变 成 了 暴 君 。 这 种 行 为 模 式 ( 只 听 授<br />

予 型 权 力 ) 会 向 下 传 遍 组 织 , 最 终 会 毒 害 他 们 。<br />

说 服 比 发 号 施 令 更 有 力<br />

在 管 理 他 人 时 , 我 学 会 了 如 果 我 在 要 求 他 们 做 之 前 能 够 说 服 他 们 , 我 就 能 更 加 有<br />

效 地 让 结 果 出 现 。 白 痴 会 利 用 残 暴 的 权 力 , 要 求 某 种 特 殊 的 行 为 —— 这 部 需 要 任 何 技<br />

巧 。 但 是 , 如 果 要 说 服 一 个 聪 明 人 ( 或 者 一 群 人 ), 让 他 们 相 信 他 们 原 本 不 想 去 做 的<br />

事 情 是 正 确 的 、 有 益 的 , 甚 至 是 符 合 他 们 的 兴 趣 的 , 这 样 就 会 更 加 有 利 于 事 情 的 开 展 。<br />

当 他 们 工 作 了 一 段 时 间 , 开 始 质 疑 为 什 么 要 做 这 样 事 时 , 他 们 不 会 责 怪 到 你 。 他 们 会<br />

依 赖 自 己 的 智 慧 , 而 智 慧 收 到 你 的 论 据 的 影 响 , 去 解 释 为 什 么 自 己 花 费 时 间 在 他 们 所<br />

作 的 事 情 上 。<br />

最 后 , 众 人 听 从 于 我 , 是 因 为 他 们 相 信 我 的 能 力 , 对 于 我 的 观 点 总 是 有 合 理 的 理<br />

由 。 他 们 只 提 出 很 少 的 问 题 , 因 为 他 们 相 信 , 我 在 这 样 要 求 他 们 做 之 前 , 已 经 深 思 熟<br />

虑 了 。 他 们 也 并 不 担 心 我 对 他 们 的 利 用 , 因 为 他 们 有 多 次 经 历 表 明 , 我 的 行 为 只 是 为<br />

了 项 目 和 团 队 的 利 益 。 众 人 越 相 信 你 , 你 就 越 容 易 说 服 他 们 。 就 像 和 Bill 那 样 , 随 着<br />

时 间 的 累 积 , 我 花 费 越 来 越 少 的 精 力 去 说 服 他 们 —— 尽 管 那 是 我 和 他 们 建 立 关 系 的 开<br />

端 —— 把 更 多 的 时 间 用 在 做 事 上 。<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 54/85


项 目 管 理<br />

《PHPer》<br />

必 要 时 独 裁 专 制<br />

授 予 型 权 力 确 实 有 它 存 在 的 理 由 。 当 事 情 失 控 时 , 授 予 型 权 力 是 恢 复 秩 序 的 最 快<br />

办 法 。 如 果 会 议 就 要 失 败 , 重 大 承 诺 无 法 达 成 , 或 者 出 现 最 基 本 的 问 题 , 那 么 就 要 拔<br />

剑 了 。 如 果 你 认 为 , 利 用 直 接 的 权 利 是 让 结 果 成 功 的 唯 一 真 实 可 能 , 那 么 不 管 结 果 怎<br />

样 , 都 要 想 尽 办 法 去 使 用 。 要 明 确 、 直 接 地 利 用 你 手 中 的 行 政 权 力 去 推 动 项 目 进 行 。<br />

但 是 , 越 多 地 使 用 这 种 权 力 , 就 越 多 地 掩 饰 组 织 内 部 的 基 本 性 问 题 。 如 果 度 过 这 一 星<br />

期 的 唯 一 方 式 , 就 是 在 会 议 上 大 吼 你 的 方 法 , 或 者 在 小 办 公 室 里 咆 哮 下 令 , 这 样 只 能<br />

说 明 需 要 开 始 审 视 你 的 项 目 远 景 、 组 织 结 构 或 者 你 的 领 导 能 力 了 。<br />

相 信 别 人<br />

当 组 织 变 得 越 来 越 大 , 它 就 越 依 赖 授 予 型 权 力 。 领 导 者 非 常 担 心 如 何 把 这 么 一 群<br />

人 整 合 到 一 起 共 同 工 作 ( 或 者 , 也 许 是 防 止 革 命 ), 有 一 种 观 点 认 为 , 没 有 时 间 让 组<br />

织 中 的 每 个 人 都 参 与 那 些 需 要 利 用 挣 得 型 的 权 力 才 能 开 展 的 讨 论 和 沟 通 。 即 使 是 在 小<br />

团 队 中 , 我 知 道 有 些 领 导 , 也 不 相 信 他 们 有 精 力 或 者 时 间 , 让 那 些 核 心 贡 献 者 都 使 用<br />

这 种 领 导 方 式 。 这 一 问 题 的 解 决 方 式 , 就 是 利 用 另 外 一 种 信 任 , 称 为 授 权 : 相 信 别 人<br />

去 做 决 策 。<br />

权 威 和 信 任 , 通 常 在 各 种 任 务 或 者 知 识 领 域 周 围 累 积 起 来 。Joe 可 能 在 C++ 对 象 方<br />

面 最 有 权 威 ,Sally 也 许 是 解 决 数 据 库 工 作 的 最 合 适 人 选 。 健 康 而 沟 通 良 好 的 团 队 成 员<br />

之 间 彼 此 相 信 , 而 这 种 信 任 足 以 让 他 们 了 解 , 在 哪 些 方 面 谁 更 有 能 力 或 者 有 更 好 观 点 ,<br />

然 后 直 接 去 征 求 那 个 人 的 建 议 , 而 不 用 担 心 遭 遇 尴 尬 或 者 讽 刺 。 这 种 担 心 很 现 实 , 因<br />

为 在 工 程 界 , 当 你 寻 求 协 助 时 , 有 一 种 成 熟 的 消 极 攻 击 型 的 行 为 文 化 ( 那 就 是 , 去 读<br />

那 些 愚 蠢 的 手 册 )。 即 使 在 大 学 里 的 计 算 机 科 学 系 , 倚 靠 自 己 也 被 看 成 是 核 心 能 力 ,<br />

学 生 请 求 同 学 的 帮 助 , 通 常 被 看 成 是 一 种 软 弱 的 表 现 。<br />

从 项 目 的 角 度 来 看 ,Sally 在 数 据 库 设 计 上 的 权 威 , 只 有 应 用 到 项 目 上 时 才 有 用 。<br />

如 果 她 独 自 坐 在 办 公 室 里 , 没 有 人 借 助 她 的 权 威 去 解 决 问 题 , 那 么 Sally 的 权 威 就 被<br />

浪 费 了 , 或 者 最 多 ,Sally 只 限 于 做 自 己 的 任 务 而 已 。 项 目 领 导 者 或 者 经 理 的 重 要 职 责<br />

之 一 , 就 是 为 整 个 团 队 塑 造 授 权 和 共 享 知 识 。 如 果 他 们 做 得 好 , 团 队 的 其 他 人 就 会 很<br />

容 易 随 从 。<br />

传 统 而 言 , 授 权 是 用 来 描 述 把 特 殊 任 务 或 者 责 任 交 出 去 的 行 为 。 我 认 为 , 授 权 的<br />

更 加 有 力 的 形 式 , 是 决 策 或 者 影 响 决 策 的 能 力 被 分 散 。 这 种 情 况 可 能 在 会 议 或 者 小 组<br />

讨 论 中 发 生 。 当 询 问 领 导 或 者 经 理 “ 那 么 , 我 们 如 何 解 决 这 些 问 题 呢 ?”, 他 就 有 机 会<br />

把 权 力 传 给 其 他 人 。“ 好 ,Sally, 你 是 最 优 秀 的 数 据 库 设 计 人 员 。 你 认 为 这 里 我 们 应<br />

该 怎 么 做 ?” 只 要 这 不 是 不 公 平 的 行 为 ( 例 如 , 在 紧 张 的 VP 查 看 会 议 中 , 演 示 失 败 ,<br />

Sally 根 本 没 有 想 到 要 她 去 回 答 任 何 问 题 ), 就 能 建 立 协 作 的 基 调 。 众 人 若 能 大 方 地 认<br />

可 他 人 的 专 长 , 他 们 就 会 恰 当 地 服 从 于 权 威 。 当 然 , 对 于 项 目 经 理 来 说 , 就 没 有 什 么<br />

风 险 了 。 如 果 Sally 的 建 议 不 好 , 大 家 可 以 继 续 讨 论 。 但 是 , 倘 若 没 有 那 第 一 个 提 问 ,<br />

讨 论 就 根 本 不 会 发 生 。<br />

当 然 , 授 权 也 可 以 扩 展 到 明 确 地 把 权 力 交 付 出 去 。 公 开 宣 布 , 某 块 工 作 或 者 功 能<br />

将 由 某 人 来 负 责 , 经 理 把 他 的 权 力 交 给 那 个 人 。 授 权 要 做 得 有 足 够 的 透 明 度 , 让 那 些<br />

需 要 看 见 的 人 都 能 真 正 看 到 , 这 一 点 非 常 重 要 。 每 一 次 , 当 我 把 责 任 转 交 给 替 我 工 作<br />

的 人 时 , 我 确 保 联 系 每 一 个 有 关 联 的 程 序 员 或 测 试 员 , 这 样 他 们 就 会 明 白 , 我 对 这 项<br />

工 作 所 掌 握 的 权 力 和 职 权 将 转 交 给 其 他 人 。 当 然 , 有 时 , 人 们 不 愿 看 到 有 事 要 授 权 ,<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 55/85


项 目 管 理<br />

《PHPer》<br />

但 是 , 这 是 领 导 的 工 作 , 你 要 用 你 的 权 力 去 强 迫 执 行 。<br />

John 是 我 团 队 中 的 一 位 项 目 经 理 , 他 已 经 准 备 好 承 担 更 多 的 责 任 。 因 此 , 当 需 要<br />

重 新 组 织 团 队 工 作 任 务 分 配 的 时 机 到 来 时 , 我 就 可 以 把 握 之 前 一 直 负 责 的 一 块 工 作 交<br />

给 他 。 通 过 与 John 和 Steve( 该 领 域 的 一 名 程 序 员 ) 适 当 的 讨 论 后 , 我 把 职 责 交 给 John。<br />

一 周 后 ,Steve 来 到 我 的 办 公 室 , 请 求 该 领 域 的 PM 帮 忙 。 当 我 听 他 讲 述 时 , 我 试 图 找<br />

出 他 和 我 谈 , 而 不 是 和 John 谈 的 原 因 。 我 打 断 他 道 :“Steve, 你 为 什 么 要 和 我 谈 这 件<br />

事 呢 ?”“ 哦 ,Scott, 你 以 前 负 责 这 件 事 , 不 是 吗 ?”“ 没 错 ,Steve, 不 过 现 在 John 负<br />

责 它 。 你 和 他 谈 过 了 吗 ?” 他 耸 耸 肩 。“Steve, 去 和 John 谈 吧 ,” 我 说 道 。“ 他 很 精 明 ,<br />

很 不 错 , 相 信 他 吧 。” 过 了 几 天 ,Steve 又 回 来 了 , 我 们 又 做 了 一 次 更 短 版 本 版 的 相 同<br />

对 话 。 自 那 以 后 , 我 再 也 没 有 听 到 Steve 说 些 什 么 ( 至 少 是 关 于 这 项 工 作 )。<br />

John 可 能 永 远 也 不 知 道 这 件 事 情 , 也 没 有 必 要 知 道 。Steve 宁 愿 和 我 一 起 工 作 , 这<br />

是 出 于 某 种 原 因 的 , 他 希 望 继 续 保 持 我 们 之 间 的 关 系 , 尽 管 负 责 人 已 经 改 变 。 但 是 ,<br />

因 为 授 权 , 我 必 须 让 自 己 置 身 于 讨 论 之 外 。 我 或 许 可 以 亲 自 回 答 Steve 的 问 题 , 也 可<br />

能 我 很 愿 意 这 么 做 , 但 是 , 那 样 , 我 会 违 背 自 己 所 做 的 授 权 决 定 。 除 非 我 有 理 由 参 与<br />

到 那 个 项 目 领 域 , 否 则 , 我 就 得 信 任 John 和 Steve 能 够 做 好 他 们 的 工 作 , 包 括 运 用 Steve<br />

对 我 的 信 任 , 说 服 他 相 信 John。<br />

很 多 经 理 在 授 权 上 , 都 遇 到 麻 烦 。 因 为 有 能 力 自 己 把 事 情 做 好 , 所 以 他 们 的 资 历<br />

不 断 提 升 , 但 是 , 领 导 需 要 各 种 技 能 的 平 衡 , 而 这 种 平 衡 和 作 为 一 个 独 立 的 贡 献 者 所<br />

需 的 平 衡 不 同 ( 请 参 阅 第 1 章 中 “ 项 目 经 理 的 平 衡 之 道 ” 部 分 )。 这 些 经 理 往 往 因 为 害 怕<br />

没 有 足 够 的 掌 控 能 力 而 退 缩 。 当 然 , 这 是 一 个 陷 阱 , 因 为 如 果 害 怕 驱 使 着 决 策 , 那 他<br />

们 就 永 远 也 学 不 会 信 任 别 人 , 没 有 信 任 , 就 没 有 领 导 力 。<br />

有 时 , 解 决 办 法 就 是 妥 协 。 在 授 权 时 , 经 理 必 须 和 团 队 成 员 讨 论 , 授 权 要 考 虑 哪<br />

些 事 情 。(“John, 我 担 心 Steve。 每 次 评 估 时 , 他 都 落 后 。 所 以 , 要 格 外 注 意 这 一 点 ,<br />

好 吗 ?”) 对 授 权 任 务 设 定 期 望 后 , 领 导 可 以 传 授 一 些 经 验 和 指 引 , 这 样 可 能 增 加 成<br />

功 的 机 会 。<br />

信 任 是 灾 祸 的 保 险<br />

就 像 我 们 前 面 所 谈 到 的 , 所 有 的 项 目 都 会 出 错 。 竞 争 对 手 不 会 按 照 你 所 期 望 他 们<br />

做 的 那 样 去 做 事 情 ( 那 是 他 们 的 工 作 ), 技 术 不 断 发 展 变 化 , 重 要 任 务 会 改 变 想 法 。<br />

作 为 一 个 项 目 经 理 , 可 以 明 确 的 是 , 事 情 总 会 出 乎 意 料 或 者 无 法 解 决 的 发 生 。 在 艰 难<br />

或 者 不 确 定 的 时 候 , 你 希 望 团 队 或 者 同 事 能 够 依 赖 你 , 并 且 彼 此 信 任 。<br />

如 果 信 任 已 经 培 养 起 来 , 并 且 随 时 间 茁 壮 成 长 , 人 们 有 合 作 决 策 的 经 验 ( 而 不 是<br />

不 顾 他 人 ), 那 么 项 目 对 于 面 对 问 题 的 解 决 能 力 就 会 很 强 。 当 众 人 相 信 团 队 时 , 他 们<br />

就 可 以 鼓 起 各 种 信 心 和 耐 心 , 而 这 是 通 过 其 它 方 法 无 法 获 得 的 。 就 像 散 兵 坑 里 的 士 兵<br />

那 样 , 每 个 人 都 可 以 依 赖 在 他 背 后 的 人 , 让 他 们 可 以 把 更 多 的 精 力 放 在 面 前 的 任 务 上 。<br />

当 团 队 的 成 员 能 够 彼 此 信 任 , 就 会 给 项 目 经 理 赢 得 时 间 , 去 专 注 于 解 决 手 边 的 问 题 ,<br />

而 不 是 试 着 让 走 廊 里 惊 慌 失 措 或 者 沮 丧 的 员 工 的 情 绪 稳 定 下 来 。 优 势 , 领 导 者 需 要 明<br />

确 请 求 这 种 支 持 。 他 要 承 认 问 题 , 并 且 征 求 , 而 不 是 命 令 他 们 给 予 支 持 , 以 此 来 表 明<br />

他 想 从 团 队 那 里 获 得 的 尊 敬 ( 大 叫 “ 现 在 支 持 我 ” 是 不 起 作 用 的 )。 总 而 言 之 , 是 人 与<br />

人 之 间 的 关 系 让 他 们 度 过 艰 难 时 光 : 而 不 是 薪 水 , 也 不 是 他 们 所 使 用 的 技 术 , 当 然 也<br />

不 是 个 人 拥 有 多 大 的 权 力 , 或 者 没 有 什 么 权 力 。<br />

因 此 , 聪 明 的 领 导 , 就 像 一 艘 轮 船 的 船 长 一 样 , 知 道 看 不 见 的 风 暴 和 危 险 潜 藏 在<br />

大 海 深 处 , 他 会 让 自 己 和 船 员 尽 自 己 所 能 做 好 准 备 , 去 面 对 他 所 不 能 准 备 的 事 情 。 如<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 56/85


项 目 管 理<br />

《PHPer》<br />

果 不 确 定 是 一 种 必 然 , 那 么 项 目 经 理 的 最 佳 投 资 , 就 是 在 他 和 每 一 位 项 目 贡 献 者 之 间<br />

建 立 起 强 大 的 信 任 网 络 。 对 于 那 些 较 大 的 团 队 而 言 , 需 要 花 更 多 的 时 间 , 在 那 些 对 项<br />

目 最 重 要 或 者 最 可 能 在 压 力 下 失 败 的 人 际 关 系 上 , 建 立 信 任 感 。 虽 然 规 范 、 远 景 文 件 ,<br />

或 者 其 他 工 作 , 确 实 能 够 帮 助 把 众 人 联 结 起 来 , 但 是 真 正 有 力 量 的 是 那 些 东 西 背 后 所<br />

隐 藏 的 人 与 人 之 间 的 信 任 。<br />

榜 样 、 问 题 和 冲 突<br />

已 所 不 欲 , 勿 施 于 人 , 这 条 金 科 玉 律 (golden rule), 也 适 用 于 经 理 人 。 只 有 领 导<br />

自 己 遵 守 命 令 , 底 下 的 人 才 会 服 从 命 令 。 人 是 社 会 性 的 动 物 , 我 们 在 生 活 中 学 习 行 为<br />

举 止 , 尤 其 是 从 其 他 的 榜 样 身 上 学 习 。 通 常 , 看 到 那 些 我 们 尊 重 或 者 崇 拜 的 人 做 某 些<br />

事 , 就 开 始 试 着 , 有 意 识 或 者 无 意 识 地 , 去 模 仿 那 种 行 为 举 止 , 这 种 学 习 往 往 具 有 最<br />

好 的 效 果 。 谈 到 信 任 , 项 目 领 导 者 要 想 让 共 事 者 也 有 这 样 的 行 为 , 就 要 首 先 证 实 这 种<br />

行 为 。Michael Jordan 除 了 具 有 品 质 外 , 还 具 有 高 度 敬 业 的 好 名 声 。 即 使 是 NBA 中 ,<br />

薪 水 最 丰 厚 , 知 名 度 最 高 的 篮 球 球 员 , 他 的 工 作 努 力 程 度 也 鲜 有 人 及 。 这 就 , 其 他 次<br />

要 球 员 就 不 可 能 请 求 停 止 练 习 去 休 息 , 也 不 可 能 少 花 点 时 间 呆 在 体 育 馆 里 。 领 导 树 立<br />

了 一 个 榜 样 , 其 他 人 都 得 照 着 做 。<br />

职 业 道 德 放 一 旁 , 这 条 金 科 玉 律 对 领 导 者 而 言 , 就 是 他 们 相 信 自 己 的 判 断 , 足 以<br />

遵 循 其 他 人 也 会 跟 着 遵 循 的 相 同 的 原 则 ( 请 参 阅 本 章 后 面 的 “ 相 信 自 己 ( 自 我 依 靠 )”<br />

那 部 分 )。 这 样 做 , 就 表 示 允 许 其 他 人 、 同 事 或 者 下 属 , 对 领 导 者 的 判 断 或 者 行 为 ,<br />

提 出 质 疑 或 挑 战 。 如 果 有 人 被 授 予 权 力 , 就 需 要 某 种 反 馈 来 挑 战 它 ( 换 言 之 , 谁 被 允<br />

许 说 国 王 没 有 穿 衣 服 ?)。 优 秀 的 领 导 充 分 信 任 他 的 队 友 , 以 求 对 他 的 行 为 和 表 现 做<br />

出 反 馈 ( 有 时 , 也 许 私 下 要 求 )。 当 然 , 领 导 者 没 有 义 务 对 反 馈 采 取 行 动 或 者 评 论 什<br />

么 , 但 是 , 如 果 没 有 健 康 和 安 全 的 途 径 可 以 把 这 些 信 息 传 达 到 项 目 经 理 那 里 , 我 们 就<br />

很 难 想 象 项 目 会 成 功 了 。<br />

领 导 者 要 规 范 信 息 反 馈 程 序<br />

人 们 对 于 给 有 权 威 的 人 物 提 供 反 馈 信 息 时 , 都 非 常 犹 豫 。 作 为 经 理 , 我 有 个 习 惯 ,<br />

在 每 周 一 对 一 的 会 面 时 , 我 会 询 问 那 些 向 我 汇 报 的 人 , 他 们 是 否 希 望 我 仔 细 考 虑 一 下 ,<br />

某 些 有 关 我 的 工 作 、 行 为 或 者 执 行 的 事 情 。 对 此 , 他 们 很 少 说 些 什 么 , 但 是 我 知 道 ,<br />

这 不 是 因 为 我 是 一 个 完 美 的 经 理 ( 没 有 完 美 的 经 理 )。 我 发 现 唯 一 的 解 决 方 法 , 就 是<br />

信 任 和 时 间 。 我 必 须 不 断 地 建 立 他 们 所 需 的 信 心 , 使 他 们 非 常 自 然 地 批 评 我 的 行 为<br />

—— 他 们 无 需 担 心 我 会 变 得 防 范 心 强 , 或 者 因 为 他 们 的 批 评 而 受 到 斥 责 。 后 来 , 他 们<br />

终 于 可 以 提 出 少 量 的 批 评 , 如 果 我 掌 握 的 好 , 下 一 次 , 他 们 就 会 提 出 更 多 。<br />

然 而 , 一 旦 建 立 起 和 他 们 之 间 的 一 个 信 息 反 馈 圈 , 我 就 明 白 , 他 们 的 观 点 非 常 有<br />

助 于 我 成 为 一 名 更 加 优 秀 的 经 理 , 这 些 信 息 远 比 我 从 老 板 那 里 得 到 的 反 馈 信 息 更 加 有<br />

效 。 当 然 , 我 不 是 和 每 个 人 都 保 持 这 种 关 系 , 但 是 大 多 数 人 , 迟 早 都 会 回 答 我 的 问 题 ,<br />

提 出 有 效 的 反 馈 信 息 。 建 议 以 不 同 的 方 式 开 会 , 对 我 的 决 策 提 出 疑 议 , 或 者 其 它 建 议 ,<br />

这 些 都 能 保 证 接 下 来 的 讨 论 , 能 够 使 我 们 双 方 对 事 物 本 身 到 底 怎 样 的 判 断 更 加 准 确 。<br />

每 次 我 参 与 讨 论 时 , 我 都 试 着 揭 示 , 批 评 某 种 观 点 和 批 评 提 出 某 种 观 点 的 人 之 间 的 差<br />

异<br />

2 。 某 A 不 同 意 某 B 所 说 的 事 , 并 不 代 表 某 A 在 评 判 某 B 这 个 人 。 我 希 望 我 的 团 队<br />

能 够 感 到 , 他 们 彼 此 信 任 的 程 度 足 以 让 他 们 想 什 么 就 说 什 么 , 就 是 公 开 的 反 对 , 也 不<br />

需 要 道 歉 。 幽 默 感 非 常 有 助 于 创 造 这 样 的 氛 围 , 领 导 者 要 说 明 , 什 么 时 候 讽 刺 或 者 挖<br />

苦 是 不 恰 当 的 , 也 许 应 该 把 自 己 当 成 笑 话 的 靶 子 。 但 是 , 我 要 强 调 的 是 , 领 导 要 自 己<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 57/85


项 目 管 理<br />

《PHPer》<br />

示 范 这 种 行 为 , 控 制 好 那 些 太 过 火 的 人 , 同 时 , 把 那 些 斗 争 着 想 要 加 入 的 人 拉 进 来 。<br />

注 释 2: 请 到 以 下 网<br />

站 http://www.scottberkun.com/essays/35-how-to-give-and-receive-criticism/, 参 阅 “ 评 批 和<br />

接 受 批 评 (How to give and receive criticism)”<br />

这 样 , 也 可 能 导 致 冲 突 和 意 见 不 一 致 。 如 果 糟 糕 的 事 情 出 现 时 , 他 们 只 是 安 静 地<br />

坐 在 那 里 , 那 么 无 论 是 授 予 型 权 力 , 还 是 挣 得 型 权 力 都 无 法 帮 上 忙 。 除 了 打 断 愚 蠢 的<br />

争 论 , 和 解 除 那 些 乱 发 言 人 的 发 言 权 外 , 权 力 就 没 有 什 么 更 好 的 用 法 了 。 当 意 见 不 同<br />

转 变 成 人 身 攻 击 , 或 者 利 用 虚 假 的 论 据 来 证 明 决 策 的 正 确 , 就 要 有 人 必 须 打 断 和 提 出<br />

反 对 。 绝 不 能 容 忍 这 样 的 行 为 发 生 , 每 个 人 都 要 同 时 得 到 相 同 的 信 息 : 不 要 再 试 这 样<br />

的 借 口 , 因 为 我 们 这 里 不 欢 迎 这 些 。<br />

当 然 , 这 里 遵 循 另 一 天 金 科 玉 律 , 真 正 的 领 导 必 须 做 好 准 备 , 如 果 他 试 着 使 用 虚<br />

假 论 据 , 那 就 等 着 别 人 可 能 ( 或 者 必 然 ) 对 他 的 挑 战 吧 。 最 优 秀 的 领 导 , 就 是 那 些 可<br />

以 承 受 来 自 忠 于 理 性 准 则 的 团 队 的 压 力 , 而 这 些 准 则 甚 至 无 惧 于 对 领 导 的 行 为 提 出 质<br />

疑 。<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 58/85


高 级 应 用 :<br />

《PHPer》<br />

高 级 应 用<br />

UCHOME2.0 登 录 验 证 机 制 分 析<br />

蜗 牛<br />

Uchome2.0 采 用 cookie+ 数 据 库 的 方 式 来 进 行 用 户 登 录 验 证 的<br />

1 登 录<br />

A: 用 户 填 好 登 录 表 单 之 后 数 据 被 提 交 给 source\do_login.php 处 理<br />

B: 在 do_login.php 中 下 面 这 些 语 句 接 收 传 递 来 的 用 户 名 密 码 与 cookie 生 效 时 间<br />

代 码 片 段<br />

$password = $_POST['password'];<br />

$username = trim($_POST['username']);<br />

$cookietime = intval($_POST['cookietime']);<br />

C: 然 后 验 证 用 户 提 交 来 的 用 户 名 以 及 密 码 的 正 确 性 , 不 正 确 则 跳 转 并 提 示 登 录<br />

失 败<br />

代 码 片 段<br />

// 同 步 获 取 用 户 源<br />

if(!$passport = getpassport($username,$password)){<br />

showmessage('login_failure_please_re_login','do.php?ac='.$_SCONFIG['login_action']);<br />

}<br />

注 意 : 这 里 验 证 用 户 名 与 密 码 的 正 确 性 是 通 过 uc_client 在 Ucenter 用 户 中 心 数 据<br />

库 中 查 询 的<br />

D: 若 验 证 通 过 之 后 , 再 将 获 取 到 得 用 户 账 户 信 息 赋 给 setarr 变 量 数 组<br />

代 码 片 段<br />

$setarr = array(<br />

'uid' => $passport['uid'],<br />

'username' => addslashes($passport['username']),<br />

'password' => md5("$passport[uid] | $_SGLOBAL[timestamp]")// 本 地 密 码 随 机 生 成<br />

);<br />

E: 查 询 uchome 的 数 据 库 看 该 用 户 信 息 是 否 存 在 于 Uchome 数 据 库 中 , 不 存 在 的<br />

话 , 则 将 从 Ucenter 中 查 询 到 的 用 户 数 据 写 入 到 uchome 的 member 表 中 , 存 在 则 将<br />

member 中 的 密 码 替 换 掉 从 Ucenter 中 查 询 出 来 的 密 码 , 存 入 setarr 变 量 数 组 中 。<br />

代 码 片 段<br />

$query = $_SGLOBAL['db']->query("SELECT password FROM".tname('member')."WHERE uid<br />

= '$setarr[uid]'");<br />

if($value = $_SGLOBAL['db'] -> fetch_array($Jquery)){<br />

$setarr['password'] = addslashes($value['password']);<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 59/85


高 级 应 用 :<br />

《PHPer》<br />

}else{<br />

// 更 新 本 地 用 户 库<br />

inserttable('member',$setarr,0,true);<br />

}<br />

F: 将 用 户 登 录 信 息 写 入 到 Uchome 的 session 表 中<br />

代 码 片 段<br />

insertsession($setarr);<br />

Session 表 的 数 据 如 下<br />

Insertsession 函 数 在 source\function_space.php 中 定 义<br />

其 主 要 功 能 为 :<br />

a) 清 除 session 表 中 的 某 个 用 户 的 记 录<br />

b) 获 得 用 户 的 IP 以 及 是 否 使 用 隐 身 道 具<br />

c) 将 setarr 变 量 数 组 中 的 数 据 插 入 到 session 表 中 。<br />

d) 更 新 统 计 数 数 据 等<br />

G: 将 用 户 名 与 密 码 加 密 写 入 cookie 中<br />

代 码 片 段<br />

ssetcookie('auth',authcode("$setarr[password]\t$setarr[uid]",'ENCODE'),$cookietime);<br />

ssetcookie('loginuser',$passport['username'],31536000);<br />

2 验 证<br />

判 断 当 前 用 户 登 录 状 态 是 通 过 source\function_common.php 中 的 checkauth 函 数 实<br />

现 的 , 下 面 就 来 分 析 这 个 函 数<br />

A: 判 断 $_cookie[auth] 是 否 存 在 , 若 不 存 在 则 不 进 行 任 何 处 理 , 并 清 除 所 有 cookie<br />

代 码 片 段<br />

if($_SCOOKIE['auth'])<br />

若 存 在 则 :<br />

B: 从 cookie 中 反 解 出 用 户 名 跟 密 码 信 息<br />

代 码 片 段<br />

@list($password,$uid) = explode("\t",authcode($_SCOOKIE['auth'],'DECODE'));<br />

$_SGLOBAL['supe_uid'] = intval($uid);<br />

注 意 : 这 里 说 的 密 码 以 及 上 面 说 的 将 密 码 加 密 进 cookie 中 的 密 码 并 不 是 用 户 的 真<br />

实 密 码 , 而 是 经 过 md5 双 重 加 密 并 且 salt 处 理 后 的 密 码<br />

C: 从 session 数 据 表 中 取 出 用 户 ID 为 $_SGLOBAL[supe_uid] 的 用 户 信 息 , 若 该 记<br />

录 存 在 则 执 行 下 面 的 操 作 , 否 则 执 行 D 操 作 ( 直 接 查 询 用 户 数 据 库 )<br />

代 码 片 段<br />

$query = $_SGLOBAL['db'] -> query("SELECT * FROM".tname('session')."WHERE uid='$SGL<br />

OBAL[supe_uid]'");<br />

if($member = $_SGLOBAL['db'] -> fetch_array($query))<br />

如 果 取 出 来 的 密 码 与 cookie 中 的 密 码 相 等 , 那 么 判 定 为 登 录 成 功 将 数 据 写 入 到<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 60/85


高 级 应 用 :<br />

《PHPer》<br />

$_SGLOBAL['session'] 数 组<br />

代 码 片 段<br />

if($member['password'] == $password){<br />

$_SGLOBAL['supe_username'] = addslashes($member['username']);<br />

$_SGLOBAL['session'] = $member;<br />

}<br />

否 则 判 定 为 登 录 失 败 , 清 除 所 有 cookie<br />

D: 在 C 步 时 , 若 在 session 表 中 没 有 该 用 户 的 数 据 则 , 在 用 户 数 据 表 member 中<br />

查 询 该 ID 得 用 户 数 据 , 看 cookie 中 的 密 码 是 否 与 数 据 库 中 的 密 码 一 样 , 如 果 一 样 则<br />

登 录 成 功 , 并 将 用 户 数 据 写 入 到 session 表 中 保 持 用 户 的 登 录 状 态 , 否 则 登 录 失 败<br />

代 码 片 段<br />

$query = $_SGLBAL['db'] -> query("SELECT * FROM ".tname('member')." WHERE uid='$_SG<br />

LOBAL[supe_uid]'");<br />

if($member = $_SGLOBAL['db'] -> fetch_array($query)){<br />

if($member['password'] == $password){<br />

$_SGLOBAL['supe_username'] = addslashes($member['username']);<br />

$session = array('uid'=>$_SGLOBAL['supe_uid'],'username'=>$_SGLOBAL['supe_username<br />

'],'password');<br />

include_once($session);// 登 录<br />

}else{<br />

$_SBLOBAL['supe_uid'] = 0;<br />

}<br />

}else{<br />

$_SGLOBAL['supe_uid'] = 0;<br />

}<br />

上 面 无 论 是 用 session 表 来 判 定 登 录 状 态 还 是 用 member 表 来 判 定 登 录 状 态 , 都 会<br />

影 响 到 一 个 变 量 , 那 就 是 $_SGLOBAL['supe_uid'], 在 程 序 处 理 的 时 候 , 用 户 登 录 与 否<br />

一 般 要 用 到 得 变 量 就 是 $_SGLOBAL['supe_uid']。<br />

例 如 在 space.php 文 件 中 有 个 这 样 的 语 句<br />

代 码 片 段<br />

if(empty($isinvite) && empty($_SCONFIG['networkpublic'])){<br />

checklogin();// 需 要 登 录<br />

}<br />

此 语 句 中 的 checklogin 函 数 就 是 检 测 用 户 是 否 需 要 登 录<br />

代 码 片 段<br />

function checklogin(){<br />

global $)SGLOBAL,$_SCONFIG;<br />

if(empty($_SGLOBAL['supe_uid'])){<br />

ssetcookie('_refer',rawurlencode($_SERVER['REQUEST_URI']));<br />

showmessage('to_login','do.php?ac='.$_SCONFIG['login_action']);<br />

}<br />

}<br />

这 个 函 数 就 是 看 $_SGLOBAL['supe_uid'] 是 否 存 在 , 存 在 的 话 就 以 这 个 ID 的 身 份<br />

去 操 作 , 不 存 在 就 说 明 用 户 登 录 不 成 功 需 要 用 户 登 录 才 能 操 作 。<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 61/85


高 级 应 用 :<br />

《PHPer》<br />

UCHOME2.0 权 限 机 制 分 析<br />

蜗 牛<br />

1 隐 私 机 制<br />

全 站 用 户 默 认 隐 私<br />

A: 管 理 员 在 后 台 设 置 全 站 默 认 的 隐 私 规 则 , 数 据 被 储 存 在 config 表 中 , 以 如 下 方<br />

式 储 存<br />

B: 更 新 config 缓 存 文 件 data\data_config.php 将 数 据 存 于 $_SCONFIG[privacy][view]<br />

数 组 中<br />

C: 在 space.php 入 口 文 件 里 通 过 ckprivacy($type, $feedmode=0) 函 数 来 检 查 是 否 具<br />

有 某 权 限<br />

有 权 限 则 返 回 1 否 则 返 回 0<br />

D: 若 无 权 限 查 看 则 提 示 加 为 好 友 才 能 观 看 , 并 终 止 程 序 。 代 码 如 下<br />

代 码 片 段<br />

if(!ckprivacy($do)){<br />

include template('space_privacy');<br />

exit();<br />

}<br />

用 户 自 定 义 隐 私<br />

A: 用 户 在 自 己 的 控 制 面 板 设 置 隐 私 规 则 , 数 据 被 储 存 在 spacefield 表 中 , 以 如 下<br />

方 式 储 存<br />

B: 在 space.php 入 口 文 件 中 通 过 getspace 函 数 获 取 用 户 spacefield 表 中 的 数 据 存<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 62/85


高 级 应 用 :<br />

《PHPer》<br />

储 在 $spaces 数 组 中<br />

C: 通 过 函 数 ckprivacy 查 看 用 户 是 否 有 权 限 查 看 数 据 , 具 体 跟 全 站 用 户 默 认 隐 私<br />

C 处 相 同<br />

2 用 户 权 限 组<br />

A: 管 理 员 在 后 台 设 置 各 用 户 组 的 权 限<br />

B: 在 admin\admincp_usergroup.php 文 件 中 通 过<br />

代 码 片 段<br />

updatetable('usergroup',$setarr,array('gid'=>$thevalue['gid']));<br />

语 句 将 用 户 组 配 置 文 件 更 新 至 usergroup 表 中<br />

C: 通 过 usergroup_cache 函 数 来 更 新 缓 存 文 件 , 根 据 用 户 组 ID 生 成 不 同 的 缓 存<br />

文 件<br />

其 中 data\data_usergroup.php 文 件 为 所 有 用 户 组 名 称 与 ID 数 组 , 其 余 的 为 其 序 列<br />

号 对 应 的 用 户 组 ID 的 权 限 设 置 数 组 : 权 限 查 询 方 法 为<br />

$_SGLOBAL['usergroup'][1][allowblog]<br />

D: 在 需 要 检 查 权 限 的 各 个 文 件 中 用 checkperm( 权 限 名 ) 分 别 进 行 权 限 的 检 查 。 而<br />

不 是 集 中 在 入 口 处 进 行 权 限 检 查<br />

实 名 认 证<br />

A: 在 后 台 设 置 未 经 实 名 认 证 的 用 户 权 限<br />

B: 将 数 据 写 入 config 表 中 以 var=>datavalue 键 值 对 的 形 式 存 储<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 63/85


高 级 应 用 :<br />

《PHPer》<br />

C: 生 成 配 置 缓 存 文 件 于 \data\data_config.php 的 数 组 中 , 调 用 方 法 :<br />

$_SCONFIG[name_allowfriend]<br />

D: 在 需 要 实 名 认 证 权 限 检 查 的 文 件 中 调 用 该 函 数 查 询 是 否 具 有 某 权 限<br />

ckrealname(’blog’);<br />

函 数 有 返 回 值 , 但 是 在 返 回 之 前 就 已 经 跳 转 了 , 提 示 用 户 没 有 某 个 权 限<br />

视 频 认 证 : 跟 实 名 认 证 机 制 是 一 样 的 , 只 不 过 权 限 检 查 函 数 为 ckvideophoto(’blog’);<br />

指 定 文 章 ( 图 片 ) 等 的 浏 览 权 限 ( 这 里 以 文 章 浏 览 权 限 为 例 )<br />

A: 用 户 发 布 文 章 的 时 候 指 定 是 好 友 可 见 还 是 密 码 查 看<br />

B: 数 据 传 递 给 文 章 发 布 函 数<br />

C: 文 章 发 布 函 数 , 将 数 据 写 入 文 章 表 blog 中 ,<br />

D: 用 户 查 看 文 章 的 时 候 , 查 询 出 该 文 章 的 隐 私 信 息 , 然 后 在 source\space_blog.php<br />

文 件 中 通 过 下 列 语 句 来 检 查 是 否 需 要 密 码 或 者 是 否 具 有 权 限 。<br />

代 码 片 段<br />

// 检 查 好 友 权 限<br />

if(!ckfriend($blog['uid'],$blog['friend'],$blog['target_ids'])){<br />

// 没 有 权 限<br />

include template('space_privacy');<br />

exit();<br />

}elseif(!$space['self'] && $blog['friend'] == 4){<br />

// 密 码 输 入 问 题<br />

$cookiename = "view_pwd_blog_$blog[blogid]";<br />

$cookievalue = empty($_SCOOKIE[$cookiename])?'':$_SCOOKIE[$cookiename];<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 64/85


高 级 应 用 :<br />

《PHPer》<br />

if($cookievalue != md5(md5($blog['password']))){<br />

$invalue = $blog;<br />

include template('do_inputpwd');<br />

作 者 博 客 :http://snail.comsing.com/<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 65/85


安 全 优 化 :<br />

《PHPer》<br />

安 全 优 化<br />

3 如 何 执 行 安 全 检 查<br />

Windows 安 全 ( 二 )<br />

机 械 工 业 出 版 社<br />

为 了 在 Windows 各 个 组 件 之 间 实 现 一 致 的 访 问 , 在 内 核 中 实 现 了 一 组 安 全 系 统 函<br />

数 , 这 些 函 数 的 原 型 定 义 在 头 文 件 ntddk.h 中 。 核 心 函 数 之 一 就 是 内 核 函 数<br />

SeAccessCheck, 用 户 态 组 件 可 以 通 过 advapi32!AccessCheck 来 调 用 这 个 函 数 。<br />

SeAccessCheck 的 参 数 分 别 为 安 全 描 述 符 、 访 问 令 牌 ( 在 参 数 SubjectSecurityContext<br />

中 ) 以 及 所 请 求 的 访 问 。<br />

BOOLEAN SeAccessCheck (<br />

IN PSECURITY_DESCRIPTOR SecurityDescriptor,<br />

IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,<br />

IN BOOLEAN SubjectContextLocked,<br />

IN ACCESS_MASK DesiredAccess,<br />

IN ACCESS_MASK PreviouslyGrantedAccess,<br />

OUT PPRIVILEGE_SET *Privileges OPTIONAL,<br />

IN PGENERIC_MAPPING GenericMapping,<br />

IN KPROCESSOR_MODE AccessMode,<br />

OUT PACCESS_MASK GrantedAccess,<br />

OUT PNTSTATUS AccessStatus);<br />

在 调 试 器 中 , 通 过 查 看 advapi32!AccessCheck 的 返 回 值 以 及 出 口 参 数 中 的 值 , 可<br />

以 很 容 易 找 出 被 用 户 态 代 码 准 许 的 访 问 。 由 内 核 态 代 码 准 许 的 访 问 可 以 通 过 分 析 内 核<br />

系 统 函 数 SeAccessCheck 的 返 回 值 来 查 看 。 如 果 要 对 由 于 在 各 种 文 件 和 注 册 表 项 上 不<br />

正 确 的 安 全 设 置 所 导 致 的 访 问 问 题 进 行 分 析 , 我 们 还 可 以 使 用 一 些 跟 踪 工 具 , 例 如 进<br />

程 监 视 器 (Process Monitor), 这 是 由 Microsoft 提 供 的 一 个 免 费 工 具 。<br />

4 在 客 户 端 / 服 务 器 程 序 中 传 播 标 识<br />

大 多 数 程 序 在 所 有 的 操 作 中 都 是 使 用 主 访 问 令 牌 , 而 客 户 端 / 服 务 器 程 序 则 经 常 使<br />

用 模 拟 访 问 令 牌 。 在 这 种 方 式 中 , 服 务 器 是 根 据 从 客 户 端 获 得 的 模 拟 访 问 令 牌 来 执 行<br />

客 户 请 求 。 模 拟 访 问 令 牌 是 通 过 进 程 间 通 信 机 制 来 传 播 的 , 进 程 间 通 信 通 常 用 于 支 撑<br />

客 户 端 / 服 务 器 之 间 的 会 话 。 身 份 模 拟 函 数 ( 例 如 ntdll!NtImpersonateClientOfPort 包 含<br />

在 LPC 通 信 机 制 中 ;rpcrt4! RpcImper sonateClient 是 由 RPC 实 现 的 ;<br />

advapi32!ImpersonateNamedPipeClient 是 由 文 件 系 统 的 重 定 向 器 实 现 的 ) 通 过 客 户 访 问<br />

令 牌 来 模 拟 主 调 线 程 的 身 份 。 在 某 些 情 况 中 , 在 服 务 器 端 拥 有 用 户 证 书 , 尤 其 在 基 于<br />

Web 的 程 序 中 , 并 且 服 务 器 将 通 过 直 接 调 用 advapi32!LogonUser(Ex)W 来 创 建 一 个 访<br />

问 令 牌 。<br />

每 种 协 议 都 通 过 各 自 的 私 有 机 制 来 传 播 客 户 标 识 。 当 客 户 和 服 务 器 分 别 驻 留 在 不<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 66/85


安 全 优 化 :<br />

《PHPer》<br />

同 系 统 上 时 , 客 户 端 / 服 务 器 程 序 可 以 通 过 安 全 服 务 器 提 供 者 接 口 (Security Server<br />

Provider Interface,SSPI) 来 传 播 安 全 信 息 。<br />

rpcrt4!RpcImpersonateClient 是 一 个 特 殊 的 “ 代 理 ” 函 数 , 这 个 函 数 将 身 份 模 拟 请<br />

求 委 托 给 RPC 使 用 的 底 层 通 信 机 制 。 当 RPC 被 用 于 在 同 一 系 统 的 两 个 进 程 间 进 行 通<br />

信 时 , 将 调 用 LPC 函 数 来 实 现 通 信 。 当 客 户 端 与 服 务 器 在 不 同 的 系 统 上 运 行 时 , 在 需<br />

要 传 输 安 全 性 的 远 程 调 用 中 ,RPC 将 使 用 文 件 系 统 的 重 定 向 功 能 ; 否 则 , 在 其 他 大 多<br />

数 情 况 中 将 使 用 SSPI。<br />

4.1 远 程 认 证 与 安 全 支 持 提 供 者 接 口<br />

客 户 端 必 须 将 一 组 证 书 呈 交 给 服 务 器 。 这 些 证 书 用 于 表 示 服 务 器 系 统 中 的 客 户 主<br />

体 。SSPI 将 通 过 一 系 列 的 安 全 提 供 者 来 认 证 远 程 证 书 , 这 些 提 供 者 包 括 NTLM 认 证 、<br />

Kerberos 基 于 域 的 认 证 或 者 客 户 证 书 认 证 。<br />

为 了 认 证 到 远 程 系 统 , 客 户 将 一 组 证 书 传 递 给<br />

secur32!InitializeSecurityContextW 以 启 动 调 用 序 列 。 在 这 个 函 数 调 用 中 获 得 的 不<br />

透 明 数 据 块 将 被 发 送 到 服 务 器 。 服 务 器 将 接 收 这 个 数 据 并 将 其 传 递 给<br />

secur32!AcceptSecurityContext, 而 这 个 函 数 将 生 成 另 一 个 不 透 明 数 据 块 , 并 且 告<br />

诉 服 务 器 认 证 过 程 是 否 完 成 。 如 果 没 有 完 成 , 那 么 服 务 器 生 成 的 数 据 块 将 被 发 送 到 客<br />

户 端 , 而 客 户 端 将 把 这 个 数 据 块 作 为 调 用 另 一 个 函 数<br />

secure32!InitializeSecurityContextW 的 参 数 。 然 后 , 将 调 用 这 个 函 数 后 返 回 的 数<br />

据 块 发 送 回 服 务 器 , 这 个 过 程 将 重 复 数 次 , 直 到 在 认 证 中 使 用 的 安 全 包 可 以 验 证 证 书 。<br />

当 消 息 交 换 过 程 完 成 时 , 服 务 器 将 以 最 后 的 数 据 块 作 为 参 数 来 调 用<br />

secure32!ImpersonateSecurityContext 以 模 拟 客 户 的 身 份 。 这 个 调 用 序 列 经 常 也 被<br />

称 之 为 ISC/ASC 序 列 。<br />

给 出 了 这 个 远 程 认 证 过 程 的 详 细 内 容 。 清 单 12 从 服 务 器 进 程 中 抓 取 的 内 容 , 此 时<br />

远 程 客 户 还 没 有 与 服 务 器 建 立 连 接 。 函 数 secur32!AcceptSecurityContext 的 返 回 值<br />

是 一 个 非 常 重 要 的 线 索 , 它 告 诉 我 们 ISC/ASC 正 在 做 什 么 , 而 每 个 认 证 包 检 测 到 的 错<br />

误 也 是 非 常 好 的 线 索 , 它 能 使 我 们 理 解 为 什 么 远 程 认 证 过 程 会 失 败 — 而 使 用 SSPI 的<br />

高 层 函 数 经 常 会 丢 失 这 个 线 索 。<br />

清 单 12 跟 踪 来 自 服 务 器 进 程 的 远 程 认 证 过 程<br />

0:009> bp Secur32!AcceptSecurityContext<br />

0:009> bp Secur32!ImpersonateSecurityContext<br />

0:003> g<br />

...<br />

Breakpoint 0 hit<br />

eax=0009be20 ebx=00000000 ecx=0009722c edx=76f9d1e0 esi=00097220 edi=000000a6<br />

eip=76f949ba esp=005bfe68 ebp=005bfea8 iopl=0 nv up ei pl nz na pe nc<br />

Secur32!AcceptSecurityContext:<br />

76f949ba 55 push ebp<br />

0:003> k<br />

ChildEBP RetAddr<br />

005bfe64 78023b9f Secur32!AcceptSecurityContext<br />

005bfea8 78023b22 RPCRT4!SECURITY_CONTEXT::AcceptThirdLeg+0x3e<br />

005bff18 78004aed RPCRT4!OSF_SCONNECTION::ProcessReceiveComplete+0x595<br />

005bff28 78001848 RPCRT4!ProcessConnectionServerReceivedEvent+0x20<br />

0:003> * "Third Leg" 是 在 NTLM 认 证 中 使 用 的 一 个 概 念<br />

0:003> g<br />

Breakpoint 1 hit<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 67/85


安 全 优 化 :<br />

《PHPer》<br />

eax=76f9d1e0 ebx=005bf83c ecx=0009722c edx=75867028 esi=000971e0 edi=005bf848<br />

eip=76f95099 esp=005bf75c ebp=005bf768 iopl=0 nv up ei pl nz na pe nc<br />

Secur32!ImpersonateSecurityContext:<br />

76f95099 55 push ebp<br />

0:003> k<br />

ChildEBP RetAddr<br />

005bf758 7802372a Secur32!ImpersonateSecurityContext<br />

005bf768 78023701 RPCRT4!SECURITY_CONTEXT::ImpersonateClient+0x39<br />

005bf770 78004443 RPCRT4!OSF_SCONNECTION::ImpersonateClient+0x3b<br />

005bf778 75852a8f RPCRT4!RpcImpersonateClient+0x64<br />

0:003> * RPCImpersonateClient 函 数 使 用 了 SSPI 函 数<br />

当 前 面 给 出 的 所 有 函 数 都 成 功 执 行 后 , 主 调 线 程 将 模 拟 客 户 端 的 模 拟 访 问 令 牌 。<br />

在 分 析 安 全 问 题 时 , 从 secur32!ImpersonateSecurityContext 中 返 回 的 位 置 是 设 置<br />

断 点 的 极 佳 位 置 , 在 服 务 器 执 行 身 份 模 拟 函 数 之 后 , 如 下 所 示 :<br />

0:003> gu<br />

eax=00000000 ebx=005bf83c ecx=c000023c edx=7ffe0304 esi=000971e0 edi=005bf848<br />

eip=7802372a esp=005bf764 ebp=005bf768 iopl=0 nv up ei pl zr na po nc<br />

RPCRT4!SECURITY_CONTEXT::ImpersonateClient+0x39:<br />

7802372a 85c0 test eax,eax<br />

根 据 MSDN 中 的 相 关 文 档 , 返 回 值 表 示 身 份 模 拟 操 作 成 功 , 通 过 扩 展 命 令 !token<br />

可 以 查 看 线 程 的 模 拟 访 问 令 牌 , 如 清 单 13 所 示 :<br />

清 单 13 在 执 行 SSPI 模 拟 操 作 后 查 看 模 拟 令 牌<br />

0:003> !token –n<br />

TS Session ID: 0<br />

User: S-1-5-21-1060284298-2111687655-1957994488-1003 (User: XP-SP1\TestAdmin)<br />

...<br />

Auth ID: 0:2780c<br />

Impersonation Level: Impersonation<br />

TokenType: Impersonation<br />

在 执 行 模 拟 操 作 之 后 , 线 程 可 以 通 过 一 个 反 转 函 数 (Revert Function) 恢 复 到 非<br />

模 拟 状 态 , 这 个 函 数 通 常 与 模 拟 函 数 是 相 对 应 的 , 在 MSDN 的 同 一 页 面 上 可 以 找 到 这<br />

两 个 函 数 的 说 明 。 另 一 个 经 常 使 用 的 模 拟 函 数 就 是 advapi32!SetThreadToken, 这 个<br />

函 数 通 常 用 于 当 服 务 器 已 经 拥 有 一 个 通 过 其 他 方 式 得 到 的 客 户 访 问 令 牌 的 情 况 , 例 如<br />

当 服 务 器 维 持 了 一 个 访 问 令 牌 缓 存 , 并 且 管 理 这 些 令 牌 的 使 用 。 还 有 一 个 函 数<br />

advapi32!ImpersonateSelf 则 用 于 这 样 的 情 况 : 线 程 需 要 一 个 类 似 于 主 访 问 令 牌 的 令<br />

牌 , 但 这 个 令 牌 却 有 着 不 同 的 组 成 员 属 性 或 者 权 限 。<br />

4.2 模 拟 级 别<br />

访 问 令 牌 中 另 一 个 重 要 的 信 息 就 是 它 的 模 拟 级 别 (Impersonation Level)。 模 拟<br />

级 别 是 客 户 在 服 务 器 使 用 的 访 问 令 牌 上 加 上 的 限 制 , 这 个 限 制 是 由 操 作 系 统 来 实 施 的 。<br />

如 果 线 程 模 拟 令 牌 的 级 别 小 于 SecurityImpersonation, 那 么 就 不 能 在 运 行 服 务 器 进<br />

程 的 系 统 上 获 得 任 何 安 全 资 源 。<br />

为 了 说 明 模 拟 级 别 的 重 要 性 , 清 单 14 给 出 的 示 例 调 用 了 GetComputerNameEx, 并<br />

且 在 不 同 的 级 别 上 模 拟 访 问 令 牌 。 这 可 以 通 过 在 07sample.exe 中 选 择 选 项 ‘1’ 来 执<br />

行 。<br />

清 单 14 在 不 同 的 模 拟 级 别 上 调 用 GetComputerNameEx<br />

代 码 片 段<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 68/85


安 全 优 化 :<br />

《PHPer》<br />

void Sample1()<br />

{<br />

WCHAR computerName[MAX_PATH];<br />

DWORD arrayLength = MAX_PATH;<br />

BOOL retCode = TRUE;<br />

ImpersonateSelf(SecurityAnonymous);<br />

retCode = GetComputerNameEx(ComputerNameNetBIOS, computerName, &arrayLength);<br />

RevertToSelf();<br />

...<br />

ImpersonateSelf(SecurityDelegation);<br />

retCode = GetComputerNameEx(ComputerNameNetBIOS, computerName, &arrayLength);<br />

RevertToSelf();<br />

if (retCode != TRUE)<br />

{<br />

TRACE(L"GetComputerName fails with token @ SecurityDelegation.");<br />

}<br />

在 以 下 的 输 出 信 息 中 表 明 , 当 模 拟 级 别 被 设 置 为 SecurityAnonymous 或 者<br />

SecurityIdentify 时 , 程 序 执 行 将 失 败 。<br />

GetComputerName fails with token @ SecurityAnonymous.Last error = 1346<br />

GetComputerName fails with token @ SecurityIdentification.Last error = 1346<br />

在 头 文 件 winerror.h 中 , 错 误 码 1346L 表 示 ERROR_BAD_IMPERSONATION_LEVEL。<br />

我 们 也 可 以 通 过 使 用 命 令 net helpmsg 或 者 扩 展 命 令 !error 来 查 看 错 误 码 。<br />

5 系 统 边 界 上 的 安 全 检 查<br />

今 天 , 即 使 一 个 简 单 的 程 序 , 都 会 与 不 同 运 行 环 境 中 的 操 作 系 统 组 件 进 行 复 杂 的<br />

交 互 。 例 如 , 如 果 在 一 个 有 着 安 全 限 制 的 环 境 中 测 试 程 序 , 程 序 无 法 打 开 某 个 文 件 或<br />

者 在 事 件 日 志 中 记 录 错 误 , 那 么 我 们 如 何 来 调 试 这 个 程 序 ? 在 下 一 节 中 , 我 们 将 分 析<br />

一 些 常 见 的 情 况 ( 在 程 序 或 者 操 作 系 统 组 件 中 由 于 安 全 性 检 查 导 致 的 问 题 ), 目 的 在<br />

于 建 立 一 个 能 够 适 用 于 其 他 情 况 的 调 试 框 架 。 在 开 始 分 析 之 前 , 我 们 首 先 要 理 解 在 操<br />

作 系 统 中 使 用 的 一 些 基 本 安 全 措 施 。<br />

Windows 存 在 着 许 多 由 操 作 系 统 定 义 的 安 全 边 界 , 并 且 每 当 进 入 或 者 离 开 这 些 安<br />

全 边 界 时 , 都 需 要 执 行 安 全 检 查 。 我 们 可 以 很 容 易 地 找 出 一 些 常 见 的 边 界 ( 例 如 文 件<br />

系 统 、Windows 注 册 表 、 每 个 进 程 的 地 址 空 间 、 内 核 地 址 空 间 ), 而 其 他 一 些 边 界 , 例<br />

如 Windows 桌 面 , 则 不 太 容 易 识 别 出 来 。 计 算 机 本 身 是 一 种 物 理 安 全 边 界 , 但 同 时 也<br />

是 一 种 逻 辑 安 全 边 界 。 因 此 , 每 个 函 数 都 可 以 检 查 调 用 者 的 标 识 , 并 且 根 据 在 函 数 中<br />

实 现 的 安 全 策 略 来 允 许 / 拒 绝 调 用 。 在 分 析 安 全 故 障 时 , 如 果 对 每 个 函 数 都 有 着 良 好<br />

的 理 解 , 那 么 无 疑 是 非 常 有 帮 助 的 。 然 而 , 这 也 是 非 常 困 难 的 , 因 为 我 们 无 法 获 得 源<br />

代 码 或 者 花 大 量 的 时 间 来 阅 读 这 些 代 码 。 事 实 上 , 只 有 函 数 的 开 发 人 员 能 够 透 彻 地 理<br />

解 代 码 , 因 此 他 们 可 以 很 快 地 查 明 问 题 。<br />

由 于 理 解 每 个 函 数 的 实 现 细 节 是 不 切 实 际 的 , 那 么 要 想 成 功 地 分 析 安 全 问 题 , 什<br />

么 才 是 最 低 的 要 求 ? 开 发 人 员 需 要 稍 微 了 解 所 使 用 的 子 系 统 , 以 及 在 子 系 统 中 使 用 这<br />

些 函 数 时 最 有 可 能 执 行 安 全 检 查 的 位 置 。 他 们 同 样 需 要 知 道 如 何 查 看 这 些 安 全 检 查 的<br />

结 果 。<br />

如 果 在 执 行 代 码 时 没 有 进 入 到 另 一 个 进 程 中 , 那 么 内 核 态 代 码 将 是 惟 一 能 够 拒 绝<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 69/85


安 全 优 化 :<br />

《PHPer》<br />

对 资 源 进 行 访 问 的 管 理 器 。 请 注 意 , 许 多 Win32 函 数 都 需 要 与 不 同 的 进 程 通 信 以 实 现<br />

它 们 的 功 能 。 当 代 码 执 行 到 另 一 个 进 程 中 时 , 它 需 要 通 过 的 访 问 边 界 实 际 上 是 非 常 多<br />

的 , 因 为 这 个 函 数 调 用 可 能 会 产 生 多 个 进 程 , 甚 至 是 多 个 系 统 。 例 如 , 在 图 1 中 给 出<br />

了 一 个 三 层 (Three-Tier) 系 统 的 基 本 架 构 ( 在 前 端 使 用 了 一 台 Web 服 务 器 , 在 中 间<br />

层 使 用 了 中 间 件 , 以 及 在 后 端 使 用 了 一 台 数 据 库 ), 在 这 种 架 构 中 可 能 会 发 生 许 多 与<br />

安 全 相 关 的 故 障 。<br />

图 1 典 型 的 多 层 应 用 程 序<br />

在 图 1 中 , 每 个 方 框 都 可 以 在 一 个 或 多 个 系 统 上 运 行 , 系 统 之 间 通 过 不 同 的 通 信<br />

机 制 来 互 联 。 在 架 构 中 的 每 一 部 分 都 可 能 检 查 用 户 标 识 以 及 拒 绝 调 用 请 求 。 下 一 节 将<br />

分 析 在 分 布 式 环 境 中 发 生 的 一 些 故 障 情 况 , 分 布 式 环 境 中 的 出 错 概 率 将 大 为 增 加 。<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 70/85


LAMP 大 讲 堂 :<br />

《PHPer》<br />

LAMP 大 讲 堂<br />

5 Apache 配 置 和 指 示 符<br />

Web 服 务 器 ( 二 )<br />

Richard Petersen<br />

Apache 的 配 置 形 式 是 在 配 置 文 件 中 输 入 指 示 符 。 利 用 这 些 指 示 符 , 可 以 输 入 基 本<br />

的 配 置 信 息 , 例 如 服 务 器 名 称 , 也 可 以 执 行 更 复 杂 的 操 作 , 例 如 实 现 虚 拟 主 机 。 这 个<br />

设 计 非 常 灵 活 , 用 户 可 以 为 特 定 的 目 录 和 不 同 的 虚 拟 主 机 定 义 配 置 特 性 。Apache 具 有<br />

各 种 各 样 不 同 的 指 示 符 , 可 用 于 执 行 种 类 丰 富 的 操 作 , 例 如 控 制 目 录 的 访 问 , 指 定 文<br />

件 图 标 格 式 , 创 建 日 志 文 件 等 。 大 多 数 指 示 符 需 要 设 置 值 , 例 如 DirectoryRoot 指 示<br />

符 , 保 存 服 务 器 网 页 的 根 目 录 , 或 者 Port 指 示 符 , 保 存 服 务 器 在 系 统 上 的 哪 个 端 口<br />

监 听 请 求 。 简 单 指 示 符 的 语 法 如 下 所 示 :<br />

directive option option ...<br />

某 些 指 示 符 可 以 创 建 配 置 块 , 里 面 可 以 包 含 对 特 定 服 务 器 组 件 进 行 配 置 的 多 个 指<br />

示 符 ( 也 被 称 作 节 指 示 符 )。 例 如 ,Directory 指 示 符 可 用 于 指 定 一 个 配 置 块 , 里 面 存<br />

放 仅 应 用 于 特 定 目 录 的 指 示 符 。 块 指 示 符 需 要 成 对 出 现 : 一 个 开 始 指 示 符 和 一 个 结 束<br />

指 示 符 。 结 束 指 示 符 定 义 配 置 块 的 终 止 , 它 由 以 斜 线 开 头 的 相 同 名 称 组 成 。 块 指 示 符<br />

接 收 的 参 数 用 于 指 定 该 指 示 符 应 用 的 对 象 。 对 于 Directory 块 指 示 符 , 必 须 指 定 它 所<br />

应 用 的 目 录 名 称 。 块 指 示 符 创 建 的 配 置 块 , 它 里 面 的 指 示 符 都 应<br />

用 于 mydir 目 录 。 这 个 配 置 块 以 指 示 符 结 束 。<br />

块 指 示 符 用 于 配 置 特 定 的 虚 拟 Web 服 务 器 , 必 须 包 含 这 个 服 务 器 要 使 用 的 IP 或 域 名<br />

地 址 。 是 这 个 配 置 块 的 结 束 指 示 符 。 这 个 块 中 的 任 何 指 示 符 都 应 用 于<br />

这 个 虚 拟 Web 服 务 器 。 指 示 符 指 定 希 望 限 制 的 访 问 方 法 类 型 , 例 如 GET<br />

或 POST。 这 个 块 中 的 访 问 控 制 指 示 符 列 出 需 要 施 加 在 这 些 方 法 上 的 控 制 。 块 指 示 符 的<br />

语 法 如 下 :<br />

代 码 片 段<br />

<br />

directive option ...<br />

directive option ...<br />

<br />

通 常 , 指 示 符 被 放 置 在 某 一 个 主 配 置 文 件 中 。 这 些 文 件 中 的 目 录 指 示 符 可 用 于 配<br />

置 特 定 的 目 录 。 然 而 ,Apache 还 可 以 使 用 基 于 目 录 的 配 置 文 件 。 任 何 一 个 目 录 可 能 都<br />

有 自 己 的 .htaccess 文 件 , 该 文 件 保 存 仅 用 于 配 置 当 前 目 录 的 指 示 符 。 如 果 你 的 站 点<br />

有 多 个 目 录 , 或 者 如 果 某 些 目 录 有 特 殊 的 配 置 需 求 , 可 以 将 它 们 的 配 置 指 示 符 放 置 在<br />

它 们 的 .htaccess 文 件 中 , 而 不 必 在 主 配 置 文 件 中 使 用 Directory 指 示 符 来 配 置 它 们 。<br />

如 果 站 点 允 许 某 些 目 录 由 用 户 或 客 户 端 控 制 , 那 么 可 能 会 仔 细 地 监 控 这 些 目 录<br />

中 .htaccess 文 件 的 使 用 , 或 者 禁 止 这 些 文 件 的 使 用 。(.htaccess 文 件 中 指 示 符 可 以<br />

覆 盖 标 准 配 置 文 件 中 的 对 应 指 示 符 , 除 非 关 闭 了 AllowOverride 指 示 符 。)<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 71/85


LAMP 大 讲 堂 :<br />

《PHPer》<br />

5.1 全 局 配 置<br />

标 准 的 Apache 配 置 有 三 个 部 分 : 全 局 设 置 , 服 务 器 设 置 , 以 及 虚 拟 主 机 设 置 。 全<br />

局 设 置 控 制 着 Web 服 务 器 的 基 本 操 作 和 性 能 。 这 里 可 以 设 置 配 置 地 址 、 进 程 ID 文 件 、<br />

计 时 、 有 关 使 用 到 的 MPM 模 块 的 配 置 , 以 及 要 加 载 哪 些 Apache 模 块 。<br />

ServerTokens 指 示 符 用 于 防 止 服 务 器 使 用 的 任 何 可 选 模 块 被 公 开 。ServerRoot<br />

指 示 符 用 于 指 定 Web 服 务 器 的 配 置 、 错 误 , 以 及 日 志 文 件 保 存 在 哪 里 。 这 个 目 录 是<br />

/etc/httpd, 该 目 录 还 包 括 错 误 和 日 志 文 件 , 以 及 服 务 器 模 块 。 之 后 , 这 个 服 务 器 根<br />

目 录 被 用 作 其 他 目 录 项 的 前 缀 。<br />

ServerRoot /etc/httpd<br />

服 务 器 的 进 程 ID(PID) 文 件 通 常 是 /etc/httpd/run/httpd.pid, 它 由 PidFile<br />

指 示 符 设 置 。<br />

PidFile run/httpd.pid<br />

连 接 和 请 求 计 时 由 Timeout、KeepAlive、MaxKeepAlive, 以 及 KeepAliveTimeout<br />

指 示 符 处 理 。Timeout 是 Web 服 务 器 判 断 请 求 的 发 送 或 接 收 超 时 的 时 间 , 以 秒 为 单 位 。<br />

KeepAlive 允 许 持 久 连 接 , 某 个 客 户 端 的 多 个 请 求 使 用 相 同 的 连 接 。 该 指 示 符 默 认 关<br />

闭 。<br />

KeepAliveRequests 设 置 持 久 连 接 上 的 最 大 请 求 数 目 。KeepAliveTimeout 是 保 持<br />

与 客 户 端 的 连 接 以 接 收 更 多 请 求 的 时 间 限 制 。<br />

Listen 指 示 符 用 于 把 服 务 器 绑 定 到 特 定 的 端 口 或 IP 地 址 。 这 个 指 示 符 的 默 认 值<br />

是 端 口 80。<br />

Listen 80<br />

1. 模 块<br />

Apache Web 服 务 器 大 部 分 的 功 能 和 灵 活 性 来 源 于 使 用 模 块 扩 展 自 身 的 功 能 。<br />

Apache 由 核 心 的 指 示 符 集 合 实 现 。 通 过 定 义 其 他 的 指 示 符 来 创 建 模 块 。 模 块 被 加 载 到<br />

Apache 服 务 器 中 , 用 户 便 可 以 使 用 该 服 务 器 的 那 些 指 示 符 。Apache 发 布 包 含 标 准 的<br />

模 块 集 合 , 不 过 用 户 可 以 下 载 其 他 的 模 块 , 甚 至 可 以 创 建 自 己 的 模 块 。 例 如 ,<br />

mod_autoindex 模 块 包 含 用 于 自 动 目 录 的 指 示 符 ( 随 后 的 一 节 将 会 讲 述 它 )。mod_mime<br />

模 块 包 含 MIME 类 型 和 处 理 器 指 示 符 。 模 块 的 加 载 使 用 LoadModule 指 示 符 。 可 以 在<br />

httpd.conf 配 置 文 件 中 找 到 大 多 数 标 准 模 块 的 LoadModule 指 示 符 。<br />

LoadModule mime_module modules/mod_mime.so<br />

LoadModule 指 示 符 以 模 块 名 称 和 模 块 的 位 置 为 参 数 。 这 些 模 块 存 放 在<br />

/etc/httpd/modules 目 录 中 , 可 使 用 modules/ 前 缀 来 引 用 它 们 。<br />

不 同 模 块 的 配 置 文 件 放 在 /etc/httpd/conf.d 目 录 下 。 它 们 通 过 使 用 Include 指<br />

示 符 也 被 加 载 进 来 。 下 面 的 例 子 是 将 /etc/httpd/conf.d 目 录 下 的 所 有 配 置 文 件<br />

( 以 .conf 为 扩 展 名 的 文 件 ) 加 载 进 来 :<br />

Include conf.d/*.conf<br />

Apache 软 件 包 提 供 的 apxs 应 用 程 序 可 用 于 构 建 Apache 扩 展 模 块 。 使 用 该 应 用 程<br />

序 , 可 编 译 Apache 模 块 的 C 语 言 源 码 , 动 态 创 建 可 使 用 LoadModule 指 示 符 进 行 加 载<br />

的 共 享 对 象 。apxs 应 用 程 序 要 求 mod_so 模 块 必 须 是 Apache 应 用 程 序 的 一 部 分 。 它 包<br />

含 大 量 的 选 项 , 例 如 ,-n 指 定 模 块 的 名 称 ,-a 在 httpd.conf 文 件 中 为 它 添 加 配 置 项 ,<br />

-i 在 Web 服 务 器 上 安 装 模 块 。<br />

在 Apache 的 网 站 httpd.apache.org 上 , 以 及 站 点 根 目 录 下 的 Apache 手 册 中 , 可<br />

以 找 到 Apache Web 配 置 指 示 符 的 完 整 列 表 , 在 许 多 系 统 中 , 这 个 手 册 位 于 Apache 发<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 72/85


LAMP 大 讲 堂 :<br />

《PHPer》<br />

布 为 站 点 建 立 的 默 认 目 录 下 的 manual 子 目 录 中 (/var/www/manual)。<br />

2. MPM 配 置<br />

MPM prefork 和 worker 模 块 的 配 置 允 许 用 户 对 Apache Web 服 务 器 进 行 定 制 , 以<br />

满 足 具 体 的 工 作 负 荷 要 求 。 默 认 的 设 置 项 适 用 于 负 荷 较 轻 的 标 准 Web 服 务 器 。 用 户 可<br />

修 改 这 些 设 置 以 满 足 不 同 的 需 求 。<br />

prefork 和 worker 是 UNIX 和 Linux 系 统 中 经 常 使 用 的 两 个 MPM 模 块 。prefork<br />

模 块 支 持 每 个 进 程 一 个 线 程 , 这 样 可 与 老 的 系 统 和 模 块 保 持 兼 容 。worker 模 块 支 持 每<br />

个 进 程 多 个 线 程 , 对 系 统 资 源 的 负 载 较 轻 。 这 两 种 模 块 共 享 一 些 相 同 的 指 示 符 , 例 如<br />

StartServer 和 MaxRequestPerChild。<br />

Apache 运 行 单 个 父 进 程 , 根 据 需 要 派 生 出 多 个 子 进 程 来 处 理 请 求 。MPM 模 块 的 配<br />

置 焦 点 在 于 配 置 多 个 进 程 。prefork 模 块 将 会 列 出 服 务 器 的 数 量 , 为 每 个 服 务 器 启 动<br />

一 个 进 程 ;worker 模 块 将 会 控 制 线 程 , 因 为 它 使 用 每 个 进 程 中 的 线 程 。StartServer<br />

指 示 符 列 出 为 这 两 种 模 块 启 动 的 服 务 器 进 程 的 数 量 。prefork 模 块 的 值 通 常 会 大 于<br />

worker 模 块 的 值 。<br />

在 prefork 模 块 中 , 需 要 设 置 最 少 的 空 闲 服 务 器 和 最 大 的 空 闲 服 务 器 。MaxClients<br />

用 于 设 置 可 以 被 启 动 的 最 大 服 务 器 数 量 ,ServerLimit 用 于 设 置 被 允 许 的 服 务 器 数 量 。<br />

MaxRequestPerChild 用 于 设 置 每 个 服 务 器 被 允 许 处 理 的 最 大 请 求 数 量 。<br />

在 worker 模 块 中 ,MaxClients 还 可 设 置 客 户 端 线 程 的 最 大 数 量 ,ThreadsPerChild<br />

设 置 每 个 服 务 器 的 线 程 数 量 。MaxRequestPerChild 限 制 每 个 服 务 器 的 处 理 的 最 大 请 求<br />

数 量 。 另 外 , 还 可 以 配 置 空 闲 的 线 程 数 量 限 制 。<br />

指 示 符 作 为 Web 服 务 器 访 问 的 控 制 阀 , 控 制 着 可 用 的 进 程 , 限 制 着 可 被 使 用 的 资<br />

源 。 在 prefork 配 置 中 ,StartServer 被 设 置 成 8, 最 小 空 闲 数 量 被 设 置 成 5, 最 大 空<br />

闲 数 量 被 设 置 成 20。 这 意 味 着 开 始 的 时 候 8 个 服 务 器 进 程 会 启 动 , 然 后 等 待 着 请 求 ,<br />

其 中 有 5 个 空 闲 的 进 程 。 当 服 务 器 进 程 不 再 被 使 用 , 它 们 会 被 停 止 , 直 到 空 闲 的 进 程<br />

数 量 小 于 20。 可 被 启 动 的 最 大 服 务 器 进 程 数 量 是 256。 每 个 服 务 器 进 程 的 最 大 连 接 数<br />

量 被 设 置 成 4 000。<br />

在 worker MPM 中 , 开 始 的 时 候 仅 有 2 个 服 务 器 进 程 被 启 动 。 空 闲 的 线 程 被 设 置 成<br />

最 小 25, 最 大 75。 线 程 的 最 大 数 量 被 设 置 成 150, 每 个 子 进 程 的 线 程 数 量 是 25。<br />

5.2 服 务 器 配 置<br />

某 些 指 示 符 用 于 配 置 服 务 器 的 整 体 操 作 。 这 些 指 示 符 被 存 在 于 httpd.conf 配 置 文<br />

件 位 于 ServerSetttings 配 置 节 。 有 些 指 示 符 要 求 提 供 路 径 名 , 而 其 他 的 指 示 符 需 要<br />

使 用 关 键 字 on 和 off 进 行 打 开 和 关 闭 。 默 认 的 httpd.conf 文 件 已 经 包 含 这 些 指 示 符 。<br />

有 些 指 示 符 被 它 前 面 的 # 号 注 释 起 来 。 删 除 这 个 # 号 便 可 以 激 活 该 指 示 符 。 许 多 配 置 项<br />

都 有 注 释 来 解 释 它 的 用 途 。<br />

下 面 是 一 个 ServerAdmin 指 示 符 的 例 子 , 该 指 示 符 设 置 的 邮 件 地 址 用 于 接 收 用 户<br />

发 送 的 有 关 管 理 问 题 的 邮 件 。 此 处 , 可 以 使 用 自 己 用 来 接 收 系 统 管 理 邮 件 的 地 址 替 换<br />

you@your.address 项 。 默 认 情 况 下 , 这 个 指 示 符 被 设 置 成 root@localhost。<br />

# ServerAdmin: Your address, where problems should be e-mailed.<br />

ServerAdmin you@your.address<br />

Web 服 务 器 通 常 使 用 端 口 80, 它 是 Apache 的 默 认 配 置 。 如 果 希 望 使 用 不 同 的 端 口 ,<br />

可 使 用 Port 指 示 符 进 行 指 定 。<br />

Port 80<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 73/85


LAMP 大 讲 堂 :<br />

《PHPer》<br />

ServerName 指 示 符 保 存 着 Web 服 务 器 的 主 机 名 。 指 定 主 机 名 非 常 重 要 , 可 以 避 免<br />

因 不 必 要 的 DNS 查 询 故 障 而 挂 起 服 务 器 。<br />

注 意 这 个 配 置 项 被 前 面 的 # 号 注 释 。 简 单 地 删 除 前 面 的 # 号 , 并 输 入 自 己 的 主 机 名<br />

称 代 替 new.host.name 即 可 。 如 果 要 使 用 不 同 于 8 0 的 端 口 , 一 定 要 在 主 机 名 的 后<br />

面 指 定 , 例 如 turtle.mytrek.com:80。 下 面 给 出 了 默 认 的 配 置 项 :<br />

# ServerName allows you to set a hostname which is sent<br />

# back to clients for your server if it’s different than the<br />

# one the program would get (i.e. use<br />

# "www" instead of the host’s real name).<br />

#ServerName new.host.name:80<br />

修 改 后 的 ServerName 配 置 项 是 这 个 样 子 :<br />

ServerName turtle.mytrek.com<br />

当 收 到 对 服 务 器 系 统 的 URL 请 求 , 例 如 对 系 统 中 本 地 文 件 的 请 求 ,<br />

UseCannonicalName 指 示 符 使 用 ServerName 和 Port 指 示 符 生 成 主 机 URL 服 务 器 名 。<br />

当 关 闭 这 个 配 置 项 , 它 只 会 使 用 客 户 端 请 求 提 供 的 名 字 。 如 果 Web 服 务 器 由 一 个 名 字<br />

引 用 , 但 是 本 身 却 使 用 另 一 个 名 字 , 例 如 www.mytrek.com 引 用 turtle.mytrek.com,<br />

这 样 可 能 会 产 生 混 淆 。 设 置 UseCannonicalName 可 解 决 这 个 问 题 , 从 而 生 成 正 确 的 本<br />

地 URL。<br />

在 Linux 系 统 中 , 已 经 对 标 准 的 Web 服 务 器 设 置 了 适 当 的 配 置 项 , 例 如 /var/www<br />

用 作 站 点 的 目 录 。 可 以 根 据 自 己 的 需 要 通 过 修 改 适 当 的 指 示 符 来 定 制 自 己 的 站 点 。<br />

DocumentRoot 指 示 符 用 于 确 定 网 页 的 主 目 录 。<br />

DocumentRoot /var/www/html<br />

注 意 也 可 以 将 Apache 配 置 成 作 为 代 理 和 / 或 缓 存 服 务 器 运 行 。 默 认 的 代 理 和 缓<br />

存 服 务 器 指 示 符 已 经 包 含 在 httpd.conf 文 件 中 。ProxyRequests 指 示 符 用 于 打 开 代 理<br />

操 作 。 缓 存 可 使 用 专 门 的 指 示 符 进 行 配 置 , 例 如 CacheRoot 指 定 缓 存 的 目 录 ,CacheSize<br />

指 定 缓 存 的 大 小 ( 默 认 是 500KB), CacheMaxExpire 设 置 未 修 改 文 档 的 时 间 限 制 。<br />

5.3 目 录 级 别 的 配 置 :.htaccess 和 <br />

Apache 最 灵 活 的 方 面 之 一 是 , 它 能 够 配 置 单 独 的 目 录 。 使 用 Directory 指 示 符 ,<br />

可 以 定 义 专 门 应 用 于 特 定 目 录 的 指 示 符 配 置 块 。 这 些 指 示 符 可 以 放 置 在 httpd.conf<br />

或 者 access.conf 配 置 文 件 中 。 也 可 以 使 用 特 定 目 录 中 的 .htaccess 文 件 来 存 放 配 置<br />

指 示 符 。 这 样 , 那 些 指 示 符 仅 应 用 于 那 个 目 录 。 文 件 名 “.htaccess” 使 用<br />

AccessFileName 指 示 符 进 行 设 置 。 如 果 愿 意 , 可 修 改 它 。<br />

AccessFileName .htaccess<br />

Directory 配 置 块 以 指 示 符 开 头 , 其 中 的 pathname 就 是 被<br />

配 置 的 目 录 。 结 束 指 示 符 使 用 相 同 的 符 号 , 不 过 “Directory” 的 前 面 有 一 个 斜 线 :<br />

。 放 置 在 这 个 配 置 块 中 的 指 示 符 仅 应 用 于 所 指 定 的 目 录 。 在 下 面 的 例 子<br />

中 , 仅 仅 拒 绝 来 自 www.myvids.com 对 mypics 目 录 的 访 问 请 求 。<br />

代 码 片 段<br />

<br />

Order Deny,Allow<br />

Deny from [url]www.myvids.com[/url]<br />

<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 74/85


LAMP 大 讲 堂 :<br />

《PHPer》<br />

使 用 Options 指 示 符 , 可 以 在 目 录 中 打 开 某 些 特 性 , 例 如 使 用 符 号 连 接 、 自 动 索<br />

引 、 执 行 CGI 脚 本 , 以 及 内 容 协 商 。 默 认 值 是 All 选 项 , 它 会 打 开 除 了 内 容 协 商<br />

(Multiviews) 之 外 的 所 有 特 性 。 下 面 的 例 子 打 开 了 自 动 索 引 (Indexes)、 符 号 链 接<br />

(FollowSymLinks), 以 及 内 容 协 商 (Multiviews)。<br />

Options Indexes FollowSymLinks Multiviews<br />

主 配 置 文 件 中 或 者 上 级 目 录 中 指 示 符 所 做 的 配 置 会 被 下 级 目 录 继 承 。 保 存<br />

在 .htaccess 文 件 中 和 Directory 配 置 块 中 特 定 目 录 的 指 示 符 被 允 许 覆 盖 其 他 的 配 置 。<br />

这 个 功 能 由 AllowOverride 指 示 符 控 制 。 带 上 all 参 数 ,.htaccess 文 件 会 覆 盖 之 前<br />

的 任 何 配 置 。none 参 数 禁 止 覆 盖 , 从 而 有 效 地 禁 止 .htaccess 文 件 。 可 以 进 一 步 控 制<br />

对 具 体 指 示 符 组 的 覆 盖 。AuthConfig 允 许 使 用 认 证 指 示 符 ,FileInfo 用 于 类 型 指<br />

示 符 ,Indexes 用 于 索 引 指 示 符 ,Limit 用 于 访 问 控 制 指 示 符 ,Options 用 于 选 项 指 示<br />

符 。<br />

AllowOverride all<br />

5.4 访 问 控 制<br />

使 用 访 问 控 制 指 示 符 , 例 如 allow 和 deny, 可 以 控 制 远 端 用 户 和 主 机 对 站 点 的 访<br />

问 。allow 指 示 符 后 面 跟 上 主 机 名 列 表 , 限 制 只 能 由 这 些 主 机 访 问 。deny 指 示 符 后 面<br />

跟 上 主 机 名 列 表 , 拒 绝 这 些 系 统 的 访 问 。 参 数 all 将 指 示 符 应 用 于 所 有 的 主 机 。order<br />

指 示 符 指 定 以 什 么 样 的 顺 序 应 用 访 问 控 制 指 示 符 。<br />

其 他 的 访 问 控 制 指 示 符 , 例 如 require, 可 用 于 建 立 认 证 控 制 , 要 求 用 户 登 录 。<br />

访 问 控 制 指 示 符 可 用 于 全 局 的 控 制 对 这 个 站 点 的 访 问 , 也 可 放 在 Directory 指 示 符 中 ,<br />

用 于 控 制 单 个 目 录 。 在 随 后 的 例 子 中 , 所 有 的 用 户 都 被 允 许 访 问 :<br />

order allow,deny<br />

allow from all<br />

5.5 URL 路 径 名<br />

某 些 指 示 符 可 用 于 修 改 或 完 成 用 于 访 问 站 点 的 URL 的 路 径 名 段 。URL 的 路 径 名 段<br />

指 定 了 站 点 中 的 特 定 目 录 或 网 页 。 一 些 指 示 符 可 用 于 为 路 径 名 起 别 名 或 者 重 定 向 目 录<br />

名 , 或 者 用 于 选 择 默 认 的 网 页 。 使 用 Alias 指 示 符 , 可 允 许 用 户 访 问 系 统 中 其 他 部 分<br />

的 资 源 , 这 些 资 源 可 能 位 于 其 他 文 件 系 统 , 也 可 能 位 于 其 他 的 网 站 。 别 名 可 以 使 用 因<br />

特 网 中 站 点 的 URL, 而 不 是 本 系 统 中 目 录 的 路 径 名 。 使 用 Redirect 指 示 符 , 可 以 把 用<br />

户 重 定 向 到 其 他 站 点 。<br />

Alias /mytrain /home/dylan/trainproj<br />

Redirect /mycars http://www.myautos.com/mycars<br />

如 果 Apache 设 定 一 个 可 访 问 目 录 而 不 是 特 定 网 页 , 它 会 查 找 这 个 目 录 中 的 索 引 网<br />

页 , 并 显 示 它 。 默 认 网 页 可 能 的 名 称 列 在 DirecoryIndex 指 示 符 中 。 通 常 使 用 的 名 称<br />

是 index.html, 不 过 也 可 以 添 加 其 他 的 。 下 面 显 示 了 标 准 的 名 称 。 当 Apache 只 提 供<br />

一 个 可 访 问 目 录 时 会 查 找 该 目 录 中 index.html 文 件 并 显 示 它 。<br />

DirectoryIndex index.html index.shtml index.cgi<br />

Apache 还 允 许 用 户 维 护 位 于 用 户 主 目 录 中 特 殊 子 目 录 下 的 网 页 , 当 然 不 能 是 主 要<br />

的 网 站 目 录 。 使 用 ~ 符 号 后 面 跟 着 访 问 这 个 目 录 的 用 户 名 。 这 个 目 录 的 名 字 由 UserDir<br />

指 示 符 指 定 。 默 认 的 名 字 是 public_html, 如 下 所 示 。 站 点 turtle.mytrek.com/~dylan<br />

访 问 的 是 turtle.mytrekc.com 主 机 上 的<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 75/85


LAMP 大 讲 堂 :<br />

《PHPer》<br />

turtle.mytrek.com/home/dylan/public_html 目 录 。<br />

UserDir public_html<br />

如 果 希 望 允 许 人 们 使 用 完 整 的 路 径 名 , 则 可 以 使 用 路 径 名 引 用 。 例 如 , 对 于 用 户<br />

dylan,/usr/www 被 翻 译 成 /usr/www/dylan 的 URL 引 用 , 该 目 录 下 保 存 着 他 的 HTML<br />

文 件 ;/home/*/www 被 翻 译 成 /home/dylan/www, 这 是 用 户 dylan 主 目 录 中 的 www 目 录 。<br />

UserDir /usr/www<br />

UserDir /home/*/www<br />

在 标 准 的 配 置 文 件 中 ,Userdir 访 问 默 认 被 注 释 起 来 。 通 常 会 希 望 拒 绝 某 些 用 户<br />

的 访 问 , 如 root 用 户 。 使 用 disable 和 enable 选 项 , 可 以 在 关 闭 某 些 用 户 访 问 权 限 ,<br />

同 时 打 开 其 他 用 户 的 访 问 权 限 , 如 下 所 示 :<br />

UserDir disable root<br />

UserDir disabled<br />

UserDir enabled dylan chris justin<br />

5.6 MIME 类 型<br />

当 浏 览 器 访 问 网 站 上 的 网 页 , 它 经 常 会 访 问 许 多 不 同 类 型 的 对 象 , 其 中 包 括 HTML<br />

文 件 、 图 片 或 音 频 文 件 , 以 及 脚 本 文 件 。 为 了 正 确 地 显 示 这 些 对 象 , 浏 览 器 必 须 能 够<br />

获 取 它 们 是 什 么 类 型 对 象 的 指 示 。JPEG 图 片 文 件 的 处 理 方 法 与 简 单 的 文 本 文 件 不 同 。<br />

服 务 器 提 供 以 MIME 类 型 的 形 式 提 供 对 象 的 类 型 信 息 。MIME 类 型 与 因 特 网 邮 件 工 具 ( 如<br />

Pine) 用 于 发 送 附 件 的 类 型 相 同 。 每 种 类 型 的 对 象 与 特 定 的 MIME 类 型 相 关 联 。 有 了<br />

MIME 类 型 , 浏 览 器 便 可 以 正 确 地 处 理 和 显 示 对 象 。<br />

MIME 协 议 将 具 体 的 类 型 与 具 有 特 定 扩 展 名 的 文 件 关 联 起 来 。 例 如 , 具 有 .jpg 扩 展<br />

名 的 文 件 的 MIME 类 型 为 image/jpeg。TypesConfig 指 示 符 记 录 mime.types 文 件 的 位<br />

置 , 该 文 件 列 出 所 有 MIME 类 型 和 相 关 联 的 文 件 扩 展 名 。DefaultType 是 所 有 类 型 无 法<br />

确 定 的 文 件 的 默 认 MIME 类 型 。AddType 允 许 用 户 无 需 编 辑 MIME 文 件 便 可 以 修 改<br />

mime.type 的 类 型 列 表 。<br />

TypesConfig /etc/mime.types<br />

DefaultType text/plain<br />

其 他 的 类 型 指 示 符 用 于 指 定 对 某 些 文 档 采 取 的 具 体 操 作 。AddEncoding 允 许 浏 览<br />

器 及 时 解 压 被 压 缩 的 文 件 。AddHandler 将 文 件 扩 展 名 映 射 到 对 应 的 操 作 ,AddLanguage<br />

允 许 用 户 指 定 文 档 的 语 言 。 下 面 的 例 子 将 具 有 .gz 扩 展 名 的 文 件 标 记 为 gzip 编 码 的 文<br />

件 , 具 有 .fr 扩 展 名 的 文 件 标 记 为 法 语 文 件 :<br />

AddEncoding x-gzip gz<br />

AddLanguage fr .fr<br />

Web 服 务 器 可 以 显 示 和 执 行 许 多 不 同 类 型 的 文 件 和 程 序 。 不 过 , 并 不 是 所 有 的 Web<br />

浏 览 器 都 能 够 显 示 所 有 的 这 些 文 件 。 较 早 的 浏 览 器 限 制 最 多 。 有 些 浏 览 器 , 如 Lynx,<br />

并 不 是 设 计 用 来 显 示 甚 至 很 简 单 的 图 片 。 为 了 允 许 Web 浏 览 器 显 示 网 页 , 服 务 器 会 与<br />

之 协 商 以 确 定 它 处 理 的 文 件 类 型 。 为 了 打 开 这 种 协 商 功 能 , 需 要 打 开 Multiviews 选<br />

项 。<br />

Option multiviews<br />

5.7 CGI 文 件<br />

通 用 网 关 接 口 (CGI, Common Gateway Interface) 文 件 是 可 以 由 访 问 站 点 的 Web<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 76/85


LAMP 大 讲 堂 :<br />

《PHPer》<br />

浏 览 器 执 行 的 程 序 。 网 页 通 常 会 在 显 示 内 容 的 时 候 以 执 行 程 序 的 形 式 启 动 CGI 文 件 。<br />

传 统 上 ,CGI 程 序 放 置 在 被 称 作 cgi-bin 的 目 录 中 , 仅 当 它 们 驻 留 在 这 样 的 特 殊 目 录<br />

中 才 能 够 被 执 行 。 通 常 , 每 个 网 站 只 存 在 一 个 cgi-bin 目 录 。Linux 发 布 通 常 将 cgi-bin<br />

目 录 建 立 在 默 认 的 Web 服 务 器 目 录 中 ( 对 于 Fedora, 是 /var/www/cgi-bin 目 录 )。 这<br />

里 用 于 放 置 可 以 在 网 站 上 执 行 的 任 何 CGI 程 序 。ScriptAlias 指 示 符 用 于 指 定 cgi-bin<br />

目 录 的 别 名 。 任 何 网 页 或 浏 览 器 都 可 以 使 用 这 个 别 名 来 引 用 这 个 目 录 。<br />

ScriptAlias /cgi-bin/ /var/www/cgi-bin/<br />

5.8 自 动 目 录 索 引<br />

当 给 定 一 个 目 录 的 URL, 而 不 是 HTML 文 件 的 URL, 且 这 个 目 录 中 不 存 在 默 认 的 网<br />

页 ,Apache 会 及 时 创 建 一 个 网 页 并 显 示 出 来 。 这 个 网 页 通 常 仅 仅 列 出 目 录 中 的 不 同 文<br />

件 。 实 际 上 ,Apache 会 为 你 索 引 这 个 目 录 中 的 项 目 。 可 以 通 过 设 置 若 干 个 选 项 来 生 成<br />

和 显 示 这 样 的 索 引 。 如 果 FancyIndexing 被 打 开 , 网 页 项 便 会 显 示 出 来 , 其 中 的 图 标<br />

和 列 头 可 用 于 排 列 整 个 列 表 。<br />

FancyIndexing on<br />

5.9 认 证<br />

Web 服 务 器 还 可 以 以 每 个 用 户 或 每 个 用 户 组 为 基 础 , 控 制 对 网 站 上 特 定 目 录 的 访<br />

问 。 可 要 求 各 种 级 别 的 认 证 。 访 问 可 仅 限 于 特 定 的 用 户 , 并 要 求 输 入 密 码 , 或 者 扩 展<br />

到 允 许 特 定 用 户 组 成 员 的 访 问 。 可 以 完 全 省 掉 密 码 , 或 者 建 立 匿 名 访 问 类 型 , 就 像 FTP<br />

的 匿 名 登 录 一 样 。<br />

为 了 对 某 个 目 录 应 用 认 证 指 示 符 , 可 以 将 这 些 指 示 符 放 置 到 Directory 配 置 块 中 ,<br />

或 者 放 置 到 该 目 录 的 .htaccess 文 件 中 。require 指 示 符 确 定 哪 些 用 户 可 以 访 问 当 前<br />

目 录 。 在 此 , 可 以 列 出 特 定 的 用 户 或 者 用 户 组 。AuthName 指 示 符 为 用 户 提 供 认 证 域 名 ,<br />

该 名 称 用 于 标 识 认 证 过 程 将 要 访 问 的 特 定 资 源 集 合 。AuthType 指 示 符 用 于 指 定 认 证 的<br />

类 型 , 例 如 基 本 类 型 或 摘 要 类 型 。require 指 示 符 还 要 求 有 AuthType、AuthName, 以<br />

及 用 于 指 定 用 户 组 和 用 户 认 证 文 件 位 置 的 指 示 符 。 在 下 面 的 例 子 中 , 仅 有 george、<br />

robert, 以 及 mark 等 用 户 被 允 许 访 问 newpics 目 录 :<br />


LAMP 大 讲 堂 :<br />

《PHPer》<br />

require groups admin<br />

<br />

S<br />

为 了 设 置 目 录 的 匿 名 访 问 , 需 要 在 该 目 录 的 Directory 配 置 块 , 或 者 .htaccess<br />

文 件 中 放 入 Anonymous 指 示 符 , 并 带 上 用 户 anonymous 作 为 它 的 参 数 。 也 可 以 使 用<br />

Anonymous 指 示 符 来 允 许 特 定 用 户 的 访 问 , 而 不 要 求 他 们 提 供 密 码 。<br />

Apache 维 护 着 自 己 的 用 户 和 组 认 证 文 件 , 其 中 指 定 了 哪 些 用 户 和 组 可 以 访 问 哪 些<br />

目 录 。 这 些 文 件 通 常 是 简 单 的 普 通 文 件 , 就 像 系 统 中 的 密 码 和 组 文 件 一 样 。 它 们 可 以<br />

变 得 很 大 , 不 过 , 太 大 可 能 会 影 响 认 证 查 询 的 速 度 。 作 为 替 代 方 法 , 许 多 站 点 使 用 数<br />

据 库 管 理 文 件 代 替 这 些 普 通 文 件 。 然 后 使 用 数 据 库 的 方 法 访 问 这 些 文 件 , 从 而 提 供 更<br />

高 的 响 应 速 度 。Apache 有 专 门 用 于 指 定 认 证 文 件 的 指 示 符 , 这 依 赖 于 所 使 用 的 文 件 类<br />

型 。AuthUserFile 和 AuthGroupFile 指 示 符 用 于 指 定 标 准 普 通 文 件 格 式 的 认 证 文 件 的<br />

位 置 。AuthDBUserFile 和 AuthDBGroupFile 指 示 符 用 于 指 定 DB 数 据 库 文 件 ,<br />

AuthDBMGUserFile 和 AuthDBMGGroupFile 用 于 指 定 DBMG 数 据 库 文 件 。<br />

htdigest、htpasswd, 以 及 dbmmanage 等 程 序 是 Apache 软 件 包 提 供 的 工 具 , 用 于<br />

创 建 和 维 护 用 户 认 证 文 件 , 这 些 文 件 就 是 用 户 密 码 文 件 , 里 面 列 出 能 够 访 问 网 站 中 特<br />

定 目 录 或 资 源 的 用 户 。htdigest 和 htpasswd 程 序 用 于 管 理 记 录 用 户 认 证 信 息 的 普 通<br />

文 件 , 而 dbmmanage 程 序 使 用 更 加 复 杂 的 数 据 库 管 理 格 式 。 如 果 用 户 列 表 过 于 庞 大 ,<br />

则 可 能 需 要 使 用 数 据 库 文 件 , 以 确 保 快 速 的 查 找 。htdigest 的 参 数 有 认 证 文 件 、 域 名 ,<br />

以 及 用 户 名 , 它 可 以 创 建 或 更 新 对 应 于 用 户 的 项 。htpasswd 还 可 以 对 密 码 实 行 加 密 。<br />

dbmmanage 拥 有 大 量 的 选 项 , 可 用 于 添 加 、 删 除 和 更 新 用 户 项 。 多 种 数 据 库 格 式 可 用<br />

于 建 立 这 种 文 件 。 三 种 常 用 的 格 式 是 Berkeley DB2、NDBM, 以 及 GNU GBDM。dbmmanage<br />

会 顺 序 查 找 这 些 格 式 的 系 统 库 。 请 仔 细 地 确 保 所 有 认 证 文 件 使 用 相 同 的 格 式 。<br />

5.10 日 志 文 件<br />

Apache 维 护 用 户 对 网 站 所 有 请 求 的 日 志 。 默 认 情 况 下 , 这 些 日 志 包 含 采 用 通 用 日<br />

志 格 式 (CLF,Common Log Format) 的 记 录 。 每 个 请 求 的 记 录 占 据 一 行 , 每 行 由 这 样<br />

几 个 字 段 组 成 : 主 机 、 身 份 验 证 、 被 认 证 的 用 户 ( 用 于 登 录 )、 日 期 、 客 户 端 提 交 的<br />

请 求 行 、 发 给 客 户 端 的 状 态 , 以 及 被 发 送 对 象 的 大 小 。<br />

1. Webalizer<br />

Webalizer 工 具 用 于 生 成 Web 日 志 的 报 表 。Webalizer 会 显 示 网 站 的 使 用 情 况 信 息 。<br />

运 行 Webalizer 命 令 的 时 候 , 使 用 情 况 报 表 会 放 置 在 /var/www/html/usage 目 录 下 。<br />

访 问 索 引 页 可 显 示 一 个 页 面 , 上 面 列 出 指 向 月 份 报 表 的 链 接 ,<br />

file://var/www/html/usage/index.html。 报 表 的 配 置 由 /etc/webalizer.conf<br />

文 件 指 定 。 之 前 的 总 结 保 存 在 /etc/webalizer.history 文 件 中 。<br />

2. 定 制 日 志<br />

使 用 LogFormat 和 CustomLog 指 示 符 , 可 定 制 日 志 记 录 , 从 而 根 据 详 细 的 级 别 添<br />

加 更 多 的 字 段 。 这 些 指 示 符 使 用 由 字 段 说 明 符 组 成 的 格 式 字 符 串 来 确 定 记 录 到 日 志 记<br />

录 中 的 字 段 。 可 以 以 任 何 顺 序 添 加 任 意 字 段 。 字 段 说 明 符 由 百 分 号 (%) 和 标 识 字 符<br />

组 成 。 例 如 ,%h 是 远 端 主 机 的 字 段 说 明 符 ,%b 代 表 字 节 大 小 ,%s 代 表 状 态 。 参 考<br />

mod_log_config 模 块 的 文 档 以 获 取 完 整 的 列 表 信 息 。 应 该 将 内 容 可 能 占 据 多 个 字 的 字<br />

段 引 用 起 来 。 引 号 本 身 必 须 由 反 斜 线 引 用 , 从 而 把 引 号 包 含 到 格 式 字 符<br />

串 中 。 下 面 的 例 子 是 FormatLog 指 示 符 使 用 的 通 用 日 志 格 式 :<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 78/85


LAMP 大 讲 堂 :<br />

《PHPer》<br />

FormatLog "%h %l %u %t \"%r\" %s %b"<br />

日 志 格 式 中 的 某 些 字 段 说 明 符 能 够 记 录 特 定 的 信 息 。%i 说 明 符 用 于 记 录 服 务 器 收<br />

到 的 请 求 中 的 消 息 头 。 对 消 息 头 中 特 定 行 的 引 用 被 放 置 在 % 号 和 字 段 说 明 符 之 间 。 例<br />

如 , 消 息 头 中 的 User-agent 行 用 于 指 定 请 求 所 使 用 的 浏 览 器 软 件 。 为 了 记 录<br />

User-agent 头 信 息 , 可 使 用 转 换 说 明 符 %{User-agent}i。<br />

为 了 维 护 与 NCSA 服 务 器 的 兼 容 性 ,Apache 最 初 使 用 AgentLog 和 RefererLog 指<br />

示 符 来 记 录 User-agent 和 Referer 头 。 它 们 已 经 被 LogFormat 和 CustomLog 指 示 符<br />

所 使 用 的 被 修 饰 的 %i 字 段 说 明 符 取 代 。Referer 头 记 录 来 自 客 户 端 的 链 接 信 息 , 用 于<br />

检 测 哪 些 网 站 具 有 指 向 站 点 的 链 接 。 下 面 是 NCSA 兼 容 的 日 志 格 式 :<br />

"%h %l %u %t \"%r\" %s %b\"%{Referer}i\" \"%{User-agent}i\"".<br />

3. 生 成 和 管 理 日 志 文 件<br />

无 需 维 护 大 型 的 日 志 文 件 , 可 以 使 用 CustomLog 或 TransferLog 指 示 符 创 建 若 干<br />

个 日 志 文 件 。 每 个 虚 拟 主 机 往 往 需 要 维 护 各 自 的 日 志 文 件 , 此 时 这 两 种 指 示 符 会 特 别<br />

有 用 。FormatLog 指 示 符 可 用 于 为 日 志 记 录 定 义 默 认 的 格 式 。 之 后 在 创 建 新 的 日 志 文<br />

件 的 时 候 ,TransferLog 会 使 用 这 个 默 认 格 式 作 为 自 己 的 格 式 。CustomLog 将 这 两 个<br />

操 作 结 合 起 来 , 使 得 可 以 创 建 新 的 日 志 文 件 , 并 为 它 定 义 自 己 的 格 式 。<br />

FormatLog "%h %l %u %t \"%r\" %s %b""<br />

# Create a new log file called myprojlog<br />

using the FormatLog format<br />

TransferLog myprojlog<br />

# Create a new log file called mypicslog using its own format<br />

CustomLog mypicslog "%h %l %u %t \"%r\" %s %b"<br />

Apache 提 供 两 个 工 具 用 于 处 理 和 管 理 日 志 文 件 :logresolve 用 于 将 日 志 文 件 中 的<br />

IP 地 址 转 换 成 主 机 名 ;rotatelogs 用 于 循 环 处 理 日 志 文 件 , 而 不 必 杀 掉 服 务 器 。 循<br />

环 的 时 间 可 以 单 独 指 定 。<br />

注 意 Apache Web 服 务 器 还 提 供 有 关 服 务 器 活 动 和 配 置 的 详 细 报 表 , 并 允 许 你 显<br />

示 远 端 服 务 器 的 这 些 信 息 。Location 指 示 符 server-info 会 显 示 Web 服 务 器 的 配<br />

置 细 节 ,server-status 指 示 符 会 显 示 Web 进 程 。server-info 和 server-status<br />

页 面 会 显 示 这 些 报 表 , 通 过 http://localhost/serverinfo 这 个 地 址 可 以 访 问 自<br />

己 的 服 务 器 报 表 。 使 用 ExtendedStatus 指 示 符 可 打 开 详 细 的 报 表 。<br />

作 者 简 介 :<br />

Richard Petersen 是 著 名 的 Linux 专 家 , 也 是 一 位 Linux/Unix 教 育 专 家 , 所 出 版 的<br />

很 多 专 著 都 非 常 畅 销 ,《Linux 完 全 参 考 手 册 ( 原 书 第 6 版 )》 是 他 的 代 表 作 , 目 前 最<br />

新 版 本 是 第 6 版 。<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 79/85


职 场 人 生 :<br />

《PHPer》<br />

职 场 人 生<br />

1<br />

大 学 生 求 职 七 大 昏 招 —— 说 谎 ( 四 )<br />

张 大 志<br />

综 合 来 看 , 求 职 过 程 中 最 容 易 出 现 谎 言 的 就 是 两 个 地 方 : 简 历 和 面 试 。<br />

在 简 历 里 说 谎 : 孙 秀 秀 、 艾 安 雅 是 在 简 历 里 说 谎 , 夸 大 自 己 的 实 力 , 夸 大 曾 经 担<br />

任 的 职 位 , 导 致 了 面 试 时 被 戳 穿 或 不 能 自 圆 其 说 而 被 减 分 , 加 之 其 它 问 题 回 答 时 表<br />

现 欠 佳 最 终 被 干 掉 ; 在 面 试 时 说 谎 , 如 李 子 平 般 地 “ 自 作 聪 明 ” 想 给 自 己 加 分 , 后<br />

又 当 面 被 自 己 的 谎 言 害 死 失 去 了 几 乎 已 到 手 的 复 试 机 会 。<br />

当 今 社 会 生 存 压 力 大 , 说 谎 所 要 付 出 的 社 会 成 本 也 相 对 比 较 低 。 面 对 如 此 形 势<br />

, 刚 刚 进 入 职 场 的 人 难 免 抱 着 侥 幸 的 心 理 , 希 望 在 求 职 时 说 一 些 无 关 痛 痒 的 谎 言 ,<br />

借 此 给 自 己 的 面 试 加 分 赢 得 工 作 机 会 。 有 这 样 想 法 的 人 , 其 实 不 在 少 数 。<br />

谁 没 有 缺 点 和 瑕 疵 呢 ? 可 谁 又 想 在 面 对 非 常 希 望 得 到 的 机 会 时 , 暴 露 自 己 的 问<br />

题 呢 ? 这 种 心 情 , 每 个 人 力 资 源 的 工 作 人 员 都 非 常 理 解 , 因 为 我 们 也 有 自 己 的 亲 戚<br />

朋 友 同 学 姐 妹 , 也 都 曾 经 是 一 个 职 场 新 人 。<br />

但 是 , 即 便 如 此 , 求 职 时 “ 说 谎 ” 也 要 “ 讲 原 则 , 看 情 况 !”<br />

请 遵 守 以 下 几 个 原 则 :<br />

关 键 问 题 , 具 实 回 答<br />

05 年 我 们 给 一 家 外 企 找 售 前 支 持 工 程 师 , 这 个 职 位 对 英 语 要 求 很 高 。 当 时 有 个 朋<br />

友 的 老 婆 想 试 一 下 这 个 机 会 , 她 干 了 3 年 售 前 而 且 是 相 关 行 业 , 简 历 上 看 很 合 适 。 因<br />

为 这 个 职 位 老 板 是 个 只 会 说 英 语 的 家 伙 , 我 在 电 话 里 反 复 问 她 英 语 怎 么 样 , 尤 其 是<br />

口 语 。 她 都 说 没 问 题 , 等 我 见 到 她 时 用 英 语 只 问 了 一 个 问 题 , 她 嘴 都 张 不 开 。 唉 !<br />

当 时 这 位 候 选 人 没 有 被 推 荐 , 而 且 浪 费 了 双 方 的 时 间 。 从 此 之 后 , 任 何 要 求 英 语 口<br />

语 的 职 位 我 都 会 在 电 话 里 先 做 个 英 语 电 话 面 试 , 以 防 万 一 。<br />

于 此 类 此 , 每 个 应 聘 者 对 自 己 曾 经 的 工 作 内 容 、 工 作 性 质 、 职 位 都 要 实 话 实 说 ,<br />

因 为 这 是 有 据 可 查 的 , 同 时 在 这 方 面 的 任 何 夸 大 必 将 使 你 失 去 机 会 。 没 带 过 团 队 的<br />

说 领 导 过 革 命 群 众 , 让 你 讲 一 讲 就 只 能 开 始 编 了 。 没 做 过 的 事 情 , 自 然 也 说 不 圆 满<br />

。 尤 其 是 所 做 工 作 成 绩 方 面 , 一 定 请 具 实 回 答 。<br />

回 答 对 自 己 不 利 的 问 题 要 有 策 略<br />

谈 到 离 职 原 因 , 最 常 听 到 的 就 是 :“ 我 的 离 职 原 因 是 : 家 里 有 事 , 回 家 处 理 了 一<br />

下 , 公 司 不 让 请 长 假 , 我 就 不 干 了 。” 如 果 候 选 人 还 提 到 过 他 之 前 供 职 的 公 司 有 多<br />

么 多 么 的 好 , 招 聘 方 会 马 上 会 问 出 :“ 那 您 现 在 回 到 北 京 了 , 为 什 么 不 考 虑 回 到 原<br />

来 的 公 司 呢 ? 做 生 不 如 做 熟 啊 !”<br />

每 当 听 到 这 种 理 由 , 面 试 官 都 要 在 心 里 打 个 问 号 。 面 试 官 会 认 为 候 选 人 一 定 是 因 为<br />

什 么 其 它 不 方 便 说 的 理 由 离 开 了 公 司 , 也 可 能 是 被 前 公 司 FIRE 了 。 不 必 做 什 么 背 景<br />

调 查 , 有 这 种 问 题 的 候 选 人 经 常 会 被 直 接 淘 汰 掉 。<br />

也 有 很 多 人 说 , 离 开 之 前 的 公 司 就 是 因 为 领 导 是 个 混 蛋 , 没 人 性 、 不 讲 理 , 但 又<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 80/85


职 场 人 生 :<br />

《PHPer》<br />

觉 得 自 己 这 样 批 评 前 任 领 导 , 肯 定 会 给 现 在 的 招 聘 方 留 下 非 常 不 好 的 印 象 。 的 确 如<br />

此 , 还 是 希 望 你 能 实 话 时 说 , 用 人 单 位 会 认 为 你 是 一 个 难 相 处 的 你 , 毕 竟 他 是 没 什<br />

么 机 会 接 触 你 以 前 领 导 的 , 而 你 正 在 这 个 公 司 面 试 。 在 此 建 议 给 出 一 个 大 家 都 能 接<br />

受 而 且 合 理 的 理 由 , 比 如 工 作 内 容 有 变 化 , 自 己 想 找 一 个 更 感 兴 趣 或 者 对 自 己 更 有<br />

发 展 的 工 作 机 会 。<br />

有 谁 没 有 不 愉 快 的 工 作 经 历 呢 ? 有 些 还 导 致 我 们 离 开 之 前 的 公 司 。 但 这 些 不 愉 快 都<br />

是 可 以 不 讲 的 。 相 信 我 , 这 些 不 愉 快 的 经 历 被 问 及 的 可 能 性 也 不 大 , 面 试 官 没 有 你<br />

自 己 了 解 你 <br />

私 人 问 题 , 可 以 不 回 答<br />

比 如 问 及 婚 姻 和 家 庭 情 况 等 , 可 以 不 回 答 。 用 人 单 位 只 是 想 多 一 条 了 解 你 的 渠 道<br />

, 并 不 是 想 满 足 窥 私 欲 , 不 回 答 一 般 都 是 可 能 被 接 受 的 。<br />

总 之 , 没 有 具 实 回 答 的 问 题 很 容 易 在 面 试 中 被 有 经 验 的 面 试 官 发 现 。 对 任 何 问 题<br />

而 言 , 有 明 显 逻 辑 错 误 、 无 有 力 证 据 证 明 自 己 所 说 的 话 , 必 然 会 让 人 很 怀 疑 。 而 被<br />

怀 疑 在 关 键 问 题 上 说 谎 的 候 选 人 , 多 半 招 聘 方 是 不 会 去 求 证 的 , 他 们 用 最 省 时 省 力<br />

的 方 法 —— 马 上 淘 汰 这 名 候 选 人 , 请 下 一 位 进 来 。<br />

求 职 想 通 过 求 职 中 的 谎 言 不 被 戳 穿 通 过 面 试 , 要 么 祈 祷 招 聘 方 经 验 严 重 不 足 , 要<br />

么 就 是 自 己 智 商 高 过 160 永 远 可 以 把 谎 言 说 圆 满 。 否 则 , 只 说 实 话 、 多 说 实 话 是 通 过<br />

面 试 最 好 的 方 法 , 如 马 云 所 说 :“ 说 真 话 成 本 最 低 。”<br />

( 至 此 , 第 一 大 昏 招 “ 说 谎 ” 已 全 部 连 载 完 毕 , 下 一 期 第 二 大 昏 招 将 与 大 家 见 面 ,<br />

敬 请 期 待 !!!)<br />

作 者 简 介 :<br />

真 名 : 张 大 志<br />

网 名 :LEO(jobchanceleo)<br />

CSDN 十 大 明 星 博 主 ,2009CSDN MVB,ITCAST 特 约 讲 师 、IT168 特 邀 职 业 发 展 顾 问 ,<br />

主 持 “IBM 软 件 技 术 精 英 职 业 规 划 讲 堂 ”, 主 持 “CD2.0 大 会 职 业 规 划 论 坛 - 后 金 融 风<br />

暴 时 代 的 软 件 人 员 素 质 要 求 ”, 为 Zed-3、CSDN 等 知 名 国 内 外 企 业 提 供 咨 询 和 培 训 ,<br />

内 容 包 括 :HR 战 略 管 理 、 员 工 招 聘 与 培 训 , 职 业 生 涯 管 理 等 。<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 81/85


LAMP 新 书<br />

《PHPer》<br />

LAMP 新 书<br />

出 版 社 : 电 子 工 业 出 版 社<br />

作 者 : 郭 欣<br />

出 版 日 期 :2009 年 8 月<br />

《 构 建 高 性 能 Web 站 点 》<br />

图 书 介 绍 :<br />

本 书 围 绕 如 何 构 建 高 性 能 Web 站 点 , 从 多<br />

个 方 面 、 多 个 角 度 进 行 了 全 面 的 阐 述 , 涵 盖 了<br />

Web 站 点 性 能 优 化 的 几 乎 所 有 内 容 , 包 括 数 据<br />

的 网 络 传 输 、 服 务 器 并 发 处 理 能 力 、 动 态 网 页<br />

缓 存 、 动 态 网 页 静 态 化 、 应 用 层 数 据 缓 存 、 分<br />

布 式 缓 存 、Web 服 务 器 缓 存 、 反 向 代 理 缓 存 、<br />

脚 本 解 释 速 度 、 页 面 组 件 分 离 、 浏 览 器 本 地 缓<br />

存 、 浏 览 器 并 发 请 求 、 文 件 的 分 发 、 数 据 库 I/O<br />

优 化 、 数 据 库 访 问 、 数 据 库 分 布 式 设 计 、 负 载<br />

均 衡 、 分 布 式 文 件 系 统 、 性 能 监 控 等 。 在 这 些<br />

内 容 中 充 分 抓 住 本 质 并 结 合 实 践 , 通 过 通 俗 易 懂 的 文 字 和 生 动 有 趣 的 配 图 , 让 读 者 充<br />

分 并 深 入 理 解 高 性 能 架 构 的 真 相 。 同 时 , 本 书 充 分 应 用 跨 学 科 知 识 和 科 学 分 析 方 法 ,<br />

通 过 宽 泛 的 视 野 和 独 特 的 角 度 , 将 本 书 的 内 容 展 现 得 更 加 透 彻 和 富 有 趣 味 。<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 82/85


LAMP 新 书<br />

《PHPer》<br />

出 版 社 : 电 子 工 业 出 版 社<br />

作 者 : 三 扬 科 技<br />

出 版 日 期 :2009 年 9 月<br />

《 大 道 PHP》<br />

图 书 介 绍 :<br />

本 书 以 PHP 应 用 程 序 开 发 为 主 题 , 对 实 践 中<br />

必 不 可 少 的 各 项 重 要 技 术 进 行 了 全 面 介 绍 与 系<br />

统 讲 解 , 并 对 多 个 PHP 开 源 框 架 的 应 用 进 行 了 深<br />

度 整 合 与 实 战 剖 析 , 可 使 PHP 程 序 员 快 速 实 现 入<br />

门 与 精 通 。.<br />

全 书 分 7 篇 , 分 45 章 , 内 容 以 企 业 开 发 为 核<br />

心 , 包 括 PHP 的 面 向 对 象 方 法 ,PHP 与 MySQL<br />

数 据 库 的 结 合 , 最 为 流 行 的 PHP 开 源 框 架 ,PHP<br />

的 安 全 及 优 化 ,Zend 相 关 工 具 及 框 架 的 使 用 , 以<br />

及 Web 实 际 开 发 中 涉 及 到 的 所 有 常 用 技 术 , 最 后<br />

通 过 项 目 实 战 进 一 步 历 练 与 提 升 PHP 整 合 开 发<br />

技 术 。..<br />

本 书 内 容 繁 而 不 杂 、 条 理 清 晰 , 同 时 随 书 光 盘 配 备 大 容 量 的 视 频 , 对 PHP 全 线 技<br />

术 进 行 细 致 讲 解 。 本 书 不 仅 适 合 初 学 者 快 速 入 门 , 也 适 合 初 、 中 级 读 者 系 统 学 习 , 还<br />

可 作 为 PHP 开 发 人 员 的 实 践 指 导 , 同 样 适 合 各 大 专 院 校 及 相 关 培 训 机 构 作 为 教 材 或 参<br />

考 资 料 。<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 83/85


LAMP 新 书<br />

《PHPer》<br />

出 版 社 : 人 民 邮 电 出 版 社<br />

作 者 :( 美 )Scott Granneman<br />

译 者 : 成 保 栋 李 保 强<br />

出 版 日 期 :2009 年 10 月<br />

《Linux 命 令 速 查 手 册 》<br />

图 书 介 绍 :<br />

Linux 有 众 多 特 色 , 命 令 行 shell 是 最 重 要 的<br />

一 个 。 如 果 运 行 Linux 服 务 器 , 主 要 的 操 作 界 面<br />

将 很 可 能 是 shell。 如 果 你 是 桌 面 Linux 的 高 级<br />

用 户 , 那 么 可 能 总 是 喜 欢 打 开 终 端 窗 口 来 完 成<br />

操 作 。 但 如 果 你 是 Linux 新 手 , 可 能 会 认 为 以 后<br />

绝 不 会 打 开 什 么 命 令 行 窗 口 , 但 是 总 会 有 那 么<br />

一 天 的 , 而 且 使 用 Linux 越 多 , 你 就 越 有 可 能 要<br />

使 用 shell。<br />

在 许 多 情 况 下 ,shell 是 彰 显 Linux 强 大 和 简 洁 的 关 键 。 你 可 以 通 过 命 令 行 完 成 一<br />

些 用 任 何 GUI 都 无 法 完 成 的 功 能 。 不 论 KDE 或 GNOME 的 功 能 有 多 么 强 大 ( 或 者 是<br />

IceWM、XFCE 以 及 其 他 为 数 众 多 的 窗 口 环 境 ), 许 多 事 情 用 命 令 行 终 端 总 能 够 做 得<br />

更 快 和 更 有 效 。 如 果 你 想 精 通 Linux, 首 先 就 得 精 通 Linux 命 令 行 。<br />

学 习 shell 的 传 统 方 法 是 使 用 Linux 的 man page。 虽 然 man page 很 有 用 , 但 它 们<br />

提 供 的 帮 助 通 常 还 不 够 , 原 因 很 简 单 : 缺 少 使 用 示 例 。 嗯 , 虽 然 一 些 man page 偶 尔<br />

也 会 提 供 一 些 例 子 , 但 总 地 来 说 , 很 难 找 到 合 适 的 示 例 。 这 样 就 把 一 个 实 际 的 问 题 摆<br />

在 不 同 经 验 水 平 的 用 户 面 前 : 查 看 列 出 的 选 项 和 相 关 的 解 释 很 简 单 , 但 是 要 弄 明 白 在<br />

真 实 环 境 中 应 该 怎 么 使 用 那 些 选 项 , 就 完 全 是 另 外 一 回 事 儿 了 。<br />

撰 写 本 书 的 目 的 正 是 为 了 弥 补 系 统 帮 助 没 有 提 供 使 用 示 例 的 缺 憾 。 我 使 用 Linux<br />

已 经 有 十 多 年 了 , 自 认 为 对 这 个 最 喜 欢 的 操 作 系 统 已 相 当 精 通 。 而 且 , 我 对 命 令 行 也<br />

非 常 着 迷 , 我 甚 至 设 置 KDE, 让 它 在 登 录 时 自 行 启 动 Konsole(KDE 的 终 端 )。 不 过<br />

我 总 是 为 其 他 Linux 用 户 缺 少 系 统 帮 助 示 例 而 感 到 惋 惜 。 所 以 , 当 有 人 邀 请 我 撰 写 本<br />

书 , 而 且 还 说 本 书 将 由 数 百 个 演 示 重 要 Linux 命 令 行 的 使 用 例 子 组 成 时 , 我 立 即 回 复<br />

道 :" 我 等 不 及 了 ! 这 就 是 我 迫 不 及 待 马 上 想 购 买 的 那 本 书 !"<br />

现 在 你 手 中 拿 着 的 就 是 这 本 书 了 : 这 是 一 本 讲 解 你 必 须 知 道 的 Linux 命 令 的 图 书 ,<br />

它 用 翔 实 的 例 子 演 示 了 每 个 命 令 的 使 用 方 法 。 本 书 现 在 和 将 来 都 会 是 一 本 有 用 的 书 ,<br />

我 同 时 希 望 阅 读 本 书 能 够 给 你 带 来 愉 快 , 甚 至 是 一 些 乐 趣 。<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 84/85


封 底<br />

代 码 片 段<br />

网 站 :http://www.phpchina.com 投 稿 :phper@phpchina.com 《PHPer》 85/85

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!