Archive for the 'php技术' Category

You are currently browsing the archives of 乱七八糟 .

数据库设计规范

规范只是用来约束人的,用来达到有许多人使用时能更快的看懂,你也可以不使用或使用自己的一套规范。

1.数据库涉及字符规范

我们约定:采用26个英文字母(区分大小写)和0-9这十个自然数,加上下划线_组成,共63个字符。不能出现其他字符(注释除外)。

2.数据库对象命名规范

我们约定,数据库对象包括表、视图(查询)、存储过程(参数查询)、函数、约束。对象名字由前缀和实际名字组成,长度不超过30。
前缀:使用小写字母

表        tb
视图        vi
存储过程    sp
函数        fn

实际名字:实际名字尽量描述实体的内容,由单词或单词组合,每个单词的首字母大写,其他字母小写,不以数字和_开头。如

表        User_Info
视图        User_List
存储过程    User_Delete

因此,合法的对象名字类似如下。

表        tbUser_Info    tbMessage_Detail
视图        vi_Message_List
存储过程        sp_Message_Add

3.数据库表命名规范

我们约定,表名由前缀和实际名字组成。
前缀:使用小写字母tb,代表表。实际名字中,一个系统尽量采取同一单词,多个后面加_来连接区分。
因此,合法的表名类似如下。

tbMember
tbMember_Info
tbForum_Board
tbBlog_Comment1

4.字段命名规范

我们约定,字段由表的简称,实际名字组组成。如果此字段关联另外的字段,那么加下划线_连接关联表字段的字段名。
因此,合法的字段名类似如下。

UserID_MeID
UserName
UserRegDate

5.视图命名规范

我们约定,字段由前缀和实际名字组成,中间用下划线连接。
前缀:使用小写字母vi,表示视图。
因此,合法的视图名类似如下。

vi_User
vi_UserInfo

6.存储过程命名规范

我们约定,字段由前缀和实际名字加操作名字组成,中间用下划线连接。
前缀:使用小写字母sp,表示存储过程。
操作名字:Insert|Delelte|Update|Caculate|Confirm
例如:

sp_User_Insert

7.数据库设计文档规范

所有数据库设计要写成文档,文档以模块化形式表达。大致格式如下:

‘——————————————-
‘    表名:    tbUser_Info
‘    作者:    Yezi(叶子)
‘    日期:    2004-12-17
‘    版本:    1.0
‘    描述:    保存用户资料
‘    具体内容:
‘    UserId        int,自动增量        用户代码
‘    UserName    char(12)        用户名字
‘    ……
‘——————————————–

8.sql语句规范

我们约定,所有sql关键词全部大写,比如SELECT,UPDATE,FROM,ORDER,BY等。

Posted by shuck on Jul 5th 2008 | Filed in php技术 | 评论(0)

php编码规范

编码规范只是使自己或别人更容易看懂与修改的代码,如果你的代码不准备别人或以后自己去以及修改可以不使用,这是我摘抄Zend Framework PHP 编码标准上的。

B.1.  绪论

B.1.1.  适用范围

本文档提供的编码指南是给参与 Zend Framework 的开发者和团队使用的,它包含下列内容:

  • PHP File 文件格式
  • 命名约定
  • 编码风格
  • 注释文档

B.1.2.  目标

好的编码标准对任何开发项目都很重要,特别是很多开发者共同在同一项目上工作。编码标准帮助确保代码的高质量、少 bug 和容易维护。

B.2. PHP File 文件格式

B.2.1.  常规

对于只包含有 PHP 代码的文件,结束标志(”?>”)是不允许存在的,PHP自身不需要(”?>”), 这样做, 可以防止它的末尾的被意外地注入空白并显示输出。

重要:__HALT_COMPILER() 允许的任意的二进制代码的内容被 Zend Framework PHP 文件或由它们产生的文件禁止。这个功能的使用只对特殊的安装脚本开放。

B.2.2.  缩进

使用四个空格的缩进,而不使用制表符 TAB 。

B.2.3.  行的最大长度

一行 80 字符以内是比较合适, 长点也可以, 但最多为 120 个字符。

B.2.4.  行结束标志

行结束标志只能是标准的 unix 文本文件的换行,换行符在文件中表示为 10,或16进制的 0×0A。

不要使用 Macintosh 电脑的回车如(0×0D)。

不要使用 Windows 电脑的回车换行组合如(0×0D,0×0A)。

B.3.  命名约定

B.3.1.  类

Zend Framework 的类命名总是对应于其所属文件的目录结构的,Zend Framework 的根目录是 “Zend/”,所有的类在其下按等级存放。

类名只允许有字母数字字符,但不鼓励使用数字。下划线只允许做路径分隔符,例如 Zend/Db/Table.php 文件里对应的类名称是 Zend_Db_Table。

如果类名包含多个单词,每个单词的第一个字母必须大写,连续的大写是不允许的,例如 “Zend_PDF” 是不允许的,而 “Zend_Pdf” 是可接受的。

由 Zend 或其参与 Zend Framework 项目的伙伴公司发行的类必须以 “Zend_” 开头并且必须按等级放在 “Zend/”目录下。

可接受的类名的例子:

Zend_Db

Zend_View

Zend_View_Helper

重要: 最终用户写的代码,不要以 “Zend_” 开头。

B.3.2.  接口

接口类也必须遵循同样的约定(如上所述),但必须以 “Interface” 结尾,比如这些例子:

Zend_Log_Adapter_Interface
Zend_Controller_Dispatcher_Interface

B.3.3.  文件名

对于其它文件,只有字母数字字符、下划线和短横线(”-”)可用,空格是不允许的。

包含任何 PHP 代码的任何文件必须以 “.php” 扩展名结尾。这些例子给出可接受的文件名,它们包含的类名都在上述章节的例子中:

Zend/Db.php

Zend/Controller/Front.php

Zend/View/Helper/FormRadio.php

