php示例程式(四)
四、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函数的情况下,这时将从上一次切割后的后半部分开始新的切割。
通过这个程序,我们又能学到什么呢,我想这个程序中值得我们学的太多了,在这儿,我就不多说了。