分页: 22/29 第一页 上页 17 18 19 20 21 22 23 24 25 26 下页 最后页 [ 显示模式: 摘要 | 列表 ]
Feb 5

默认情况下,PHP会话(session)是通过文件来保存的。这样做有以下几个缺点:

  1. 会话文件一般都很小,但文件数却很多,在文件系统中保存许多这样的小文件非常浪费空间,且效率不高。
  2. 分布式的站点难以利用会话文件来共享会话。
  3. 会话文件方式不利于统计在线用户的会话信息。

为解决以上问题,我们可以考虑用数据库来保存会话信息。

对于 PHP 开发来说,保存会话用 MySQL 是一个非常不错的选择。MySQL 提供一种建立在内存中的表类型 Heap,如果每条会话数据量很小的话,可以考虑用这种类型的表来进一步优化性能。但是 Heap 类型的表有许多限制,例如它不支持 text 类型的字段,因此如果在无法预测会话数据记录长度的情况下,选择 MyISAM 是比较合适的,这种类型的表没有事物处理开销,对于基于磁盘的表可以得到最优性能。

下面是 sessions 表的结构:

  1. DROP TABLE IF EXISTS `sessions`;
  2. CREATE TABLE `sessions` (
  3.   `session_id` varchar(32) NOT NULL default '',
  4.   `user_id` int(10) unsigned NOT NULL default '0',
  5.   `data_value` text NOT NULL,
  6.   `last_visit` timestamp(14) NOT NULL,
  7.   PRIMARY KEY (`session_id`),
  8.   KEY `user_id` (`user_id`)
  9. ) TYPE=MyISAM;

PHP 支持用户会话模块,可以通过 session_set_save_handler 来设置自定义的会话处理函数。因为默认的处理模块是 files,因此要在用 session_set_save_handler 设置会话处理函数之前,先用 session_module_name(’user’) 来告诉 PHP 使用用户会话模块, 而session_set_save_handler 必须要在 session_start 之前执行。

用户会话数据在会话处理函数中都是序列化之后的,要取出其中的某个会话变量,可以对其进行反序列化,默认是 php 序列化方式,可以用 session::unserialize 函数来反序列化。

下面的代码定义了一个用 MySQL 来处理 PHP 会话的类,其中所使用的 class_mysql.php 请参见 《超级简单但超级实用的 PHP 的 mysql 类》

  1. <?php
  2. /**
  3. * @author 马秉尧
  4. * @copyright (C) 2005 CoolCode.CN
  5. */
  6. require_once("class_mysql.php");
  7. class session {
  8.     var $db;
  9.     function session(&$db) {
  10.         $this->db = &$db;
  11.         session_module_name('user');
  12.         session_set_save_handler(
  13.             array(&$this, 'open'),
  14.             array(&$this, 'close'),
  15.             array(&$this, 'read'),
  16.             array(&$this, 'write'),
  17.             array(&$this, 'destroy'),
  18.             array(&$this, 'gc')
  19.         );
  20.         session_start();
  21.     }
  22.     function unserialize($data_value) {
  23.         $vars = preg_split(
  24.             '/([a-zA-Z_x7f-xff][a-zA-Z0-9_x7f-xff]*)|/',
  25.             $data_value, -1, PREG_SPLIT_NO_EMPTY |               
  26.             PREG_SPLIT_DELIM_CAPTURE
  27.         );
  28.         for ($i = 0; $vars[$i]; $i++) {
  29.             $result[$vars[$i++]] = unserialize($vars[$i]);   
  30.         }
  31.         return $result;
  32.     }
  33.     function open($path, $name) {
  34.         return true;
  35.     }
  36.     function close() {
  37.         return true;
  38.     }
  39.     function read($session_id) {
  40.         $session_id = $this->db->escape_string($session_id);
  41.         if ($row = $this->db->query("select * from `sessions` where `session_id` = '$session_id' limit 1")) {
  42.             return $row['data_value'];
  43.         }
  44.         else {
  45.             $this->db->query("insert into `sessions` set `session_id` = '$session_id'");
  46.             return "";
  47.         }
  48.     }
  49.     function write($session_id, $data_value) {
  50.         $data = $this->unserialize($data_value);
  51.         $session_id = $this->db->escape_string($session_id);
  52.         $data_value = $this->db->escape_string($data_value);
  53.         $this->db->query("update `sessions` set " 
  54.                                 . "`user_id` = '{$data['user_id']}', "
  55.                                 . "`data_value` = '$data_value', "
  56.                                 . "`last_visit` = null "
  57.                                 . "where `session_id` = '$session_id'");
  58.         return true;
  59.     }
  60.     function destroy($session_id) {
  61.         $session_id = $this->db->escape_string($session_id);
  62.         $this->db->query("delete from `sessions` where `session_id` = '$session_id'");
  63.         return true;
  64.     }
  65.     function gc($lifetime) {
  66.         $this->db->query("delete from `sessions` where unix_timestamp(now()) - unix_timestamp(`last_visit`) > $lifetime");
  67.         return true;
  68.     }
  69.     // get sessions by user_id
  70.     function get($user_id) {
  71.         $user_id = $this->db->escape_string($user_id);
  72.         return $this->db->query("select * from `sessions` where `user_id` = '$user_id'");
  73.     }
  74.     // get sessions list
  75.     function lists($page, $rows) {
  76.         if ($page == 0) {
  77.             return $this->db->query("select * from `sessions` order by `user_id`");
  78.         }
  79.         else {
  80.             $start = ($page - 1) * $rows;
  81.             return $this->db->query("select * from `sessions` order by `user_id` limit $start, $rows");
  82.         }
  83.     }
  84. }
  85. ?>