文件名必须遵循上述的对应类名的规则。

B.3.4.  函数和方法

函数名只包含字母数字字符,但不鼓励使用数字,下划线是不允许的。

函数名总是以小写开头,当函数名包含多个单词,每个子的首字母必须大写,这就是所谓的 “驼峰” 格式。

我们鼓励使用冗长的名字,这样容易理解代码。

这些是可接受的函数名的例子:

filterInput()

getElementById()

widgetFactory()

对于面向对象编程,对象的访问器总是以 “get” 或 “set” 为前缀。当使用设计模式如 单态模式(singleton)或工厂模式(factory),方法的名字应当包含模式的名字,这样容易从名字识别设计模式。

在对象中的方法,声明为 “private” 或 “protected” 的, 名称的首字符必须是一个单个的下划线,这是唯一的下划线在方法名字中的用法。声明为 “public” 的从不以下划线开头。

全局函数 (”floating functions”) 允许但不鼓励,建议把这类函数封装到静态类里。

B.3.5.  变量

变量只包含数字字母字符,不鼓励使用数字,下划线不接受。

声明为 “private” 或 “protected” 的类成员变量名必须以一个单个下划线开头,这是唯一的下划线在变量名中的用法,声明为 “public” 的从不以下划线开头。

象函数名(见上面 3.3 节)一样,变量名总以小写字母开头并遵循“驼峰式”命名约定。

我们鼓励使用冗长的名字,这样容易理解代码。除非在小循环里,不鼓励使用简洁的名字如 “$i” 和 “$n” 。如果一个循环超过 20 行代码,索引的变量名必须有个具有描述意义的名字。

B.3.6.  常量

常量包含数字字母字符和下划线,数字允许作为常量名。

常量名的所有字母必须大写。

为加强可读性,常量中的单词必须以下划线分隔,例如可以这样 EMBED_SUPPRESS_EMBED_EXCEPTION 但不许这样 EMBED_SUPPRESSEMBEDEXCEPTION

常量必须通过 “const” 定义为类的成员,不鼓励使用 “define” 定义的全局常量。

B.4.  编码风格

B.4.1. PHP 代码划分(Demarcation)

PHP 代码总是用完整的标准的 PHP 标签定界:

<?php

?>

短标签( )是不允许的,只包含 PHP 代码的文件,不要结束标签 (参见 第 B.2.1 节 “ 常规 ”)。

B.4.2.  字符串

B.4.2.1.  字符串文字

当字符串是文字(不包含变量),用单引号( apostrophe )来括起来:

$a = 'Example String';

B.4.2.2.  包含单引号(’)的字符串文字

当文字字符串包含单引号(apostrophe )就用双引号括起来,特别在 SQL 语句中:

$sql = "SELECT `id`, `name` from `people` WHERE `name`='Fred' OR `name`='Susan'";

在转义单引号时,上述语法是首选的。

B.4.2.3.  变量替换

变量替换有下面两种形式:

$greeting = "Hello $name, welcome back!";

$greeting = "Hello {$name}, welcome back!";

为保持一致,这个形式不允许:

$greeting = "Hello ${name}, welcome back!";

B.4.2.4.  字符串连接

字符串用 “.” 操作符连接,在它的前后加上空格以提高可读性:

$company = 'Zend' . ' ' . 'Technologies';

当用 “.” 操作符连接字符串,代码可以分成多个行,也是为提高可读性。在这些例子中,每个连续的行应当由 whitespace 来填补,例如 “.” 和 “=” 对齐:

$sql = "SELECT `id`, `name` FROM `people` "
     . "WHERE `name` = 'Susan' "
     . "ORDER BY `name` ASC ";

B.4.3.  数组

B.4.3.1.  数字索引数组 Numerically Indexed Arrays

索引不能为负数

建议数组索引从 0 开始。

当用 array 声明有索引的数组,在每个逗号的后面价格空格以提高可读性:

$sampleArray = array(1, 2, 3, 'Zend', 'Studio');

也可以用 “array” 声明多行有索引的数组,在每个连续行的开头要用空格填补对齐:

$sampleArray = array(1, 2, 3, 'Zend', 'Studio',
                     $a, $b, $c,
                     56.44, $d, 500);

B.4.3.2.  关联数组

当用 声明关联数组,array 我们鼓励把代码分成多行,在每个连续行的开头用空格填补来对齐键和值:

$sampleArray = array('firstKey'  => 'firstValue',
                     'secondKey' => 'secondValue');

B.4.4.  类

B.4.4.1.  类的声明

用下面的约定来命名类。

花括号总是从类名下一行开始。

每个类必须有一个符合 PHPDocumentor 标准的文档块。

四个空格的缩进。

每个 PHP 文件中只有一个类。

放另外的代码到类里允许但不鼓励。在这些文件中,用两行空格来分隔类和其它代码。

这是个可接受的类的例子:

/**
 * Documentation Block Here
 */
class SampleClass
{
    // entire content of class
    // must be indented four spaces
}

B.4.4.2.  类成员变量

必须用下面的变量名约定来命名类成员变量。

变量的声明必须在类的顶部,要先于方法的声明。

不允许使用 var (因为 ZF 是基于 PHP 5 的 ),要用 privateprotectedpublic。直接访问变量允许但不鼓励,最好使用访问器 (set/get)。

B.4.5.  函数和方法

B.4.5.1.  函数和方方声明

必须用下面的变量名约定来命名函数。

在类中的函数必须用 privateprotectedpublic 声明它们的可见性。

象类一样,花括号从函数名的下一行开始,函数名和括参数的圆括号中间没有空格。

强烈反对使用全局函数。

可接受的在类中的函数声明的例子:

/**
 * Documentation Block Here
 */
class Foo
{
    /**
     * Documentation Block Here
     */
    public function bar()
    {
        // entire content of function
        // must be indented four spaces
    }
}

