php入门第七天

    Form的提交及页面间的传值。
    Cookie是存放在客户的硬盘上的文件,每种浏览器都有它各自的位置。记得有一回我用不同的浏览器上两个百度号,结果两个浏览器上的用户都成了我后上的那个号,这个用浏览器的Cookie是做不到的,显然用的是flash cookie。也许是为了方便用多个号发贴的人,后来就没遇到这样的事了。Flash是个比较不安全的东西,但有时又不得不用,比如要在新浪上传相片,用没有Flash的浏览器来,虽然相应地显示了有file控件的界面,但图就是传不上去,不知道出于什么目的。吐完了,说正文。
<?php
session_start();
$_SESSION['list'] = [4, 3, 2, 1, '1', '"', "'", ['a' => 1, 'b' => 2]];
//序列化输出 session
echo serialize($_SESSION);
?>
然后,你在opera浏览器中的首选项查看cookie,点管理cookie,在本地的ip(一般是127.0.0.1)可以看到一个PHPSESSID,也就是说在一般情况下,session的key是基于客户的浏览器的。
如果你的wamp安装在D:\wamp,那么你可以在D:\wamp\tmp找到session文件,用记事本之类的软件打开,文件内容和序列化的session差不多。
Cookie和Session在同一浏览器的各个页面都是同样的值
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<?php
isset($_SESSION) === FALSE && print('没有$_SESSION这个数组,因为没session_start()');
session_start();
var_dump(['session' => $_SESSION], ['cookie' => $_COOKIE]);
/*Session 和 Cookie都是有时间限制的。但是cookie不支持数组,所以要存数组,需要先序列化,读数组时再反序列化。用json格式更短,但php的json要if很多情况,速度较慢,数组转过去,转回来的却是对象,反而不方便*/
$request_time = $_SERVER['REQUEST_TIME'];
setCookie('test_time', serialize([date('His', $request_time)]), $request_time+3600);
if (isset($_COOKIE['test_time']))
{// 删除cookie只需要先把值置为空,再让它时间到期就行。
    echo $_COOKIE['test_time'];
    setCookie('test_time', '', $request_time-3600);
}
?>
Session这样销毁
<?php
//第一步:开启Session并初使化
session_start();       
//第二步:还原Session
$_SESSION = array();   
//第三步:如果使用基于Cookie的Session,使用setCooike()删除包含Session Id的Cookie
$session_name = session_name();
isset($_COOKIE[$session_name]) && setcookie($session_name, '', time()-43200, '/');
//第四步:最后彻底销毁Session
session_destroy();
?>
    cookie的大小是受浏览器设置的限制的,一般浏览器都设为1000个字节长,一般够用;至于session则理论上只受服务器的硬盘大小的限制。但php自带的session有个问题,就是服务器的session的数量过多时,储存器的读写效率会很低下,所以一般较大的项目一般用sql或nosql来模似session的功能,而且这也直接解决了有多台服务器操作session的问题。
    Session的id是可以不用cookie的,一般是用url或隐藏域来代替,这种技术主要用于不支持cookie的比较老的手机的,一般这种手机在中国是没有的。url或隐藏域来作键是更安全的,这样就算客户的机子上有扫描用户cookie的软件,也是可以保护用户隐私的,因为他只存在于浏览器开着的时候,当然缓存文件是会记录有隐藏域的html的。但这个方法有三个缺点:
1、程序上不如用cookie做id来得方便。
2、跨界面性较差,比如你开了两个界面在同一浏览器,在一个界面上了,另一个没上,另一个的你点链接及在本页都不会让你上去。所以只适合手机这样的单页应用。
3、如果客户把浏览器关了,客户下次是无没自动登入的。
关于cookie的安全性:
    Cookie作为session的key时是用来确定用户的身份的,如果别人知道这个key就可以冒充用户,或者知道用户上了你的网站。
    又想说闲话了。话说MySpace这个网站,原来是美国的社交的主流的网站,这个网站很草根,什么英德裔、西班牙裔和非洲裔什么人都有。后来FaceBook创建了,它是基于常青藤大学的社交,所以美国社会的主流人群英德裔都跑那去了,MySpace就只有西班牙裔和非洲裔这样的少数民族了。
    所以你上了MySpace,结果你上别的网站,让别的网站读了你的cookie,向你推送针对西班牙裔和非洲裔的广告,不知道你会咋想。或者三K党在你家安了流氓软件,发现你就是那个在MySpace“说他们坏话”的人,先通过IP找到你家大概的位置(ivp4因为数量有限,所以并不是每家一个ip,而是你上线时,电信根据你的大概位置给你一个零时的IP;ivp6则可以做到一家一个ip,相当于网络实名制),正好你又是典型的美国式的单门独院,从你的电脑找你上了MySpace的证据,然后把你家人秘密枪决了之类的。
    一般网站还会在cookie中存一些不会影响到多个页面的逻辑的,而且他们认为不影响网站数据安全及客户个人隐私的一些东西。比如用cookie做购物车存些商品。
    关于cookie的安全性问题,只要你电脑没流氓软件,浏览器安全级别设置合理,不让javascript读取cookie等,一般不会有问题。
    你上一个网站,是因为你信任它,但它可能会不经过你同意而共享你的信息。比如你上新浪,会看到淘宝的广告,因为淘宝有新浪的股权,所以新浪可能会向淘宝共享你的信息,以便投放更准确的广告。另外新浪好像在美国上市的,所以会不会参加了美帝的梭镜计划也不好说。嗯,以上的话都没有事实根据,如有雷同,纯属巧合。
回正题:
    FORM默认的提交方法(method属性)是get,这种方法的一般是用于请求和查询数据的。get传送的信息会在地址栏显示,且方便缓存,虽然url长度有限制,但用于查询是足够了的,也防止有的人提交过多的信息。另外get最好用不要用于登录,会把密码显示出来,不过你可以加层frame,这样主界面不更新,就没有url的问题——建议不要没事用frame。如果你想把post转成url, 可以直接取 file_get_contents('php://input', 'r') 的post字符串,或者用http_build_query这个函数。
    在form.method为post时,处理这个页面的地址(action属性)默认是$_REQUEST['REQUEST_URI'];form.method为get时,action中用get传的值也就是$_REQUEST['QUERY_STRING']会被清除,留下空间给get提交,相当于$_REQUEST['PHP_SELF']。所以对于不能用cookie的手机,当用户登入后,便用把get当cookie用,用户则用post提交和有$_REQUEST['QUERY_STRING']的链接来向服务器请求,这时查询就只能用post了。用下面的代码操作一下,就明白了。
    下面的用网址 test.php/abc/tre?test=123 进去,会发现$_SERVER 的值的不同
<!-- form_test.php start -->
<?php ?> 
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta name="generator" content="PSPad editor, www.pspad.com">
<title></title>
</head>
<body>
<form action="<?php if (isset($_REQUEST['action'])) {echo $_SERVER[$_REQUEST['action']];}; ?>" method="<?php if ( ! isset($_REQUEST['get'])): ?>post<?php endif; ?>" accept-charset="utf-8" > 
<br/>id <input type="text" name="id" id="id" value="" maxlength="100" size="50" style="width:50%" />
<br/>name[] <input type="text" name="name[]" id="name" value="" maxlength="100" size="50" style="width:50%" />
<br/>name[] <input type="text" name="name[]" id="name" value="" maxlength="100" size="50" style="width:50%" />
<br/>area[bei] <input type="text" name="name[bei]" value="" maxlength="100" size="50" style="width:50%" />
<br/>area[YII] <input type="text" name="name[YII]" value="" maxlength="100" size="50" style="width:50%" />
<br/>
<input type="checkbox" name="get" value="">用GET提交
<input type="radio" name="action" value="REQUEST_URI">REQUEST_URI
<input type="radio" name="action" value="SCRIPT_NAME">SCRIPT_NAME
<input type="radio" name="action" value="PHP_SELF">PHP_SELF
  