这个类的使用很简单,在原来使用 session_start 的地方,替换成 $session = new session($db) 就可以了。$db 表示 sessions 表所在的数据库。

另外可以用 get 方法来获取某个用户的所有会话信息,通过 lists 方法来得到所有用户会话列表。这样就可以方便的管理用户会话了。

Feb 5
  PHP以其易用性得到迅速的推广,但易用并不是说就能用好它,实际上许多程序员用它很容易的立一个个WEB应用系统,但又有多少人仔细的考虑过他们的代码,是否容易维护、是否足够健壮、否效率足够高、是否足够安全,当PHP用于建立大型网站时这些就成为很关键的因素。下面我们从较轻微的问题开始讨论,直至一些致命的错误。共分三部分。
 第一部分、较轻微的错误
 
 一、Printf(),
   该函数主要用来格式化显示数据。当你要改变某个数据的显示格式时才使用。
 例如以不同的精度来显示PI(3.1415926)的值。
    /*
  * The three faces of Π
  */
 
  printf ("Pi is: %.2fn
n", M_PI);
  printf ("Pi is also: %.3fn
n", M_PI);
  printf ("Pi is also: %.4fn
n", M_PI);
 ?>
 
   但许多程序员仅仅为显示一些变量值和函数返回值使用该函数。因为Printf()在显示数据前要先格式化该数据以速度较慢,因此,仅为了显示数据时应用print和echo,以提高速度。
 
 二、语意检查
   PHP是一种弱类型语言,也就是说在使用一个变量前不用定义,这样给编程带来了很大的方便和灵活,但你自己必须知道该变量到底应该是哪种类型,因为该变量在运行时仍实际对应着某一种类型(各种类型之间可以自由互相转换),没有类型的变量是不存在的。有可能PHP并不能检查出你的语意错误,但由于变量类型的变化,会导致一些潜在的问题的发生。另外一个值得注意的问题是变量的范围,它也可能会导致一些潜在的问题的发生。
 在PHP中有以下几种基本变量:
 Boolean, resource, integer, double, string, array and object。
 
 三、临时变量的使用
   临时变量的滥用会导致程序运行效率的降低。何时使用临时变量可基于以下两点考虑:
 1、该变量是否至少使用两次。
 2、该变量的使用是否会显著提高程序的可读性。
 如果一条也不满足,则省略该变量的使用。例如:
    $tmp = date ("F d, h:i a"); /* ie January 3, 2:30 pm */
  print $tmp;
 ?>
 就应该改成:
    print date ("F d, h:i a");
 ?>
 
 又如:
   
 // string reverse_characters(string str)
 // Reverse all of the characters in a string.
 function reverse_characters ($str)
 {
  return implode ("", array_reverse (preg_split("//", $str)));
 }
 
 ?>
 的可读性不强,可改成:
   
 // string reverse_characters(string str)
 // Reverse all of the characters in a string.
 function reverse_characters ($str)
 {
  $characters = preg_split ("//", $str);
  $characters = array_reverse ($characters);
 
  return implode ("", $characters);
 }
 
 ?>
 
 四、客户端和服务器端代码的分离
   客户端和服务器端代码的在PHP程序中实际上就是HTML代码和PHP语言代码,很多人把HTML和PHP语句混合在一个文件里,使得这文件很大,这种风格对程序的维护和再开发很不利,不适合大型站点的开发。一般有两种方法把HTML和PHP语句分开:
 1、编写专用API,例如:
 
 index.php ? The Client side
 
 
 
  <?php print_header (); ?>
 
 
 


 
 
 
 
 
 

 
 

 
 

 
 
 
 
 site.lib ? The server side code
 
 
   
 $dbh = mysql_connect ("localhost", "sh", "pass")
 or die (sprintf ("Cannot connect to MySQL [%s]: %s",
 mysql_errno (), mysql_error ()));
 @mysql_select_db ("MainSite")
 or die (sprintf ("Cannot select database [%s]: %s",
 mysql_errno (), mysql_error ()));
 
 $sth = @mysql_query ("SELECT * FROM site", $dbh)
 or die (sprintf ("Cannot execute query [%s]: %s",
 mysql_errno (), mysql_error ()));
 
 $site_info = mysql_fetch_object ($sth);
 
 function print_header ()
 {
  global $site_info;
  print $site_info->header;
 }
 
 function print_body ()
 {
  global $site_info;
  print nl2br ($site_info->body);
 }
 
 function print_links ()
 {
  global $site_info;
 
  $links = explode ("n", $site_info->links);
  $names = explode ("n", $site_info->link_names);
 
 for ($i = 0; $i < count ($links); $i++)
 {
  print "ttt
  $names[$i]
  n
n";
 }
 }
 ?>
 
 这种方法使得程序看起来比较简洁,而且执行速度也较快。
 
 2、使用模板的方法
 这种方法使得程序看起来更简洁,同样实现上面的功能,可用以下代码:
 
 
 %%PAGE_TITLE%%
 
 
 

%%PAGE_TITLE%%


 
 
 
 
 
 
%%PAGE_LINKS%% %%PAGE_CONTENT%%

 
 
 
   用占位符代替要动态生成的内容,然后用一解析程序分析该模板文件,把占位符用际的内容替换。种方法使得即使不会使用PHP的页面制作人员也能修改模板文件。这种方法的缺点是执行效率不高,因为要解释模板文件。同时实现起来也比较复杂。
 
 注: www.thewebmasters.net的 FastTemplate class可方便的实现以上功能。
 
 五、不要用过时的函数
 作为一种自由软件,PHP发展很快,其中的很多函数都已过时,例如:
 
 while (1):
 print "5";
 if ($idx++ == 5):
 break;
 endif;
 endwhile;
 
   虽然还能用但效率肯定不高,而且可能在以后的版本中会禁用,导致程序不能运行。因此要经常对照最新PHP手册检查那些函数已过时及时修正
Feb 5
为了能准确的播放asx文件,我们必须用js对mediaplayer进行控制。


<?


//asx的格式:
function channelprogramlist($filename){
$str="";
$str.="<ASX version="3.0">rn";
$str.="t<ENTRY>rn";
$str.="tt<AUTHOR>".$filename;   //节目名
$str.="</AUTHOR>rn";
  $filename=urlencode($filename); //把节目名转换
  $filepath="http://".192.168.0.1"/".$filename;  //192.168.0.1是服务器的ip
  $str.= "tt<REF HREF="$filepath" />rn";
  $str.= "t</ENTRY>rn";
 }
$str.= "</ASX>";
return $str;
}


//写asx文件
function writeFile($str){        
 $file="mms.asx";
 $fp = fopen($file,"w+");
 fwrite($fp,$str);
 fclose($fp);
 return  $file;
}


//控制mediaplayer每次从新读取文件
function PlayChannel($urlstr){
echo "<script language="javascript">n";
echo "function change(){n";
echo "t"."document.mediaPlayer.file=".$urlstr.";n";
echo "}n";
echo "</script>n";
}


?>


<html>
<head>
<title>播放器</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<?php
$filename="神话";
PlayChannel(writeFile(channelprogramlist($filename)));
?>
</head>
<body leftmargin="0" topmargin="0" onLoad="change()" bgcolor="#000000">
<object id="mediaPlayer" width="554" height="380" classid="clsid:22D6F312-B0F6-11D0-94AB-0080C74C7E95" standby="Loading Microsoft Media Player components..." type="application/x-oleobject">
<PARAM NAME="animationatStart" VALUE="true">
<PARAM NAME="transparentatStart" VALUE="true">
<PARAM NAME="autoStart" VALUE="true">
<PARAM NAME="CanSeek" VALUE="FALSE">
<PARAM NAME="showControls" VALUE="FALSE">
<param name="FileName" value="mms.asx">
<embed type="application/x-mplayerO" pluginspage="http://www.microsoft.com/Windows/Downloads/Contents/Products/MediaPlayer/" autostart="1" width="500" height="400">
</embed>
</object>
</body>
</html>

Feb 5
最近做完了一个项目,感慨颇深。根据做项目的经验,现初步拟了一个项目开发过程及成员组成。还请各位多多指教。

项目过程

1、项目启动
1)、项目组成立(公司成员、客户成员)
2)、制定项目预期目标
3)、制定项目计划周期
4)、建立好项目组成员沟通机制