注: 传址(Pass-by-reference)只在函数声明中允许:

/**
 * Documentation Block Here
 */
class Foo
{
    /**
     * Documentation Block Here
     */
    public function bar(&$baz)
    {}
}

传址在调用时是禁止的。

返回值不能在圆括号中,这妨碍可读性而且如果将来方法被修改成传址方式,代码会有问题。

/**
 * Documentation Block Here
 */
class Foo
{
    /**
     * WRONG
     */
    public function bar()
    {
        return($this->bar);
    }

    /**
     * RIGHT
     */
    public function bar()
    {
        return $this->bar;
    }
}

B.4.5.2.  函数和方法的用法

函数的参数用逗号和紧接着的空格分开,下面的例子中的函数带有三个参数:

threeArguments(1, 2, 3);

传址方式在调用的时候是禁止的,参见函数的声明一节如何正确使用函数的传址方式。

带有数组参数的函数,函数的调用可包括 “array” 并分成多行来提高可读性,同时,书写数组的标准仍然适用:

threeArguments(array(1, 2, 3), 2, 3);

threeArguments(array(1, 2, 3, 'Zend', 'Studio',
                     $a, $b, $c,
                     56.44, $d, 500), 2, 3);

B.4.6.  控制语句

B.4.6.1. If / Else / Elseif

使用 if and elseif 的控制语句在条件语句的圆括号前后都必须有一个空格。

在圆括号里的条件语句,操作符必须用空格分开,鼓励使用多重圆括号以提高在复杂的条件中划分逻辑组合。

前花括号必须和条件语句在同一行,后花括号单独在最后一行,其中的内容用四个空格缩进。

if ($a != 2) {
    $a = 2;
}

下面的例子示例 “if” 语句, 包括 “elseif” 或 “else” 的格式约定:

if ($a != 2) {
    $a = 2;
} else {
   $a = 7;
}

if ($a != 2) {
    $a = 2;
} elseif ($a == 3) {
   $a = 4;
} else {
   $a = 7;
}

在有些情况下, PHP 允许这些语句不用花括号,但在 ZF 代码标准里,它们(”if”、 “elseif” 或 “else” 语句)必须使用花括号。

“elseif” 是允许的但强烈不鼓励,我们支持 “else if” 组合。

B.4.6.2. Switch

在 “switch” 结构里的控制语句在条件语句的圆括号前后必须都有一个单个的空格。

“switch” 里的代码必须有四个空格缩进,在”case”里的代码再缩进四个空格。

switch ($numPeople) {
    case 1:
        break;

    case 2:
        break;

    default:
        break;
}

switch 语句中必须有 default

注: 有时候,在 falls through 到下个 case 的 case 语句中不写 break or return 很有用。为了区别于 bug,任何 case 语句中,所有不写 break or return 的地方必须有 “// break intentionally omitted” 这样的注释。

B.4.7.  注释文档

B.4.7.1.  格式

所有文档块 (”docblocks”) 必须和 phpDocumentor 格式兼容,phpDocumentor 格式的描述超出了本文档的范围,关于它的详情,参考:http://phpdoc.org/

所有 Zend Framework 或和它一起工作的源代码必须在每个文件的顶部包含文件级 (”file-level”)的 docblock ,在每个类的顶部放置一个 “class-level” 的 docblock。下面是一些例子:

B.4.7.2.  文件

每个包含 PHP 代码的文件必须至少在文件顶部包含这些 phpDocumentor 标签:

/**
 * 文件的简短描述
 *
 * 文件的详细描述(如果有的话)... ...
 *
 * LICENSE: 一些 license 信息
 *
 * @copyright  2005 Zend Technologies
 * @license    http://www.zend.com/license/3_0.txt   PHP License 3.0
 * @version    $Id:$
 * @link       http://dev.zend.com/package/PackageName
 * @since      File available since Release 1.2.0
*/

B.4.7.3.  类

每个类必须至少包含这些 phpDocumentor 标签:

/**
 * 类的简述
 *
 * 类的详细描述 (如果有的话)... ...
 *
 * @copyright  2005 Zend Technologies
 * @license    http://www.zend.com/license/3_0.txt   PHP License 3.0
 * @version    Release: @package_version@
 * @link       http://dev.zend.com/package/PackageName
 * @since      Class available since Release 1.2.0
 * @deprecated Class deprecated in Release 2.0.0
 */

B.4.7.4.  函数

每个函数,包括对象方法,必须有最少包含下列内容的文档块(docblock):

  • 函数的描述
  • 所有参数
  • 所有可能的返回值

因为访问级已经通过 “public”、 “private” 或 “protected” 声明, 不需要使用 “@access”。

如果函数/方法抛出一个异常,使用 @throws:

@throws exceptionclass [description]

Posted by shuck on Jul 5th 2008 | Filed in php技术 | 评论(0)

软件测试工作流程图—–软件测试部与软件开发部有用的东西

有7个图,打开可能会很慢,但对软件测试人员以及软件的管理人员会有很大的帮助。

原文连接:http://test1.anyp.com/ujohn/12773-106588.aspx

测试教材:测试工作流程图.doc 测试员培训入门教材 软件工程中的测试流程模型与管理 软件的界面测试

单元测试工作指南

Posted by shuck on Jun 26th 2008 | Filed in php技术 | 评论(0)

zend framework 1.5 出现 Internal 500 错误

解决方法:

1.apache/conf/httpd.conf 中LoadModule rewrite_module modules/mod_rewrite.so 前而的#没有去除

2.htaccess文件中的RewriteEngine on没有设置成on

Posted by shuck on Jun 25th 2008 | Filed in php技术 | 评论(0)

ZendFramework-1.5.2下载

今天下载ZendFramework,跑到zend的网站去,竟然还要注册后才下,本来访问国外的网站速度就慢,还要注册,恼火死了,现在我贴个地址    下载