<br/><input type="submit" name="submit" value="Submit Post!" />
<br/><input type="submit" name="submit2" value="Submit2 Post!" />
<br/><input type="reset" id="reset" value="重置">
<br/>
<?php if (isset($_POST['submit'])): ?>
isset($_POST['submit'])
<?php elseif (isset($_POST['submit2'])): ?>
isset($_POST['submit2'])
<?php else: ?>
还没提交
<?php endif; ?>
<?php 
var_dump(['$_POST' => $_POST]
, ['$_GET' => $_GET]
, ['$_SERVER' => $_SERVER]); 
?>
</form>
<script>
document.getElementById('reset').onclick = function() {
return confirm("确定要复原")
};
</script>
</body>
</html>
<!-- form_test.php end -->
    get因为基于url,易于保存状态,并可以方便地在页面间传值。但要用post保存状态就麻烦一些。先让我们看看CI用的隐藏域传值。
if ( ! function_exists('form_hidden'))
{
    function form_hidden($name, $value = '', $recursing = FALSE)
    {
        static $form;
        if ($recursing === FALSE)
        {
            $form = "\n";
        }
        if (is_array($name))
        {
            foreach ($name as $key => $val)
            {
                form_hidden($key, $val, TRUE);
            }
            return $form;
        }
        if ( ! is_array($value))
        {
            $form .= '<input type="hidden" name="'.$name.'" value="'.form_prep($value, $name).'" />'."\n";
        }
        else
        {
            foreach ($value as $k => $v)
            {
                $k = (is_int($k)) ? '' : $k;
                form_hidden($name.'['.$k.']', $v, TRUE);
            }
        }
        return $form;
    }
}
if ( ! function_exists('form_prep'))
{
    function form_prep($str = '', $field_name = '')
    {
        static $prepped_fields = array();
        // if the field name is an array we do this recursively
        if (is_array($str))
        {
            foreach ($str as $key => $val)
            {
                $str[$key] = form_prep($val);
            }
            return $str;
        }
        if ($str === '')
        {
            return '';
        }
        // we've already prepped a field with this name
        // @todo need to figure out a way to namespace this so
        // that we know the *exact* field and not just one with
        // the same name
        if (isset($prepped_fields[$field_name]))
        {
            return $str;
        }
        $str = htmlspecialchars($str);
        // In case htmlspecialchars misses these.
        $str = str_replace(array("'", '"'), array("'", """), $str);
        if ($field_name != '')
        {
            $prepped_fields[$field_name] = $field_name;
        }
        return $str;
    }
}
CI的说明是这样说的, form_hidden()
可以使你创建一个隐藏输入栏。你可以输入name和value来创建一个:
form_hidden('username', 'johndoe');


// 将产生:


<input type="hidden" name="username" value="johndoe" />
或者你也可以使用数组来联合创建它们:
$data = array(
              'name'  => 'John Doe',
              'email' => 'john@example.com',
              'url'   => 'http://example.com'
            );


echo form_hidden($data);


// 将产生:


<input type="hidden" name="name" value="John Doe" />
<input type="hidden" name="email" value="john@example.com" />
<input type="hidden" name="url" value="http://example.com" />
    不过我觉得如果用textarea代替hidden,不就不用怕单双引号破坏表单了吗,要隐藏,只需要<div style="display:none"><textarea 。。。。。。。。 </div>就可以也吗, 接着form_prep那句改成htmlspecialchars就可以了。
    有时觉得麻烦,可以直接拷上个模版的代码,再用<div style="display:none"></div>一夹也可行,但不建议这样做。
    另外还可以用序列化加base64来做。下面的函数还可以用来传URL和表单,而不会破坏URL和表单。
if ( ! function_exists('form_url_encode'))
{
    function form_url_encode($input)
    {
        return strtr(
            base64_encode(
                serialize($input)
            ), '+/=', '-_,'
        );
    }
}
if ( ! function_exists('form_url_decode'))
{
    function form_url_decode($input)
    {
        return unserialize(
            base64_decode(
                strtr($input, '-_,', '+/=')
            )
        );
    }
}
效率很高,不过生成的字符串会有些长。而且读的时候要decode。


还有一种msgpack的转字符串方法,据说无论效率及占用空间都有优势。不过要装扩展。详见http://msgpack.org/。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值