2、需求调研
1)、创建调研计划、协调调研时间
2)、收集客户资料,获取客户需求
 所有的资料都需要保留一份,资料中存疑的需要及时询问
3)、编写需求文档
 重点描述出客户的业务流程和性能要求。
 采用Word、Excel、Rose等形式。
4)、需求变更记录
5)、确定开发环境和运行环境
6)、扩展性要求
7)、与旧系统的接驳要求。
8)、估算出项目工作量

本阶段需要一套需求管理系统来进行需求的管理。

 本阶段的需求文档也是用户测试的依据。

3、系统设计/详细设计
一个系统可以分为基础平台和应用模块两部分。
1)、选择基础平台,无论是采用第三方平台还是自行开发平台,都需要深入了解,查看是否符合要求。
2)、应用模块设计(针对业务流程)
3)、中间件的采用或自行开发,需要深入了解。
4)、用户界面的设计
 如果用户界面设计完毕并确认,即可初步写出用户使用手册、管理员使用手册。
5)、变更记录

本阶段的系统设计是集成测试的依据。

4、程序开发
创建开发任务计划表、开发计划日程表
1)、优先编写测试用例
2)、按照编码规范编写代码
3)、按照文档注释规范注释
以上形成开发文档。

 本阶段需要一套版本管理系统。

 本阶段的测试用例也是单元测试的依据。
 如果能做到,最好每日构建。