Posted by shuck on Jun 12th 2008 | Filed in php技术 | 评论(1)

php 生成静态页面

在喜悦国际村看到的一篇讨论贴还可以

静态页面的生成一般有这么几个思路了。。
1。程序编写过程中。不使用直接输出的语句。而时将所有的输出连接至输出字符串,输出完成后。再直接将输出字符串内容写入文件
2。编写中按照正常的方式编写。通过ob函数组捕获输出。然后将输出写入文件
3。使用模板类时,用get/fetch一类的方法获取输出。并写入文件。

具体实现上又有这两种方法
1。管理后台添加记录时,直接生成目标html页面,并且前台调用连接直接指向生成的html页面。这种方法程优点是程序效率最高。服务器负荷轻,不过由于生成的是纯静态页面,一旦页面样式上有所改动就必须重新生成所有的内容页。所以实际使用中应用一般不是太多。更多的是使用js,ssi,xml/xsl等客户端手段,生成的静态文件中仅保存数据,不涉及样式,这样能达到速度和维护性的平衡,不过相对前后台程序要复杂些(应用这种方法时,由于内容为纯静态,可以搭配单独编译的纯静态的apache使用。。效率和资源占用上比包含动态内容支持的要更佳)

2。前台访问链接指向php程序,php程序首先检查是否存在相应的静态文件。如果静态文 件不存在。则生成并重定向至此文件,否则直接重定向。这种方法实际使用中一般和apache的url_rewrite功能一起使用。将php的文件地址重 为html的形式,有利于搜索引擎的检索。这种方法在效率上略有损失,不过程序结构简单,便于调整,在访问量不是很大时使用很合适。。

下面是此村村长说的,讲得很好

生成静态页的主要目的是什么? 提高效率.
在这里我以村子为例来说明我的构架, 请注意, 这个构架没有完全在村子使用.

———————–用户读帖子,存在静态页————–A————–
用户 :访问  http://www.phpx.com/happy/static/top92092.html
apache:  文件存在. 输出文件
用户 :得到页面

———————–用户读帖子,静态页未生成或已删除—-B————–
用户 : 访问  http://www.phpx.com/happy/static/top92092.html
apache:     文件不存在. 重定向到404处理程序 (httpd.conf加 ErrorDocument 404 /errprocess.php 指令)
errprocess.php: 得到用户请求的页面及各种变量. 是否需要进行生成静态的页面?
首字母为: top ,是需要生成的页面,调用showthread.php (需改进结构将页面输出到变量$pagecontent)
得到页面的内容$pagecontent, 将$pagecontent存成静态文件 top92092.html,
最后可以:
a) header(”location:http://www.phpx.com/happy/static/top92092.html“)
b) header(”HTTP/1.1 200 OK”); 以后 直接输出$pagecontent, 要注意img src等相对链接的位置了!!!
用户 : 得到页面 或者重定向到 A 操作.

———————–用户回帖子————————–C————-
用户 : 回复帖子 top92092.html
newreply.php: 删除静态文件 top92092.html (如果用户信息也是生成静态js, 还要同时删除 用户id.js )
数据入库等常规操作.
最后可以:
a) header(”location:http://www.phpx.com/happy/static/top92092id.html“)
b) 或者改进 newreply.php 在入库后, 调用 showthread.php 得到页面的内容$pagecontent,
将$pagecontent存成静态文件 top92092.html, 输出$pagecontent;不过为了方法统一,
建议使用b)重定向只使用一个静态生成点.
用户 :用户得到页面 或 到B操作

———————–用户发表新帖————————D————
用户 : 发表新帖子
newthread.php:  (如果用户信息也是生成静态js, 还要同时删除 用户id.js ) 数据入库等常规操作.
最后可以:
a) header(”location:http://www.phpx.com/happy/static/top新帖id.html“)
b) 或者改进 newthread.php 在入库后, 调用 showthread.php 得到页面的内容$pagecontent,
将$pagecontent存成静态文件 top92092.html, 输出$pagecontent;不过为了方法统一,
建议使用b)重定向只使用一个静态生成点.
用户 :用户得到页面 或 到B操作

———————–村子更换html风格———————E———
管理员: 删除  static 目录下的全部文件
用户访问页面, 页面不存在, 执行 B 操作

(
关键点:
1 不可以直接http://www.phpx.com/happy/top92092.html 这样其他设计的时候有问题

2 要注意文件位置, 比如 happy/images/a.gif 用户访问 happy/showthread.php时
代码写成 <img src=images/a.gif> 看到是对的. 而生成静态页后. 页面位置变成了
happy/static/top92092.html  这时图片的位置就不对了. 变成了 ../images/a.gif
所以showthread.php 写成 <image=”/happy/images/a.gif”> 就不会有错了.
这当然会带来一些问题比如以后访问位置改成  www.phpx.com/bbs/ 那showthread.php代码
就需要修改了. 类似的还有很多, 比如javascript一类的.

3 帖子需要统计点击率, 怎么实现? 在生成文件时加代码 <img src=/happy/clicked.php?id=92092 width=1 height=1> ,由clicked.php 去更新点击数

4 用户信息, 如用户发贴数怎样保持最新? 用javascript
a) 将用户信息部分改成 <script src=/happy/uinfo.php?uid=用户的id></script> 这样无论用户发贴数变化或者更新头像都是没有问题的
b)用户信息也用其类似办法生成静态 <script src=/happy/static/用户的id.js></script>

5)一个目录下的文件过多就会有问题了.如果帖子量很大 ,全部指向 /happy/static/top帖子id.html
不再是一个好的设计. 可以做变通处理 比如 /happy/static/版面id/top帖子id.html 将每个版面的
帖子放置一个目录等. 类似的算法还很多.

6) 这种设计会提高效率么?
我们来算算就知道了
不采用以上结构. 一个帖子帖子有10个回复 和 100次浏览(简单计算, 不考虑帖子锁定, 用户权限等等)

