四、php3中自做session的读写
初看到这个程序时,唯一的感觉就是无从下手。后来还是session给了我一点灵感,大家应该都知道php4中的session,而这个程序就是在php3中模仿session的读写。
源程序如下:
// ------------------------------------------------------------------
// READ SESSION
// ------------------------------------------------------------------
Function read_session() {
global $session, $session_path, $session_id;
/* set up session variables */
/* What should we do if the script cannot find the session file? */
$fp = fopen( $session_path.$session_id, "r" );
while(!feof($fp))
{
$line = fgets($fp,100);
$tok = strtok($line, "=");
$a = $tok;
$tok = strtok( "=");
$b = chop($tok);
$c = UrlDecode($b);
if((strlen($c) > 0) && (strlen($a) > 0))
{
eval( "\$session$a = \$c;");
}
}
fclose($fp);
return($fp);
}
// ------------------------------------------------------------------
// WRITE SESSION
// ------------------------------------------------------------------
Function write_session() {
global $session_path, $session_id, $session, $sm_string_array;
$level = 0;
unset($sm_string_array);
reset($session);
/* Write array to session file */
$fp = fopen($session_path . $session_id, "w");
if($fp != "false")
{
write_session_loop($fp);
} else {
echo "<h2>Session Error " . $fp . ": Cannot Write to File!</h2><br>\n";
}
fclose($fp);
}
Function write_session_loop($fp) {
global $session, $sm_string_array;
static $level=0;
if(IsSet($sm_string_array))
{
$num_elements_string_array = count($sm_string_array);
} else {
$num_elements_string_array = 0;
}
if($num_elements_string_array > 0)
{
$s=0;
$string = "";
while(($s < $num_elements_string_array) && IsSet($sm_string_array[$s]))
{
if(gettype($sm_string_array[$s]) == "string")
{
$string = $string . "['" . $sm_string_array[$s] . "']";
} else {
$string = $string . "[" . $sm_string_array[$s] . "]";
}
$s++;
}
} else {
$string= "";
}
eval( "\$test_array= \$session$string;");
if(gettype($test_array) == "array")
{
$num_elements = count($test_array);
} else {
$num_elements = 0;
eval( "\$value = \$session$string;");
$value_url = UrlEncode($value);
$pair = $string . "=" . $value_url;
fputs($fp, "$pair\n");
}
eval( "reset(\$session$string);");
$x=0;
while($x < $num_elements)
{
eval( "\$key = key(\$session$string);");
$sm_string_array[$level] = $key;
$level++;
unset($sm_string_array[$level]);
write_session_loop($fp); // 函数递归
$level--;
eval( "next(\$session$string);");
$x++;
}
}
?>
还是让我们先看看write_session_lop($fp),这是一个递归函数,先别痛苦,要学编程,递归是一定得知道的。由于$session和$sm_string_array是两个全局变量,实际上你也可以将这两个变量看成是这个函数的两个参数,而我们在write_session()这个函数中可以看出,在调用write_session_lop($fp)时$sm_string_array经历了一个unset的过程,也就是说在在刚进入write_session_lop($fp)时,$sm_string_array未定义,那我们就先顺着这个思路看下去:
因为$sm_string_array未定义,所以$num_elements_string_array = 0,于是$string=””,这时一个比较冷的函数出现了,先别管他,在这里eval( "\$test_array= \$session$string;")也就是$test_array=$session,下面是一判断,我们先假设$session是个数组,有两个元素,这时$num_elements=2,又是eval( "reset(\$session$string);"),还不管他,这时这句话与reset($session)等价,将指针改指到数组$session的第一个元素,这时进入一个循环,$key = key($session),$sm_string_array[0]=$key记录了目前数组的指针的索引。清除$sm_string_array[1],进入递归,现在我们不能不谈谈静态变量了,static $level=0定义了一个静态变量初始值为0,而通过下面这个例子,你应该能知道静态变量是怎么一回事了。
<?php
function myfunc() {
static $mystr="哈";
$mystr.="哈";
echo $mystr."<br>\n";
}
myfunc();
myfunc();
myfunc();
?>
输出结果:
哈哈
哈哈哈
哈哈哈哈
静态变量使得变量在每次执行完函数后不再消失。
现在我们再回到我们原来的程序来,现在$num_elements_string_array=1,进入循环,string为目前数组的指针的索引,如果是数字,就用[1]的格式,如果是字符,就用[‘string’]的格式。这里eval( "\$test_array= \$session$string;")也就是$test_array= $session[1],(现在eval函数的作用,你应该能猜上一半了,如果还不知道,就去查查书吧)。我们假设$session[1]不再是数组,$value = $session[1] 将$value以 URL 编码后存入$value_url中,将$string=$value_url插入文件,总算暂时跳出了递归。现在开始折腾session[2],他会同样将$string=$value_url,当然这时$string 和$value_url可和刚才的不一样了,它是对应于session[2]的。
现在函数write_session_loop($fp)的作用我们已经知道了,它以其固定的格式将变量、一维数组或多维数组session存入文件中。多维数组的处理情况会复杂得多,在这里,我们就不再跟踪其执行过程了。
现在再回过头来看看write_session(),一切变得那么顺理成章,在这儿,只是按路径$session_path和文件名$session_id打开一个文件用来插入。
而read_session()也只是按这个格式将文件中的内容取出并重新给session赋值。这里除了再次使用了eval函数外,还有一个比较冷的函数是strtok这个函数和explode有点类似 将字符串 arg1 依字符串 arg2 的值切开成小段小段的字符串。事实上对于这个函数,php4gb上讲得并不是太清楚,对于这有一个参数的情况只能发生在前面已有一个strtok函数的情况下,这时将从上一次切割后的后半部分开始新的切割。
通过这个程序,我们又能学到什么呢,我想这个程序中值得我们学的太多了,在这儿,我就不多说了。
|