5、测试
 本阶段需要一套Bug管理系统,形成需求、设计、开发、测试互动。

1)、编写测试计划和测试方案
2)、功能测试
 单元测试、集成测试
3)、性能测试
 集成测试、压力测试

如果能做到,最好能进行自动化测试。
如果能做到,做分析统计工作。

最后形成测试报告。

6、试用、培训、维护
本阶段需要解决:
1)、解决异地修改和公司修改的同步问题。
2)、用户测试中的Bug修改问题,按照级别分为
 a)、程序Bug
 b)、设计变更
 c)、需求变更
尽量按照a b c的顺序来进行修改,尽量避免b、c级的修改。

最后形成安装手册、维护记录。

项目成员组成

根据以上过程,一个项目组中,需要:
1、需求工程师,其要求
善于与客户沟通,能快速了解客户的需求,对客户所在的行业比较熟悉。
善于学习新知识。
熟悉Word、Excel、Rose等工具的使用。
熟悉开发语言和开发框架
熟悉已积累的产品的功能、性能等。

2、系统分析师/设计师,其要求
精通开发语言和开发框架,部分需要精通数据库
精通已积累的产品的功能、性能等
深入了解客户行业特点
能根据客户的要求分析出其实质
能做出优秀的设计
熟悉Word、Excel、Rose等工具的使用

3、开发工程师,其要求
熟悉开发语言,熟悉开发要求和注释规范,部分需要熟悉数据库。
熟悉单元测试。
能根据设计做出良好的编码,保证功能和性能。
部分需要有一定的设计要求,因为涉及到将来的维护。

4、测试工程师,其要求
熟悉测试工作,能按照测试计划进行测试。
熟悉开发语言,能协助开发工程师找错。
能独立完成黑、白盒测试。
如果是高级测试人员,还要能够对系统能深入进行分析并能制定出优秀的测试方案。

5、管理人员
一般由以上人员兼任,主要有
项目经理:负责整个项目
开发经理:负责系统设计、开发工作
测试经理:负责测试工作

6、其他人员
一些项目涉及到其他人员,如页面设计人员、页面制作人员。
部分大的项目,还有专门的维护人员。

由于目前国内很多公司并没有严格这么区分,如果项目小的话,可以一人兼任多项职位
Jan 22

<?php

// created by joe lumbroso
// see some other good php3 scripts
// goto http://www.dtheatre.com/scripts

echo "<font color=\"red\"><blink><b>Pinging</b></blink></font><br>";
$to_ping = "dtheatre.com";
$count = 3;
$psize = 65;
echo " Please be patient, this can take a few moments...\n<br><br>";
flush();

while (1) {
?>
<pre>
<?
exec("ping -c $count -s $psize $to_ping", $list);
for ($i=0;$i < count($list);$i++) {
print $list[$i]."\n";
}
?>
</pre>
<?
flush();
sleep(3);
}
?>
分页: 22/29 第一页 上页 17 18 19 20 21 22 23 24 25 26 下页 最后页 [ 显示模式: 摘要 | 列表 ]