每次浏览 需选出帖子内容,选出每个帖子的用户信息(使用join操作) 更新点击数. 100*3 =300次 数据库查询
每次回复 帖子入库 更新原帖回复数, 更新用户发贴数. 10*2 =20次 数据库查询

也就是这个例子需要做 320次数据库查询. 而且其中在浏览时要将用户表 和 帖子表做join
这两个表通常会比较大.(如果不做join, 至少每次浏览加一次数据库查询. 因为帖子已经选出, 可以遍历获得全部发贴
人的id, 再select ** where uid in (全部发帖人id) 获得这些人的信息 )

采用静态结构的情况:
a) 用户信息动态
浏览: 有10个回复, 则被删除十次.
生成10次静态文件, 需做需选出帖子内容,选出每个帖子的用户信息(使用join操作)操作: 10*2=20次
100次浏览: clicked.php更新帖子点击数 100*1 =100 次 uinfo.php 获得信息  100*1 =100 次
每次回复 帖子入库 更新原帖回复数, 更新用户发贴数. 10*2 =20次 数据库查询
总共需要240次数据库查询

b) 用户信息也静态
浏览: 有10个回复, 则被删除十次.
生成10次静态文件, 需做需选出帖子内容,选出每个帖子的用户信息(使用join操作)操作: 10*2=20次
100次浏览: clicked.php更新帖子点击数 100*1 =100 次
每次回复 帖子入库 更新原帖回复数, 更新用户发贴数.   10*2 =20次 数据库查询
生成新的userid.js 10*1 =10次 数据库查询
总共需要150次数据库查询

对比, 前者需要320次查询, 其中100次为两个大表join .
a) 需要240次数据库查询,10次大表join
b) 需要150次数据库查询,10次大表join

这里面还没有考虑调用 静态页 和 调用php的内存及cpu开销. 仅数据库一项差距就比较大了.

404 主要还是为了最大限度的提升性能.

下面再就 404方式和php cache 做一个比较.
(这里假设showart.php 为php cache的运行程序)

文件存在时:
php cache方式 (  showart.php ? id=1234)
apache  IO判断 showart.php 是否存在 ,  装入showart.php
showart.php IO判断是否存在 static/1234.html . 文件存在, 输出
两次IO. 其中一次为apache ,一次为 showart.php
404 方式  ( static/1234.html)
apache  IO判断 static/1234.html 是否存在,文件存在, 输出
Apache有一次IO
文件不存在时:
php cache方式 (  showart.php ? id=1234)
apache  IO判断 showart.php 是否存在 ,  装入showart.php
showart.php IO判断是否存在 static/1234.html . 文件不存在,
showart.php 调用 showthread.php 取得页面内容,
生成static/1234.html  .  输出
四次IO ,  apache 一次, showart.php 三次

404 方式  ( static/1234.html)
apache  IO判断 static/1234.html 是否存在,文件不存在,
apache  IO判断 errprocess.php 是否存在 ,  装入errprocess.php
errprocess.php 调用 showthread.php 取得页面内容,
生成static/1234.html  .  输出
四次IO ,  apache 两次, showart.php 两次

以上的计算是近似计算不是实际情况. 但是数量基本是正确的.

而一个页面, 大部分时间是存在访问, 少量时间是不存在访问.
比如BBS帖子,  看帖和发贴的比率至少有5:1 吧.
如果是新闻类的内容. 估计就更大, 可能达到 数百, 数千比一
尽管每一次访问减少是一次IO. 但是访问量增大的时候, 效果就非常明显.

这里还没有考虑存在访问时的内存效率
另外 apache io 的效率要高于php io


1。对于同一目录下文件过多引起性能问题的解决方法
a.对帖子id根据数据库中字段长度做str_pad:比方说id为123456,数据库中为int(11),则id处理为00000123456,
b.考虑到lux下一般同一下文件到达四位数会有性能影响,对其做切割,最后路径为static/00/000/123/456.html
c.然后以此为路径储存生成的文件(注意要兴建逐层的路径,分割没必要太细,否则会大大增加磁盘空间占用,降低系统性能)
2。每次回复帖子都要删除文件。并重新读取数据库,重新生成整个帖子文件这块似乎有些繁琐。这块的操作也是很多的。
我的方法是帖子数据用js来储存数据,这样回复帖子/编辑帖子时候只要根据表单数据对js文本进行累加就行了。。避免了频繁的删除,兴建文件和读取数据库带来的性能影响,不过对js处理时候要注意文件的锁定。
3。对于用户信息。头像等动态内容的处理
由于同一个帖子页面中往往有数十个用户信息需要获取。如果直接用<script>的方法读取那么就需要打开数十个http连接。无论从client和server短都是个不小的负担。也减慢了整体速度。
这里可以吧所有的用户id连接起来。通过一个<script>标签一次性取出,并存入数组。调用的时候通过js函数来显示。这样效率会更高。而且服务器压力更小

原地址:http://www.phpx.com/happy/viewthread.php?tid=92092&extra=&highlight=%BE%B2%CC%AC&page=4 

Posted by shuck on Jun 10th 2008 | Filed in php技术 | 评论(0)

javascript倒计时

