随笔 - 46  文章 - 0  trackbacks - 0
<2024年4月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

留言簿(2)

随笔分类

随笔档案

搜索

  •  

最新评论

阅读排行榜

评论排行榜

Session的中文译名叫做“会话”,其本来的含义是指有始有终的一系列动作/消息,比如打电话时从拿起电话拨号到挂断电话这中间的一系列过程可以称之为一个session。目前社会上对session的理解非常混乱:有时候我们可以看到这样的话“在一个浏览器会话期间,...”,这里的会话是指从一个浏览器窗口打开到关闭这个期间; 也可以看到“用户(客户端)在一次会话期间”这样一句话,它可能指用户的一系列动作(一般情况下是同某个具体目的相关的一系列动作,比如从登录到选购商品到结账登出这样一个网上购物的过程;然而有时候也可能仅仅是指一次连接;其中的差别只能靠上下文来推断了。

然而当session一词与网络协议相关联时,它又往往隐含了“面向连接”和/或“保持状态”这样两个含义,“面向连接”指的是在通信双方在通信之前要先建立一个通信的渠道,比如打电话,直到对方接了电话通信才能开始。“保持状态”则是指通信的一方能够把一系列的消息关联起来,使得消息之间可以互相依赖,比如一个服务员能够认出再次光临的老顾客并且记得上次这个顾客还欠店里一块钱。这一类的例子有“一个TCP session”或者“一个POP3 session”。

鉴于这种混乱已不可改变,要为session下个定义就很难有统一的标准。而在阅读session相关资料时,我们也只有靠上下文来推断理解了。不过我们可以这样理解:例如我们打电话,从拨通的那一刻起到挂断电话期间,因为电话一直保持着接通的状态,所以把这种接通的状态叫做session。它是访客与整个网站交互过程中一直存在的公有变量,在客户端不支持COOKIE的时候,为了保证数据正确、安全,就采用SESSION变量。访问网站的来客会被分配一个唯一的标识符,即所谓的会话 ID。它要么存放在客户端的 cookie,要么经由 URL 传递。

SESSION的发明填补了HTTP协议的局限:HTTP协议被认为是无状态协议,无法得知用户的浏览状态,当它在服务端完成响应之后,服务器就失去了与该浏览器的联系。这与HTTP协议本来的目的是相符的,客户端只需要简单的向服务器请求下载某些文件,无论是客户端还是服务器都没有必要纪录彼此过去的行为,每一次请求之间都是独立的,好比一个顾客和一个自动售货机或者一个普通的(非会员制)大卖场之间的关系一样。
因此通过SESSION(cookie是另外一种解决办法)记录用户的有关信息,以供用户再次以此身份对web服务器提起请求时作确认。会话的发明使得一个用户在多个页面间切换时能够保存他的信息。网站编程人员都有这样的体会,每一页中的变量是不能在下一页中使用的(虽然form,url也可以实现,但这都是非常不理想的办法),而SESSION中注册的变量就可以作为全局变量使用了。

那么SESSION到底有什么用处呢?网上购物时大家都用过购物车,你可以随时把你选购的商品加入到购物车中,最后再去收银台结帐。在整个过程中购物车一直扮演着临时存贮被选商品的角色,用它追踪用户在网站上的活动情况,这就是SESSION的作用,它可以用于用户身份认证,程序状态记录,页面之间参数传递等。

SESSION的实现中采用COOKIE技术,SESSION会在客户端保存一个包含session_id(SESSION编号)的COOKIE;在服务器端保存其他session变量,比如session_name等等。当用户请求服务器时也把session_id一起发送到服务器,通过session_id提取所保存在服务器端的变量,就能识别用户是谁了。同时也不难理解为什么SESSION有时会失效了。

当客户端禁用COOKIE时(点击IE中的“工具”—“Internet选项”,在弹出的对话框里点击“安全”—“自定义级别”项,将“允许每个对话COOKIE”设为禁用),session_id将无法传递,此时SESSION失效。不过php5在linux/unix平台可以自动检查cookie状态,如果客户端设置了禁用,则系统自动把session_id附加到url上传递。windows主机则无此功能。

Session常见函数及用法?

Session_start() :开始一个会话或者返回已经存在的会话。

说明:这个函数没有参数,且返回值均为true。如果你使用基于cookie的session(cookie-based sessions),那么在使用Session_start()之前浏览器不能有任何输出,否则会发生以下错误:
Warning: Cannot send session cache limiter - headers already sent (output started at /usr/local/apache/htdocs/cga/member/1.php:2)…………

你可以在php.ini里启动session.auto_start=1,这样就无需每次使用session之前都要调用session_start()。但启用该选项也有一些限制,如果确实启用了 session.auto_start,则不能将对象放入会话中,因为类定义必须在启动会话之前加载以在会话中重建对象。
请求结束后所有注册的变量都会被序列化。已注册但未定义的变量被标记为未定义。在之后的访问中这些变量也未被会话模块定义,除非用户以后定义它们。

警告: 有些类型的数据不能被序列化因此也就不能保存在会话中。包括 resource 变量或者有循环引用的对象(即某对象将一个指向自己的引用传递给另一个对象)。

注册SESSION变量 :

PHP5使用$_SESSION[‘xxx’]=xxx注册SESSION全局变量。和GET,POST,COOKIE的使用方法相似。

注意:session_register(),session_unregister ,session_is_registered在php5下不再使用,除非在php.ini里把register_globle设为on,不过出于安全考虑,强烈建议关闭register_globle。HTTP_SESSION_VARS也不提倡使用了,官方建议用$_SESSION代替之。例如:

Page1.php
<?php
Session_start(); //使用SESSION前必须调用该函数。
$_SESSION[‘name’]=”我是黑旋风李逵!”; //注册一个SESSION变量
$_SESSION[‘passwd’]=”mynameislikui”;
$_SESSION[‘time’]=time();
echo '<br /><a href="page2.php">通过COOKIE传递SESSION</a>'; //如果客户端支持cookie,可通过该链接传递session到下一页。
echo '<br /><a href="page2.php?' . SID . '">通过URL传递SESSION</a>';//客户端不支持cookie时,使用该办法传递session.
?>
Page2.php
<?php
session_start();
echo $_SESSION['name']; //
echo $_SESSION['passwd']; //
echo date('Y m d H:i:s', $_SESSION['time']);
echo '<br /><a href="page1.php">返回山一页</a>';
?>

有两种方法传递一个会话 ID:

cookie

URL 参数

会话模块支持这两种方法。cookie 更优化,但由于不总是可用,也提供替代的方法。第二种方法直接将会话 ID 嵌入到 URL 中间去。

PHP 可以透明地转换连接。除非是使用 PHP 4.2 或更新版本,需要手工在编译 PHP 时激活。在 Unix 下,用 --enable-trans-sid 配置选项。如果此配置选项和运行时选项 session.use_trans_sid 都被激活(修改php.ini),相对 URI 将被自动修改为包含会话 ID。

● session_id

session_id() 用于设定或取得当前session_id。php5中既可以使用session_id(),也可以通过附加在url上的SID取得当前会话的session_id和session_name。

如果session_id()有具体指定值的话,将取代当前的session_id值。使用该函数前必须启动会话:session_start();

当我们使用session cookies时,如果指定了一个session_id()值,每次启动session_start()都会往客户端发送一个cookie值。不论当前session_id是否与指定值相等。
session_id()如果没有指定值,则返回当前session_id();当前会话没有启动的话,则返回空字符串。

● 检查session是否存在?

在以往的php版本中通常使用session_is_register()检查session是否存在,如果您使用$_SESSION[‘XXX’]=XXX来注册会话变量,则session_is_register()函数不再起作用。你可以使用
isset($_SESSION[‘xxx’])来替代。

● 更改session_id session_regenerate_id() 更改成功则返回true,失败则返回false。
使用该函数可以为当前session更改session_id,但不改变当前session的其他信息。例如:

<?php
session_start();
$old_sessionid = session_id();
session_regenerate_id();
$new_sessionid = session_id();
echo "原始 SessionID: $old_sessionid<br />";
echo "新的 SessionID: $new_sessionid<br />";
echo"<pre>";
print_r($_SESSION);
echo"</pre>";
?>

● session_name() 返回当前session的name或改变当前session的name。如果要改变当前session的name,必须在session_start()之前调用该函数。注意:session_name不能只由数字组成,它至少包含一个字母。否则会在每时每刻都生成一个新的session id.

session改名示例:

<?php
$previous_name = session_name("WebsiteID");
echo "新的session名为: $previous_name<br />";
?>

● 如何删除session?

1、unset ($_SESSION['xxx']) 删除单个session,unset($_SESSION['xxx']) 用来unregister一个已注册的session变量。其作用和session_unregister()相同。session_unregister()在PHP5中不再使用,可将之打入冷宫。

unset($_SESSION) 此函数千万不可使用,它会将全局变量$_SESSION销毁,而且还没有可行的办法将其恢复。用户也不再可以注册$_SESSION变量。

2、$_SESSION=array() 删除多个session

3、session_destroy()结束当前的会话,并清空会话中的所有资源。。该函数不会unset(释放)和当前session相关的全局变量(globalvariables),也不会删除客户端的session cookie.PHP默认的session是基于cookie的,如果要删除cookie的话,必须借助setcookie()函数。

返回值:布尔值。




功能说明:这个函数结束当前的session,此函数没有参数,且返回值均为true

session_unset() 如果使用了$_SESSION,则该函数不再起作用。由于PHP5必定要使用$_SESSION,所以此函数可以打入冷宫了。

下面是PHP官方关于删除session的案例:

<?php
// 初始化session.
session_start();
/*** 删除所有的session变量..也可用unset($_SESSION[xxx])逐个删除。****/
$_SESSION = array();
/***删除sessin id.由于session默认是基于cookie的,所以使用setcookie删除包含session id的cookie.***/
if (isset($_COOKIE[session_name()])) {
setcookie(session_name(), '', time()-42000, '/');
}
// 最后彻底销毁session.
session_destroy();
?>

由此我们可以得出删除Session的步骤:

①session_start()
②$_SESSION=array()/unset($_SESSION['xxx'])
③session_destroy()

● SESSION安全:

会话模块不能保证存放在会话中的信息只能被创建该会话的用户看到。根据其存放的数据,还需要采取更多措施来主动保护会话的完整性。

评估会话中携带的数据并实施附加保护措施通常要付出代价,降低用户的方便程度。例如,如果要保护用户免于受简单的社交策略侵害(注:指在 URL 中显示的会话 ID 会被别人在电脑屏幕上看到,或被别的网站通过 HTTP Referer 得到等),则应该启用 session.use_only_cookies。此情形下,客户端必须无条件启用 cookie,否则会话就不工作。

有几种途径会将现有的会话 ID 泄露给第三方。泄露出的会话 ID 使第三方能够访问所有与指定 ID 相关联的资源。第一,URL 携带会话 ID。如果连接到外部站点,包含有会话 ID 的 URL 可能会被存在外部站点的 Referer 日志中。第二,较主动的攻击者可能会侦听网段的数据包。如果未加密,会话 ID 会以明文方式在网络中流过。对此的解决方式是在服务器上实施 SSL 并强制用户使用。

默认情况下,所有与特定会话相关的数据都被存储在由 INI 选项 session.save_path 指定的目录下的一个文件中。对每个会话会建立一个文件(不论是否有数据与该会话相关)。这是由于每打开一个会话即建立一个文件,不论是否有数据写入到该文件中。注意由于和文件系统协同工作的限制,此行为有个副作用,有可能造成用户定制的会话处理器(例如用数据库)丢失了未存储数据的会话。

上面介绍函数下文将会用到,但还有一些有关session的函数也介绍一下:
session_encode
函数功能:sesssion信息编码
函数原型:string session_encode(void);
返回值:字符串
功能说明:返回的字符串中包含全局变量中各变量的名称与值,形式如:a s:12:"it is a test\";c s:4:"lala"; a是变量名 s:12代表变量a的值"it is a test的长度是12 变量间用分号”;”分隔。
session_decode
函数功能:sesssion信息解码
函数原型:boolean session_decode (string data)
返回值:布尔值
功能说明:这个函数可将session信息解码,成功则返回逻辑值true
Php5不再使用session_id,而是把它变成一个常量SID,并保存在cookie中。如果客户端禁用了cookie,php会自动通过url自动传动传递SID,其条件是设置php.ini中的session.use_trans_sid = 1。此时即使客户端即使禁用了cookie也没关系了。
用 strip_tags() 来输出 SID 以避免 XSS 相关的攻击。

Session跨页传递问题:

session跨页传递需要考虑三种情况:

①客户端禁用了cookie。
②浏览器出现问题,暂时无法存取cookie
③php.ini中的session.use_trans_sid = 0或者编译时没有打开--enable-trans-sid选项
为什么会这样呢?下面解释一下原因:

Session文件分为两部分:session变量保存在服务器端(默认以文件方式存储session);而session id则以cookie形式保存在客户端。(注意:session默认是基于cookie的)。

当用户的浏览器向服务器提出请求时,同时发送包含session id的cookie(默认情况下)。服务器根据客户端提供的session id来得到用户的文件,即保存在服务器端的session变量值。事实上,session id可以使用客户端的Cookie或者Http1.1协议的Query_String(就是访问的URL的“?”后面的部分)来传送给服务器,然后服务器读取Session的目录……。也就是说,session id是取得存储在服务上的session变量的身份证。当代码session_start();运行的时候,就在服务器上产生了一个session文件,随之也产生了与之唯一对应的一个session id,定义session变量以一定形式存储在刚才产生的session文件中。通过session id,可以取出定义的变量。跨页后,为了使用session,你必须又执行session_start();将又会产生一个session文件,与之对应产生相应的session id,用这个session id是取不出前面提到的第一个session文件中的变量的,因为这个session id不是打开它的“钥匙”。如果在session_start();之前加代码session_id($session id);将不产生新的session文件,直接读取与这个id对应的session文件。

PHP中的session在默认情况下是使用客户端的Cookie来保存session id的,所以当客户端的cookie出现问题的时候就会影响session了。必须注意的是:session不一定必须依赖cookie,这也是session相比cookie的高明之处。当客户端的Cookie被禁用或出现问题时,PHP会自动把session id附着在URL中,这样再通过session id就能跨页使用session变量了。但这种附着也是有一定条件的,其一:“php.ini中的session.use_trans_sid = 1或者编译时打开打开了--enable-trans-sid选项”;其二:运行PHP的服务器必须是unix/linux系统,windows不具备此项功能。

明白了以上的道理,我们就可以得出解决session跨页传递问题的三条途径:

1、设置php.ini中的session.use_trans_sid = 1或者编译时打开打开了--enable-trans-sid选项,让PHP自动跨页传递session id。

2、手动通过URL传值、隐藏表单传递session id。
3、用文件、数据库等形式保存session_id,在跨页过程中手动调用。

下面举例说明:

第一种情况:

page1.php
<?php
session_start();
$_SESSION['var1']="中华人民共和国";
$url="<a href="."\"s2.php\">下一页</a>";
echo $url;
?>
page2.php
<?php
session_start();
echo "传递的session变量var1的值为:".$_SESSION['var1'];
?>

运行以上代码,在客户端cookie正常的情况下,应该可以在得到结果“中华人民共和国”。
现在你手动关闭客户端的cookie,再运行,可能得不到结果了吧。如果得不到结果,再“设置php.ini中的session.use_trans_sid = 1或者编译时打开打开了--enable-trans-sid选项”,又得到结果“中华人民共和国”

第二种途径:

s1.php
<?php
session_start();
$_SESSION['var1']="中华人民共和国";
$sn = session_id();
$url="<a href="."\"s2.php?s=".$sn."\">下一页</a>"; //PHP5定义了一个常量SID来表示session_id(),$url还可以写成$url='<a href="page2.php?' . SID . '">下一页</a>';
echo $url;
?>
s2.php
<?php
session_id($_GET['s']);
session_start();
echo "传递的session变量var1的值为:".$_SESSION['var1'];
?>

第三种途径:

login.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Login</title>
<meta http-equiv="Content-Type" content="text/html; charset=??????">
</head>
<body>

请登录:

<form name="login" method="post" action="mylogin1.php">
用户名:<input type="text" name="name"><br>
口 令:<input type="password" name="pass"><br>
<input type="submit" value="登录">
</form>
</body>
</html>
mylogin1.php
<?php
$name=$_POST['name'];
$pass=$_POST['pass'];
if(!$name    !$pass) {
echo "用户名或密码为空,请<a href=\"login.html\">重新登录</a>";
die();
}
if (!($name=="laogong" && $pass=="123")) {
echo "用户名或密码不正确,请<a href=\"login.html\">重新登录</a>";
die();
}
//注册用户
ob_start();
session_start();
$_SESSION['user']= $name;
$psid=session_id();
$fp=fopen("e:\\tmp\\phpsid.txt","w+");
fwrite($fp,$psid);
fclose($fp);
//身份验证成功,进行相关操作
echo "已登录<br>";
echo "<a href=\"mylogin2.php\">下一页</a>";
?>
mylogin2.php
<?php
$fp=fopen("e:\\tmp\\phpsid.txt","r");
$sid=fread($fp,1024);
fclose($fp);
session_id($sid);
session_start();
if(isset($_SESSION['user']) && $_SESSION['user']="laogong" ) {
echo "已登录!";
}
else {
//成功登录进行相关操作
echo "未登录,无权访问";
echo "请<a href=\"login.html\">登录</a>后浏览";
die();
}
?>
posted @ 2008-10-01 13:29 hehuachina 阅读(257) | 评论 (0)编辑 收藏
header,php
1。PHP header() 函数

网上很多资料这样写:php的函数header()可以向浏览器发送Status标头,如 header("Status: 404 Not Found")。

但是我发现实际上浏览器返回的响应却是:

HTTP/1.x 200 OK
Date: Thu, 03 Aug 2006 07:49:11 GMT
Server: Apache/2.0.55 (Win32) PHP/5.0.5
X-Powered-By: PHP/5.0.5
Status: 404 Not Found
Content-Length: 0
Keep-Alive: timeout=15, max=98
Connection: Keep-Alive
Content-Type: text/html

查了一些资料,正确的写法是:
header("http/1.1 404 Not Found");
                           
第一部分为HTTP协议的版本(HTTP-Version);第二部分为状态代码(Status);第三部分为原因短语(Reason-Phrase)。若要想让浏览器不是从 Proxy 或 cache 中取得页面,可以使用下列的标头

header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . "GMT");
header("Cache-Control: no-cache, must-revalidate");
header("Pragma: no-cache");

