原文http://blog.sina.com.cn/s/blog_4b9b442c0100r94n.html
以下内容是个人整理,不足之处请提出。内容将持续更新。
一、数据库加载:
数据库配置文件:安装时填写的数据库配置数据存储在caches/configs/database.php
(1)index.php入库文件,并加载phpcms/base.php。
(2)index.php文件:pc_base::creat_app();
(3)phpcms/libs/classes/application.class.php:$controller =$this->load_controller();
默认加载:phpcms\modules\content\index.php
(4)phpcms\modules\content\index.php:$this->db =pc_base::load_model('content_model');
加载文件:phpcms/model/content_model.class.php
(5)phpcms/model/content_model.class.php:$this->db_config= pc_base::load_config('database');
(6)加载配置文件:caches/configs/database.php
二、模板解析:
文件:phpcms/libs/functions/global.func.php
调用:include template($module,$template);
模板缓存文件:phpcms/libs/classes/template_cache.class.php
template_compile:模板编译函数
------------------------------ edit in 2011-05-07------------------------------
三、用户登录模块(phpsso关联)
1、phpcms/modules/member/index.php
登陆操作:login()
...
$status =$this->client->ps_member_login($username,$password);//phpsso中判断用户登陆,正确返回用户数据array
...//如果本地用户信息不存在,则插入数据,保持数据一致。
...
$synloginstr =$this->client->ps_member_synlogin($r['phpssouid']);//phpsso用户同步登陆函数
//==========其余分析至[phpsso通信]==========
四、用户注册模块(phpsso关联)
1、phpcms/modules/member/index.php
注册操作:register()
$this->_session_start();//加载phpcms/libs/classes/session_mysql.class.php
...
$member_setting = getcache('member_setting');//加载用户配置
...
$siteid = isset($_REQUEST['siteid'])&& trim($_REQUEST['siteid']) ?intval($_REQUEST['siteid']) : 1;//默认siteid为1
...
$this->_init_phpsso();//加载phpcms/modules/member/classes/client.class.php
//phpcms/base.php中load_app_class()函数的defined("ROUTE_M")来至于phpcms/libs/classes/application.class.php
...
$status =$this->client->ps_member_register($userinfo['username'],$userinfo['password'], $userinfo['email'], $userinfo['regip'],$userinfo['encrypt']);//phpsso中添加注册用户,返回phpssouid
...
$userid =$this->db->insert($userinfo,1);//本地用户数据添加。密码加密存储
五、后台部分整理
1、口令卡(移除)
配置文件:caches/configs/system.php
后台登陆/退出:phpcms/modules/admin/index.php
后台管理:phpcms/modules/admin/admin_manage.php
口令卡类:phpcms/modules/admin/classes/card.class.php
管理员类:phpcms/modules/admin/classes/admin.class.php
语言文件:phpcms/languages/zh-cn/admin.lang.php
phpcms/languages/zh-cn/system_menu.lang.php
模板文件:phpcms/modules/admin/templates/admin_list.tpl.php
phpcms/modules/admin/templates/login_card.tpl.php
phpcms/modules/admin/templates/admin_card.tpl.php
2、后台登陆
phpcms/modules/admin/classes/admin.class.php
常规下加载phpcms/libs/classes/session_mysql.class.php
...session_start();//开启session
phpcms/modules/admin/classes/admin.class.php
状态判断:check_admin()
phpcms/modules/admin/index.php
登陆操作:login()
...
$_SESSION['userid'] = $r['userid'];
...
$cookie_time = SYS_TIME+86400*30;
...
param::set_cookie('userid', $r['userid'],$cookie_time);
...
//设置session和cookie
六、phpsso通信机制
1、用户登陆/注册模块中调用phpcms/modules/member/classes/client.class.php
private function _ps_send(){//调用phpsso接口地址
}
------------------------------ edit in 2011-05-11------------------------------
private function _get_url() {
$sys_protocal = isset($_SERVER['SERVER_PORT'])&& $_SERVER['SERVER_PORT'] == '443'? 'https://' : 'http://';
$php_self =$_SERVER['PHP_SELF'] ?$this->_safe_replace($_SERVER['PHP_SELF']) :$this->_safe_replace($_SERVER['SCRIPT_NAME']);
$path_info =isset($_SERVER['PATH_INFO']) ?$this->_safe_replace($_SERVER['PATH_INFO']) :'';
$relate_url= isset($_SERVER['REQUEST_URI']) ?$this->_safe_replace($_SERVER['REQUEST_URI']) :$php_self.(isset($_SERVER['QUERY_STRING']) ?'?'.$this->_safe_replace($_SERVER['QUERY_STRING']) :$path_info);
return$sys_protocal.(isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST']: '').$relate_url;
}
private function _ps_post($url, $limit = 0, $post = '', $cookie ='', $ip = '', $timeout = 15, $block = true) {
$return ='';
$matches =parse_url($url);//解析URL
$host =$matches['host'];//主机名
$path =$matches['path'] ? $matches['path'].($matches['query'] ?'?'.$matches['query'] : '') : '/';//路径及查询字符串
$port =!empty($matches['port']) ? $matches['port'] : 80;//端口
$siteurl =$this->_get_url();//获取当前页面完整URL地址
if($post){//post方式提交
$out = "POST $path HTTP/1.1\r\n";
$out .= "Accept: **\r\n";
$out .= "Referer: ".$siteurl."\r\n";
$out .= "Accept-Language: zh-cn\r\n";
$out .= "User-Agent: $_SERVER[HTTP_USER_AGENT]\r\n";
$out .= "Host: $host\r\n";
$out .= "Connection: Close\r\n";
$out .= "Cookie: $cookie\r\n\r\n";
}
$fp =@fsockopen(($ip ? $ip : $host), $port, $errno, $errstr,$timeout);//用socket方式打开一个文件指针
if(!$fp)return '';
stream_set_blocking($fp, $block);//设置阻塞模式
stream_set_timeout($fp, $timeout);//设置连接时间
@fwrite($fp,$out);//把数据写入文件指针中,即发送请求头信息
$status =stream_get_meta_data($fp);//从封装协议文件指针中取得报头/元数据,即返回写入的相关状态
if($status['timed_out']) return''; //等待数据流超时
while(!feof($fp)) {//循环读取响应头信息,直到文件指针到达文件结束的位置
if(($header = @fgets($fp)) &&($header == "\r\n" || $header =="\n")) break;//从文件指针中读取一行
}
$stop =false;
while(!feof($fp) && !$stop){//控制是否读取完成
$data = fread($fp, ($limit == 0 || $limit > 8192 ?8192 : $limit));
$return .= $data;
if($limit) {
$limit -= strlen($data);
$stop = $limit <= 0;
}
}
@fclose($fp);//关闭一个已打开的文件指针
//部分虚拟主机返回数值有误,暂不确定原因,过滤返回数据格式
$return_arr= explode("\n", $return);
if(isset($return_arr[1])) {
$return = trim($return_arr[1]);
}
unset($return_arr);
return$return;
}
七、php-socket相关
1、创建流:fopen()、fsockopen()、pfsockopen()
2、stream_set_blocking($resource,$flag)
$flag:0非阻塞,1阻塞
某个函数读取一个网络流,当没有未读取字节时:
阻塞:一直等待,直到下一个未读取的字节出现。
非阻塞:立即告诉调用者当前没有新内容。
阻塞的好处是,排除其它非正常因素,阻塞的是按顺序执行的同步的读取。
3、stream_set_timeout($resource,$responseTimeout)//设置返回的超时时间
4、stream_get_meta_data($resource)
//从封装协议文件指针中取得报头/元数据
(1)timed_out (bool) - 如果在上次调用 fread() 或者 fgets() 中等待数据时流超时了则为TRUE。
(2)blocked (bool) - 如果流处于阻塞 IO 模式时为 TRUE。参见stream_set_blocking()。
(3)eof (bool) - 如果流到达文件末尾时为 TRUE。注意对于 socket 流甚至当 unread_bytes为非零值时也可以为 TRUE。要测定是否有更多数据可读,用 feof()替代读取本项目的值。
(4)unread_bytes (int) - 当前在 PHP 自己的内部缓冲区中的字节数。
5、stream_get_contents($resource)//取得返回的数据流内容
6、相关函数:fwrite()、fgets()、feof()、fread()、fclose()
读字符串函数fgets函数的功能是从指定的文件中读一个字符串到字符数组中,函数调用的形式为: fgets(字符数组名,n,文件指针);其中的n是一个正整数。表示从文件中读出的字符串不超过n-1个字符。在读入的最后一个字符后加上串结束标志'\0'。例如:fgets(str,n,fp);的意义是从fp所指的文件中读出n-1个字符送入字符数组str中。
fread是用于整块数据的读写函数,可用来读写一组数据,如一个数组元素,一个结构变量的值等。读数据块函数调用的一般形式为:fread(buffer,size,count,fp),其中buffer是一个指针,在fread函数中,它表示存放输入数据的首地址。size 表示数据块的字节数。count 表示要读写的数据块块数。fp 表示文件指针。
eg:fread(fa,4,5,fp);其意义是从fp所指的文件中,每次读4个字节(一个实数)送入实数组fa中,连续读5次,即读5个实数到fa中。
7、$_POST、HTTP_RAW_POST_DATA、php://input
(1)HTTP_RAW_POST_DATA仅在碰到未识别MIME类型的数据时产生。对于enctype="multipart/form-data"表单数据不可用。
(2)访问原始POST数据的更好方法是php://input
(3)php://input 允许读取 POST 的原始数据。和 $HTTP_RAW_POST_DATA比起来,它给内存带来的压力较小,并且不需要任何特殊的 php.ini 设置。php://input 不能用于enctype="multipart/form-data"。
基本上$GLOBALS['HTTP_RAW_POST_DATA'] 和$_POST是一样的。但是如果post过来的数据不是PHP能够识别的,你可以用$GLOBALS['HTTP_RAW_POST_DATA']来接收,比如text/xml或者soap等等。
PHP默认识别的数据类型是application/x-www.form-urlencoded标准的数据类型
因此,对型如text/xml的内容无法解析为$_POST数组,故保留原型,交给$GLOBALS['HTTP_RAW_POST_DATA']来接收。
eg.
(1)phpcmsv9中phpsso_server/phpcms/modules/phpsso/classes/phpsso.class.php
if(isset($GLOBALS['HTTP_RAW_POST_DATA'])){
$this->data['avatardata'] =$GLOBALS['HTTP_RAW_POST_DATA'];
...
}
(2)phpsso_server/phpcms/modules/phpsso/index.php
file_put_contents($filename,$this->data['avatardata']);//把数据写入文件
eg.
<form action="test.php"method="post">
<input type="text" name="user">
<input type="password"name="password">
<input type="submit">
</form>
test.php
<? echo file_get_contents("php://input");?>
八、http协议
1、特点
简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。
灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。
无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
2、php-socket中http的请求和响应
========== 请求头信息 ==========
Host:localhost
User-Agent:Mozilla/5.0 (Windows NT 5.1; rv:2.0) Gecko/20100101Firefox/4.0
Accept:application/json, text/javascript, */*
Accept-Language:zh-cn,zh;q=0.5
Accept-Encoding:gzip, deflate
Accept-Charset:GB2312,utf-8;q=0.7,*;q=0.7
Keep-Alive:115
Proxy-Connection:keep-alive
Content-Type:application/x-www-form-urlencoded
X-Requested-With:XMLHttpRequest
Referer:http://localhost/
Cookie:---cookie相关---
---请求发送数据---
========== 响应头信息 ==========
Proxy-Connection:Keep-Alive
Connection:Keep-Alive
Content-Length:112
Via 1.1WALKISA
Date:Tue, 17 May 2011 03:26:18 GMT
Content-Type:text/html; charset=gbk
Server:nginx/0.7.67
X-Powered-By:PHP/5.2.13
------------------------------ edit in 2011-05-18------------------------------
九、信息模型和用户模型
涉及数据表:v9_model、v9_model_field
信息模型:phpcms/modules/content/fields/content_form.class.php
用户模型:phpcms/modules/member/fields/member_form.class.php
缓存类文件:caches/caches_model/caches_data/content_form.class.php(member_form.class.php)
信息模型调用:require CACHE_MODEL_PATH.'content_form.class.php';
$content_form = new content_form($modelid,$catid, $CATEGORYS);
$forminfos_data =$content_form->get();
模型缓存更新:
(1)后台更新文件:phpcms/modules/admin/cache_all.php
array('name' => L('sitemodel'), 'function'=>'sitemodel'),调用phpcms/modules/admin/classes/cache_api.class.php中的模型缓存更新函数sitemodel()
(2)sitemodel()中根据fields.inc.php配置信