查看效果

  1. <script language="JavaScript">
  2. <!-- //
  3. var startTime = new Date();
  4. var EndTime=startTime.getTime()+2*1000;  //2 是秒数
  5. function GetRTime(){
  6. var NowTime = new Date();
  7. var nMS =EndTime - NowTime.getTime();
  8. //var nD =Math.floor(nMS/(1000 * 60 * 60 * 24));
  9. var nH=Math.floor(nMS/(1000*60*60)) % 24;
  10. var nM=Math.floor(nMS/(1000*60)) % 60;
  11. var nS=Math.floor(nMS/1000) % 60;
  12. &nbsp;//document.getElementById("RemainD").innerHTML=nD;
  13. &nbsp;document.getElementById("RemainH").innerHTML=nH;
  14. &nbsp;document.getElementById("RemainM").innerHTML=nM;
  15. &nbsp;document.getElementById("RemainS").innerHTML=nS;
  16. if(nMS>5*59*1000&&nMS<=5*60*1000)
  17. {
  18. &nbsp;alert("还有最后五分钟!");
  19. }
  20. if(nMS>1000){
  21. &nbsp;setTimeout("GetRTime()",1000);
  22. &nbsp;}
  23. }
  24. window.onload=GetRTime;
  25. // -->
  26. </script>
  27. <p id="CountMsg">倒计时还有:<strong id="RemainH">XX</strong>时<strong id="RemainM">XX</strong>分<strong id="RemainS">XX</strong>秒</p>

Posted by shuck on Jun 7th 2008 | Filed in php技术 | 评论(0)

javascript时间选择器

在网上找的javascript时间选择器,功能很强大,写得很好,浏览器兼容也很好
11.bmp

查看演示

压缩包里有作者的详细说明 ,仔细看下用法就可以了

下载 

Posted by shuck on Jun 7th 2008 | Filed in php技术 | 评论(2)

javascript 字体颜色选择器

由于需要做个网站名称颜色由用户自己修改的功能,在网上找了下,好像就这个还可以,我没改,有时间封装下。
我还想字体样式,网上没找到,由于时间仅所以就放弃了,有时间看下编辑器的样式是怎么搞的,在扣出来。

  1. <HTML>
  2. <HEAD>
  3. <TITLE> Office 风格颜色选择器</TITLE>
  4. <META NAME="Generator" CONTENT="EditPlus">
  5. <META NAME="Author" CONTENT="">
  6. <META NAME="Keywords" CONTENT="">
  7. <META NAME="Description" CONTENT="">
  8. </HEAD>
  9.  
  10. <BODY>
  11. <script language=javascript>
  12. <!--
  13.  
  14. //注意:只有把<script>标签放在<body>标签内才可以正常使用“其它颜色”功能
  15.  
  16. document.write("<OBJECT id=\"dlgHelper\" CLASSID=\"clsid:3050f819-98b5-11cf-bb82-00aa00bdce0b\" width=\"0px\" height=\"0px\"></OBJECT>");
  17. var ocolorPopup = window.createPopup();
  18. var ecolorPopup=null;
  19.  
  20. function colordialogmouseout(obj){
  21.     obj.style.borderColor="";
  22.     obj.bgColor="";
  23. }
  24.  
  25. function colordialogmouseover(obj){
  26.     obj.style.borderColor="#0A66EE";
  27.     obj.bgColor="#EEEEEE";
  28. }
  29.  
  30. function colordialogmousedown(color){
  31.     ecolorPopup.value=color;
  32.     //document.body.bgColor=color;
  33.     ocolorPopup.document.body.blur();
  34. }
  35.  
  36. function colordialogmore(){
  37.     var sColor=dlgHelper.ChooseColorDlg(ecolorPopup.value);
  38.     sColor = sColor.toString(16);
  39.     if (sColor.length < 6) {
  40.         var sTempString = "000000".substring(0,6-sColor.length);
  41.         sColor = sTempString.concat(sColor);
  42.     }
  43.     ecolorPopup.value="#"+sColor.toUpperCase();
  44.     //document.body.bgColor="#"+sColor.toUpperCase();
  45.     ocolorPopup.document.body.blur();
  46. }
  47.  
  48. function colordialog(){
  49.     var e=event.srcElement;
  50.     e.onkeyup=colordialog;
  51.     ecolorPopup=e;
  52.     var ocbody;
  53.     var oPopBody = ocolorPopup.document.body;
  54.     var colorlist=new Array(40);
  55.     oPopBody.style.backgroundColor = "#f9f8f7";
  56.     oPopBody.style.border = "solid #999999 1px";
  57.     oPopBody.style.fontSize = "12px";
  58.  
  59.     colorlist[0]="#000000";    colorlist[1]="#993300";    colorlist[2]="#333300";    colorlist[3]="#003300";
  60.     colorlist[4]="#003366";    colorlist[5]="#000080";    colorlist[6]="#333399";    colorlist[7]="#333333";
  61.  
  62.     colorlist[8]="#800000";    colorlist[9]="#FF6600";    colorlist[10]="#808000";colorlist[11]="#008000";
  63.     colorlist[12]="#008080";colorlist[13]="#0000FF";colorlist[14]="#666699";colorlist[15]="#808080";
  64.  
  65.     colorlist[16]="#FF0000";colorlist[17]="#FF9900";colorlist[18]="#99CC00";colorlist[19]="#339966";
  66.     colorlist[20]="#33CCCC";colorlist[21]="#3366FF";colorlist[22]="#800080";colorlist[23]="#999999";
  67.  
  68.     colorlist[24]="#FF00FF";colorlist[25]="#FFCC00";colorlist[26]="#FFFF00";colorlist[27]="#00FF00";
  69.     colorlist[28]="#00FFFF";colorlist[29]="#00CCFF";colorlist[30]="#993366";colorlist[31]="#CCCCCC";
  70.  
  71.     colorlist[32]="#FF99CC";colorlist[33]="#FFCC99";colorlist[34]="#FFFF99";colorlist[35]="#CCFFCC";
  72.     colorlist[36]="#CCFFFF";colorlist[37]="#99CCFF";colorlist[38]="#CC99FF";colorlist[39]="#FFFFFF";
  73.  
  74.     ocbody = "";
  75.     ocbody += "<table CELLPADDING=0 CELLSPACING=3>";
  76.     ocbody += "<tr height=\"20\" width=\"20\"><td align=\"center\"><table style=\"border:1px solid #808080;\" width=\"12\" height=\"12\" bgcolor=\""+e.value+"\"><tr><td></td></tr></table></td><td bgcolor=\"eeeeee\" colspan=\"7\" style=\"font-size:12px;\" align=\"center\">当前颜色</td></tr>";
  77.     for(var i=0;i<colorlist.length;i++){
  78.         if(i%8==0)
  79.             ocbody += "<tr>";
  80.         ocbody += "<td width=\"14\" height=\"16\" style=\"border:1px solid;\" onMouseOut=\"parent.colordialogmouseout(this);\" onMouseOver=\"parent.colordialogmouseover(this);\" onMouseDown=\"parent.colordialogmousedown('"+colorlist[i]+"')\" align=\"center\" valign=\"middle\"><table style=\"border:1px solid #808080;\" width=\"12\" height=\"12\" bgcolor=\""+colorlist[i]+"\"><tr><td></td></tr></table></td>";
  81.         if(i%8==7)
  82.             ocbody += "</tr>";
  83.     }
  84.     ocbody += "<tr><td align=\"center\" height=\"22\" colspan=\"8\" onMouseOut=\"parent.colordialogmouseout(this);\" onMouseOver=\"parent.colordialogmouseover(this);\" style=\"border:1px solid;font-size:12px;cursor:default;\" onMouseDown=\"parent.colordialogmore()\">其它颜色</td></tr>";
  85.     ocbody += "</table>";
  86.  
  87.     oPopBody.innerHTML=ocbody;
  88.     ocolorPopup.show(e.offsetLeft, e.offsetTop+e.offsetHeight, 158, 147, document.body);
  89. }
  90. //-->
  91. </script>
  92. 选择颜色:<input name="sel1" type="text" onFocus="colordialog()"></BODY>
  93. </HTML>