具体含义下面解释。

2。禁止页面在IE中缓存

http响应消息头部设置:

CacheControl = no-cache
Pragma=no-cache
Expires = -1

[color=#000000]Expires是个好东东,如果服务器上的网页经常变化,就把它设置为-1,表示立即过期。如果一个网页每天凌晨1点更新,可以把
[/color][color=#000000]Expires[/color][color=#000000]设置为第二天的凌晨1点。

当HTTP1.1服务器指定
[/color]CacheControl = no-cache[color=#000000]时,浏览器就不会缓存该网页。

[/color]旧式 HTTP 1.0 服务器不能使用 Cache-Control 标题。所以为了向后兼容 HTTP 1.0 服务器,IE使用Pragma:no-cache 标题对 HTTP 提供特殊支持。如果客户端通过安全连接 (https://)与服务器通讯,且服务器在响应中返回 Pragma:no-cache 标题,则 Internet Explorer不会缓存此响应。注意:Pragma:no-cache 仅当在安全连接中使用时才防止缓存,如果在非安全页中使用,处理方式与 Expires:-1相同,该页将被缓存,但被标记为立即过期。

http-equiv meta标记:

在html页面中可以用http-equiv meta来标记指定的http消息头部。老版本的IE可能不支持html meta标记,所以最好使用http消息头部来禁用缓存。

3。隐藏文件的位置


html标签 <A href='http://hostname/*.mp3'></a>就可以实现普通文件下载。如果为了保密文件,就不能把文件链接告诉别人,可以用header函数实现文件下载。

header("Content-type: audio/mpeg");
header("Content-Disposition: attachment; filename=filenale");
header("Content-Description: PHP3 Generated Data");


4。header函数前输入内容

一般来说在header函数前不能输出html内容,类似的还有setcookie() 和 session 函数,这些函数需要在输出流中增加消息头部信息。如果在header()执行之前有echo等语句,当后面遇到header()时,就会报出 “Warning: Cannot modify header information - headers already sent by ....”错误。就是说在这些函数的前面不能有任何文字、空行、回车等,而且最好在header()函数后加上exit()函数。例如下面的错误写法,在两个php代码段之间有一个空行:

<?php
  //some code here
?>
//这里应该是一个空行
<?php
    header("http/1.1 403 Forbidden");
    exit();
  ?>

原因是:PHP脚本开始执行 时,它可以同时发送http消息头部(标题)信息和主体信息. http消息头部(来自 header() 或SetCookie() 函数)并不会立即发送,相反,它被保存到一个列表中. 这样就可以允许你修改标题信息,包括缺省的标题(例如Content-Type 标题).但是,一旦脚本发送了任何非标题的输出(例如,使用 HTML 或 print()调用),那么PHP就必须先发送完所有的Header,然后终止 HTTPheader.而后继续发送主体数据.从这时开始,任何添加或修改Header信息的试图都是不允许的,并会发送上述的错误消息之一。

解决办法:

修改php.ini打开缓存(output_buffering),或者在程序中使用缓存函数ob_start(),ob_end_flush()等。原理是:output_buffering被启用时,在脚本发送输出时,PHP并不发送HTTPheader。相反,它将此输出通过管道(pipe)输入到动态增加的缓存中(只能在PHP4.0中使用,它具有中央化的输出机制)。你仍然可以修改/添加header,或者设置cookie,因为header实际上并没有发送。当全部脚本终止时,PHP将自动发送HTTP header到浏览器,然后再发送输出缓冲中的内容。
posted @ 2008-09-29 17:02 hehuachina 阅读(1079) | 评论 (0)编辑 收藏
     摘要: <?php/************************************************************** * login.php * @author 风舞  * @email wjiujun (at) gmail.com * @no...  阅读全文
posted @ 2008-09-29 16:19 hehuachina 阅读(269) | 评论 (0)编辑 收藏
install
1.download package
jQuery Grid Plugin 3.2 with docs
解壓後,放到自建的jqGrid資料夾

2.建立html page
放在jqGrid下,並include jqGrid的js及css

<script type="text/javascript" src="jquery.js"></script> //1.jquery core
<script type="text/javascript" src="jquery.jqGrid.js"></script> //2.jqGrid的js
<link rel="stylesheet" type="text/css" media="screen" href="themes/basic/grid.css" /> //3.jqGrid的css


3.environment配置
在jquery.jqGrid.js裡,有兩個地方需要調整:
(1)js的路徑
有個pathtojsfiles變數
var pathtojsfiles = "js/"; // need to be ajusted
此為設定要載入的js檔路徑

(2)圖檔路徑
imgpath: 'themes/basic/images';


**備註
每個欄位長度至少要60以上,不會排序的圖(遞增,遞減)會看不見
posted @ 2008-09-06 19:04 hehuachina 阅读(985) | 评论 (0)编辑 收藏
ExtJS是一个挺热的Framework,它非常齐全,但是这也带来了一些问题,就是框架太庞大了,如果没有智能感知单凭记忆来写代码未免有点麻烦。可是如果直接在代码中添加ext_all_debug.js等文件的reference,智能感知会提示你出错而无法更新。之前ExtJS的社区里有人提供了一个js文件,可以实现VS中的智能感知,但是这个文件毕竟是2007年11月的了。在这样的情况下,很多程序员只好选择Apex或者Spekt这样的开发环境。

  但是在不同开发环境中切换,以及放弃VS高度集成的优势,不能不说是一种遗憾。而智能感知出错的原因主要在于,其自身的模拟执行环境不能正确地模拟窗体事件。现在提供一个小技巧,其实很简单:

 

1. 在ext-base.js的第一行添加

window.addEventListener = false;

2. 在你编写代码的脚本加上

/// <reference path="adapter/ext-base.js"/>
/// <reference path="ext-all-debug.js"/>
效果如图:
image 
(Ext 2.02)
 
image 
(Ext 1.x)



注意:在发布的时候,别忘记了把Ext-base.js中加进去的那行代码注释掉。
posted @ 2008-09-04 10:34 hehuachina 阅读(509) | 评论 (0)编辑 收藏
     摘要: 开源的工作流很少有让人满意的,即便是国内用的比较多的jbpm,用起来也会觉得很便扭。再加上PHP中没有什么好用的工作流,于是干脆自己设计一个,设计的原则如下: 1 根据80/20原则,只使用wfmc模型中最符合自身应用的20%功能 2 充分吸收国内使用jbpm开发BOSS中遇到的问题,工作流引擎只负责参数的收集和流程的流转,具体和业务的控制,交给每个流程定制的控制类去实现。 3 表单采用简单...  阅读全文
posted @ 2008-08-14 21:06 hehuachina 阅读(538) | 评论 (0)编辑 收藏

<?
/*
@string 构造函数中,$string="aa.php:7|tt.php:10|sad:28"
@列出/只读 1
@增加       2
@修改       4
@删除       8
@所有权限    16
*/
class yqrRight
{
var $RightString;
var $arrPageRight;
function yqrRight($string)
{
   $this->RightString=$string;
   $this->arrPageRight=$this->listPageAndRight($string);
}

/*
@pagename eg: order.php
return 28 number
*/
function getRightByPageName($pagename)
{
   return $this->getRightNumOfPage($pagename,$this->arrPageRight);
}
/*
@right_position 1,2,4,8,16
@myright_number 28
@return 返回是否具有相应的位权
*/
function can($right_position,$myright_number)
{
   $arr=$this->listRightToArray($myright_number);
   return $this->isHasRight($right_position,$arr);
}
function listRightToArray($myright)
{
   $right=array(1,2,4,8,16);
   $arr=array();
   $j=0;
   for($i=0;$i<count($right);$i++)
   {
    if($right[$i] & $myright)
    {
     $arr[$j]=$right[$i];
     $j++;
    }
   }
   return $arr;
}

function isHasRight($number_right,$arr_right)
{
   if(array_search($number_right,$arr_right)!==false)
   {
    return true;
   }else{
    return false;
   }
}

function listPageAndRight($str)
{
   $arr_result=array();
   $arr_page_right=explode("|",$str);
   foreach ($arr_page_right as $key=>$value)
   {
    list($pagename,$pageright)=explode(":",$value);
    $arr_result[$pagename]=$pageright;
   }
   return $arr_result;
}

function getRightNumOfPage($pageName,$arr_PageAndRight)
{
   foreach ($arr_PageAndRight as $key=>$value)
   {
    if($key==$pageName)
    {
     return $value;
    }
   }
   return false;
}
function isHasRightOfPage($pagename,$right_position)
{
   $num=$this->getRightByPageName($pagename);
   return $this->can($right_position,$num);
}

}

$str="order.php:7|add.php:28|sad.php:0|tt.php:15";
$myright=new yqrRight($str);

if($myright->isHasRightOfPage("tt.php",16))
{
echo "您具有本页面的权限!";
}else{
echo "对不起,您没有权限访问这个页面!";
}

?>

posted @ 2008-08-08 23:32 hehuachina 阅读(1102) | 评论 (0)编辑 收藏

常见的分页处理流程为:

1、用select count(*) from tbl_name取得待分页的总记录数

2、根据每页的记录数计算出总页数:总页数 = ceil(总记录数/每页记录数)

3、根据当前页号计算出起始位置:起始位置 = (当前页号-1)*每页记录数

4、用select * from tbl_name limit 起始位置,每页记录数 取得待显示记录

5、列表输出相关信息

在这个流程中,数据库需要两次遍历表才能得到所需数据。尽管limit会在得到指定记录数后会终止遍历,但前面直到“起始位置”的检索是浪费掉的。

这里提出一种新算法与大家讨论:

1、利用mysql的用户变量,分割并提取每页起始的id号。

2、查询结果的记录数即为总页数

3、根据当前页号取得当前页的起始id

4、用select * from tbl_name where id>=起始id limit 每页记录数 取得待显示记录

5、列表输出相关信息

可以看到,在后一次查询中。由于利用了id作为主键的特征,数据库可直接定位到所需记录。从而减少了查询时间。

这个查询算法有一个副产品:可以产生一条用于衔接上下页的重复记录,也就是各页间有一条重叠的记录。当然,去掉他也是很容易的。

以下是测试代码:

<?PHP

include "mysql_result_all.inc"; // 用于显示查询结果的工作函数

$pagesize = 9; // 每页行数

$type = 1; // =1降序排列

$mode = 0; // =1不重复上页最后一条记录

$conn = mysql_connect(); // 连接mysql

mysql_select_db("site"); // 选择数据库

// 准备动态修改查询串

if($type) {

$order = "desc";

$expr = "<=";

}else {

$order = "";

$expr = ">=";

}

if($mode) $pagesize++;

mysql_query("set @v:=-1"); // 定义mysql用户变量

$rs = mysql_query("select @v:=(@v+1) as xh, id from data HAVING mod(xh,$pagesize)=0 order by id $order");

mysql_result_all($rs); // 检查各页分布

echo $pages = mysql_num_rows($rs); // 取得总页数

if($mode) $pagesize--;

// 测试分页结果,$i表示显示页

for($i=0;$i<$pages;$i++) {

mysql_data_seek($rs,$i); // 移动结果集指针

list($xh,$id) = mysql_fetch_row($rs); // 取得起始id

echo "<br>[$i] $xh -- $id";

$rs1 = mysql_query("select * from data where id$expr$id order by id $order limit $pagesize");

mysql_result_all($rs1); // 显示相关结果

}

?>

mysql_result_all.inc

这个函数我贴过多次了,对调试程序非常有用的。

<?

function mysql_result_all($result,$format="") {

echo "<table $format><tr>";

for($i=0;$i<mysql_num_fields($result);$i++) {

echo "<th>".mysql_field_name($result,$i)."</th>";

}

echo "</tr>";

while($row = mysql_fetch_row($result)) {

echo "</tr>";

for($i=0;$i<mysql_num_fields($result);$i++) {

echo "<td>".$row[$i]."</td>";

}

echo "</tr>";

}

echo "</table>";

}

?>

posted @ 2008-08-08 23:09 hehuachina 阅读(203) | 评论 (0)编辑 收藏
来源:http://www.phpchina.com/bbs/viewthread.php?tid=29502
在开发过程中,往往因为表单出错而返回页面的时候填写的信息都不见了,为了支持页面回跳,可以通过两种方法实现。
第一,使用Header方法设置消息头Cache-control
header('Cache-control: private, must-revalidate');  //支持页面回跳
第二,使用session_cache_limiter方法
//注意要写在session_start方法之前
session_cache_limiter('private, must-revalidate');
PS:Cache-Control消息头域说明
Cache-Control指定请求和响应遵循的缓存机制。在请求消息或响应消息中设置Cache-Control并不会修改另一个消息处理过程中的缓存处理过程。请求时的缓存指令包括no-cache、no-store、max-age、max-stale、min-fresh、only-if-cached,响应消息中的指令包括public、private、no-cache、no-store、no-transform、must-revalidate、proxy-revalidate、max-age。各个消息中的指令含义如下:
Public指示响应可被任何缓存区缓存。
Private指示对于单个用户的整个或部分响应消息,不能被共享缓存处理。这允许服务器仅仅描述当用户的部分响应消息,此响应消息对于其他用户的请求无效。
no-cache指示请求或响应消息不能缓存
no-store用于防止重要的信息被无意的发布。在请求消息中发送将使得请求和响应消息都不使用缓存。
max-age指示客户机可以接收生存期不大于指定时间(以秒为单位)的响应。
min-fresh指示客户机可以接收响应时间小于当前时间加上指定时间的响应。
max-stale指示客户机可以接收超出超时期间的响应消息。如果指定max-stale消息的值,那么客户机可以接收超出超时期指定值之内的响应消息。
posted @ 2008-08-06 11:55 hehuachina 阅读(210) | 评论 (0)编辑 收藏

<?php
/**
 * 页面作用:常用表单验证类
 * 作 者:欣然随风
 * 建立时间:2006-3-6
 * QQ:276624915
 */

class class_post
{
 //验证是否为指定长度的字母/数字组合

 function fun_text1($num1,$num2,$str)
 {
    Return (preg_match("/^[a-zA-Z0-9]{".$num1.",".$num2."}$/",$str))?true:false;
 }

 //验证是否为指定长度数字

 function fun_text2($num1,$num2,$str)
 {
    return (preg_match("/^[0-9]{".$num1.",".$num2."}$/i",$str))?true:false;
 }
 //验证是否为指定长度汉字

 function fun_font($num1,$num2,$str)
 {
 // preg_match("/^[\xa0-\xff]{1,4}$/", $string);

    return (preg_match("/^([\x81-\xfe][\x40-\xfe]){".$num1.",".$num2."}$/",$str))?true:false;
 }
 //验证身份证号码

 function fun_status($str)
 {
    return (preg_match('/(^([\d]{15}|[\d]{18}|[\d]{17}x)$)/',$str))?true:false;
 }

 //验证邮件地址

 function fun_email($str){
    return (preg_match('/^[_\.0-9a-z-]+@([0-9a-z][0-9a-z-]+\.)+[a-z]{2,4}$/',$str))?true:false;
 }
 //验证电话号码

 function fun_phone($str)
 {
  return (preg_match("/^((\(\d{3}\))|(\d{3}\-))?(\(0\d{2,3}\)|0\d{2,3}-)?[1-9]\d{6,7}$/",$str))?true:false;
 }
 //验证邮编

 function fun_zip($str)
 {
  return (preg_match("/^[1-9]\d{5}$/",$str))?true:false;
 }
 //验证url地址

 function fun_url($str)
 {
  return (preg_match("/^http:\/\/[A-Za-z0-9]+\.[A-Za-z0-9]+[\/=\?%\-&_~`@[\]\':+!]*([^<>\"\"])*$/",$str))?true:false;
 }

 // 数据入库 转义 特殊字符 传入值可为字符串 或 一维数组

 function data_join(&$data)
 {
  if(get_magic_quotes_gpc() == false)
  {
   if (is_array($data))
   {
    foreach ($data as $k => $v)
    {
     $data[$k] = addslashes($v);
    }
   }
   else
   {
    $data = addslashes($data);
   }
  }
  Return $data;
 }

 // 数据出库 还原 特殊字符 传入值可为字符串 或 一/二维数组

 function data_revert(&$data)
 {
  if (is_array($data))
  {
   foreach ($data as $k1 => $v1)
   {
    if (is_array($v1))
    {
     foreach ($v1 as $k2 => $v2)
     {
      $data[$k1][$k2] = stripslashes($v2);
     }
    }
    else
    {
     $data[$k1] = stripslashes($v1);
    }
   }
  }
  else
  {
   $data = stripslashes($data);
  }
  Return $data;
 }

 // 数据显示 还原 数据格式 主要用于内容输出 传入值可为字符串 或 一/二维数组

 // 执行此方法前应先data_revert(),表单内容无须此还原

 function data_show(&$data)
 {
  if (is_array($data))
  {
   foreach ($data as $k1 => $v1)
   {
    if (is_array($v1))
    {
     foreach ($v1 as $k2 => $v2)
     {
      $data[$k1][$k2]=nl2br(htmlspecialchars($data[$k1][$k2]));
      $data[$k1][$k2]=str_replace(" ","&nbsp;",$data[$k1][$k2]);
      $data[$k1][$k2]=str_replace("\n","<br>\n",$data[$k1][$k2]);
     }
    }
    else
    {
     $data[$k1]=nl2br(htmlspecialchars($data[$k1]));
     $data[$k1]=str_replace(" ","&nbsp;",$data[$k1]);
     $data[$k1]=str_replace("\n","<br>\n",$data[$k1]);
    }
   }
  }
  else
  {
   $data=nl2br(htmlspecialchars($data));
   $data=str_replace(" ","&nbsp;",$data);
   $data=str_replace("\n","<br>\n",$data);
  }
  Return $data;
 }
 }
?>

posted @ 2008-08-06 10:35 hehuachina 阅读(669) | 评论 (0)编辑 收藏
仅列出标题  下一页