Posted by shuck on Apr 18th 2008 | Filed in php技术 | 评论(0)

php 读取excel

这不是我写的,我志修改了一下,使调用更方便

  1. <?php
  2. require_once 'ExcelReader.class.php';   //调用下面的代码
  3.  
  4. // ExcelFile($filename, $encoding);
  5. $data = new Spreadsheet_Excel_Reader();
  6. $data->setOutputEncoding('GB2312');
  7. $data->setUTFEncoder('mb');         // iconv  or mb
  8. $data->setRowColOffset(1);
  9. $data->read('book2.xls');
  10. $array = $data->outPutData(); //返回2维数组
  11. print_r($array);
  12. ?>
  1. <?php
  2. define('NUM_BIG_BLOCK_DEPOT_BLOCKS_POS', 0x2c);
  3. define('SMALL_BLOCK_DEPOT_BLOCK_POS', 0x3c);
  4. define('ROOT_START_BLOCK_POS', 0x30);
  5. define('BIG_BLOCK_SIZE', 0x200);
  6. define('SMALL_BLOCK_SIZE', 0x40);
  7. define('EXTENSION_BLOCK_POS', 0x44);
  8. define('NUM_EXTENSION_BLOCK_POS', 0x48);
  9. define('PROPERTY_STORAGE_BLOCK_SIZE', 0x80);
  10. define('BIG_BLOCK_DEPOT_BLOCKS_POS', 0x4c);
  11. define('SMALL_BLOCK_THRESHOLD', 0x1000);
  12. // property storage offsets
  13. define('SIZE_OF_NAME_POS', 0x40);
  14. define('TYPE_POS', 0x42);
  15. define('START_BLOCK_POS', 0x74);
  16. define('SIZE_POS', 0x78);
  17. define('IDENTIFIER_OLE', pack("CCCCCCCC",0xd0,0xcf,0x11,0xe0,0xa1,0xb1,0x1a,0xe1));
  18.  
  19. //echo 'ROOT_START_BLOCK_POS = '.ROOT_START_BLOCK_POS."\n";
  20.  
  21. //echo bin2hex($data[ROOT_START_BLOCK_POS])."\n";
  22. //echo "a=";
  23. //echo $data[ROOT_START_BLOCK_POS];
  24. //function log
  25.  
  26. function GetInt4d($data, $pos) {
  27.         return ord($data[$pos]) | (ord($data[$pos+1]) << 8) | (ord($data[$pos+2]) << 16) | (ord($data[$pos+3]) << 24);
  28. }
  29.  
  30.  
  31. class OLERead {
  32.     var $data = '';
  33.    
  34.    
  35.     function OLERead(){
  36.        
  37.        
  38.     }
  39.    
  40.     function read($sFileName){
  41.        
  42.         // check if file exist and is readable (Darko Miljanovic)
  43.         if(!is_readable($sFileName)) {
  44.             $this->error = 1;
  45.             return false;
  46.         }
  47.        
  48.         $this->data = @file_get_contents($sFileName);
  49.         if (!$this->data) { 
  50.             $this->error = 1;
  51.             return false;
  52.            }
  53.            //echo IDENTIFIER_OLE;
  54.            //echo 'start';
  55.            if (substr($this->data, 0, 8) != IDENTIFIER_OLE) {
  56.             $this->error = 1;
  57.             return false;
  58.            }
  59.         $this->numBigBlockDepotBlocks = GetInt4d($this->data, NUM_BIG_BLOCK_DEPOT_BLOCKS_POS);
  60.         $this->sbdStartBlock = GetInt4d($this->data, SMALL_BLOCK_DEPOT_BLOCK_POS);
  61.         $this->rootStartBlock = GetInt4d($this->data, ROOT_START_BLOCK_POS);
  62.         $this->extensionBlock = GetInt4d($this->data, EXTENSION_BLOCK_POS);
  63.         $this->numExtensionBlocks = GetInt4d($this->data, NUM_EXTENSION_BLOCK_POS);
  64.        
  65.     /*
  66.         echo $this->numBigBlockDepotBlocks." ";
  67.         echo $this->sbdStartBlock." ";
  68.         echo $this->rootStartBlock." ";
  69.         echo $this->extensionBlock." ";
  70.         echo $this->numExtensionBlocks." ";
  71.         */
  72.         //echo "sbdStartBlock = $this->sbdStartBlock\n";
  73.         $bigBlockDepotBlocks = array();
  74.         $pos = BIG_BLOCK_DEPOT_BLOCKS_POS;
  75.        // echo "pos = $pos";
  76.     $bbdBlocks = $this->numBigBlockDepotBlocks;
  77.        
  78.             if ($this->numExtensionBlocks != 0) {
  79.                 $bbdBlocks = (BIG_BLOCK_SIZE - BIG_BLOCK_DEPOT_BLOCKS_POS)/4;
  80.             }
  81.        
  82.         for ($i = 0; $i < $bbdBlocks; $i++) {
  83.               $bigBlockDepotBlocks[$i] = GetInt4d($this->data, $pos);
  84.               $pos += 4;
  85.         }
  86.        
  87.        
  88.         for ($j = 0; $j < $this->numExtensionBlocks; $j++) {
  89.             $pos = ($this->extensionBlock + 1) * BIG_BLOCK_SIZE;
  90.             $blocksToRead = min($this->numBigBlockDepotBlocks - $bbdBlocks, BIG_BLOCK_SIZE / 4 - 1);
  91.  
  92.             for ($i = $bbdBlocks; $i < $bbdBlocks + $blocksToRead; $i++) {
  93.                 $bigBlockDepotBlocks[$i] = GetInt4d($this->data, $pos);
  94.                 $pos += 4;
  95.             }  
  96.  
  97.             $bbdBlocks += $blocksToRead;
  98.             if ($bbdBlocks < $this->numBigBlockDepotBlocks) {
  99.                 $this->extensionBlock = GetInt4d($this->data, $pos);
  100.             }
  101.         }
  102.  
  103.        // var_dump($bigBlockDepotBlocks);
  104.        
  105.         // readBigBlockDepot
  106.         $pos = 0;
  107.         $index = 0;
  108.         $this->bigBlockChain = array();
  109.        
  110.         for ($i = 0; $i < $this->numBigBlockDepotBlocks; $i++) {
  111.             $pos = ($bigBlockDepotBlocks[$i] + 1) * BIG_BLOCK_SIZE;
  112.             //echo "pos = $pos";   
  113.             for ($j = 0 ; $j < BIG_BLOCK_SIZE / 4; $j++) {
  114.                 $this->bigBlockChain[$index] = GetInt4d($this->data, $pos);
  115.                 $pos += 4 ;
  116.                 $index++;
  117.             }
  118.         }
  119.  
  120.     //var_dump($this->bigBlockChain);
  121.         //echo '=====2';
  122.         // readSmallBlockDepot();
  123.         $pos = 0;
  124.         $index = 0;
  125.         $sbdBlock = $this->sbdStartBlock;
  126.         $this->smallBlockChain = array();
  127.    
  128.         while ($sbdBlock != -2) {
  129.    
  130.           $pos = ($sbdBlock + 1) * BIG_BLOCK_SIZE;
  131.    
  132.           for ($j = 0; $j < BIG_BLOCK_SIZE / 4; $j++) {
  133.             $this->smallBlockChain[$index] = GetInt4d($this->data, $pos);
  134.             $pos += 4;
  135.             $index++;
  136.           }
  137.    
  138.           $sbdBlock = $this->bigBlockChain[$sbdBlock];
  139.         }
  140.  
  141.        
  142.         // readData(rootStartBlock)
  143.         $block = $this->rootStartBlock;
  144.         $pos = 0;
  145.         $this->entry = $this->__readData($block);
  146.        
  147.         /*
  148.         while ($block != -2)  {
  149.             $pos = ($block + 1) * BIG_BLOCK_SIZE;
  150.             $this->entry = $this->entry.substr($this->data, $pos, BIG_BLOCK_SIZE);
  151.             $block = $this->bigBlockChain[$block];
  152.         }
  153.         */
  154.         //echo '==='.$this->entry."===";
  155.         $this->__readPropertySets();
  156.  
  157.     }
  158.    
  159.      function __readData($bl) {
  160.         $block = $bl;
  161.         $pos = 0;
  162.         $data = '';
  163.        
  164.         while ($block != -2)  {
  165.             $pos = ($block + 1) * BIG_BLOCK_SIZE;
  166.             $data = $data.substr($this->data, $pos, BIG_BLOCK_SIZE);
  167.             //echo "pos = $pos data=$data\n";   
  168.         $block = $this->bigBlockChain[$block];
  169.         }
  170.         return $data;
  171.      }
  172.        
  173.     function __readPropertySets(){
  174.         $offset = 0;
  175.         //var_dump($this->entry);
  176.         while ($offset < strlen($this->entry)) {
  177.               $d = substr($this->entry, $offset, PROPERTY_STORAGE_BLOCK_SIZE);
  178.            
  179.               $nameSize = ord($d[SIZE_OF_NAME_POS]) | (ord($d[SIZE_OF_NAME_POS+1]) << 8);
  180.              
  181.               $type = ord($d[TYPE_POS]);
  182.               //$maxBlock = strlen($d) / BIG_BLOCK_SIZE - 1;
  183.        
  184.               $startBlock = GetInt4d($d, START_BLOCK_POS);
  185.               $size = GetInt4d($d, SIZE_POS);
  186.        
  187.             $name = '';
  188.             for ($i = 0; $i < $nameSize ; $i++) {
  189.               $name .= $d[$i];
  190.             }
  191.            
  192.             $name = str_replace("\x00", "", $name);
  193.            
  194.             $this->props[] = array (
  195.                 'name' => $name,
  196.                 'type' => $type,
  197.                 'startBlock' => $startBlock,
  198.                 'size' => $size);
  199.  
  200.             if (($name == "Workbook") || ($name == "Book")) {
  201.                 $this->wrkbook = count($this->props) - 1;
  202.             }
  203.