首页 > 编程技术 > php

PHP中Cookies指南

发布时间:2016-11-25 17:13

综述

  Cookie是在HTTP协议下,服务器或脚本可以维护客户工作站上信息的一种方式。Cookie是由Web服务器保存在用户浏览器上的小文件,它可以包含有关用户的信息(如身份识别号码、密码、用户在Web站点购物的方式或用户访问该站点的次数)。无论何时用户链接到服务器,Web站点都可以访问Cookie信息。

  怎样设置cookies?

  在PHP中可以使用setcookie函数设置一个cookie。cookie是 HTTP标头的一部分, 因此设置cookie功能必须在任何内容送到浏览器之前。这种限制与header()函数一样。任何从客户端传来的cookie将自动地转化成一个PHP变量。PHP取得信息头并分析, 提取cookie名并变成变量。因此,假如设置cookie如setcookie("mycookie","Cookies")php将自动产生一个名为$mycookie,值为"Cookies"的变量。

  我们来看一下setcookie函数语法:


  init setcookie(string CookieName,string CookieValue,int CookieExpireTime,path,domain,int secure);

  参数说明:

  PATH:表示web服务器上的目录,默认为被调用页面所在目录

  DOMAIN:cookie可以使用的域名,默认为被调用页面的域名。这个域名必须包含两个".",所以假如你指定你的顶级域名,你必须用".mydomain.com"

  SECURE:假如设为"1",表示cookie只能被用户的浏览器认为是安全的服务器所记住.

cookies使用举例

  假设我们有这样一个需要注册的站点,它自动识别用户的身份并进行相关的操作:假如是已经注册的用户,发送给他信息;假如不是已经注册的用户,则显示一个注册页面的链接。

  按照上面的要求,我们先创建数据库用来保存注册用户的信息:名字(first name),姓(last name),Email地址(email address),计数器(visit counter)。

  先按下面步骤建表:


mysql> create database users;
    Query OK, 1 row affected (0.06 sec)
    mysql> use users;
    Database changed
    mysql> create table info (FirstName varchar(20), LastName varchar(40), email varchar(40), count varchar(3));
    Query OK, 0 rows affected (0.05 sec)
  然后建一个php页面对照数据库检查cookies。

  由于php能转换可识别的cookie为相应的变量,所以我们能检查一个名为"myCookies" 的变量:


<? if (isset($myCookies)) { // 假如Cookie已经存在
    ……
    } else { //假如Cookie不存在
    ……
    }
    ?>

  当cookie存在时,我们执行下面步骤:

  首先取得cookie值,用explode函数分析成不同的变量,增加计数器,并设一个新cookie:


$info = explode("&", $myCookies);
    ……
    $count ;
    $CookieString=$FirstName.'&'.$LastName.'&'.$email.'&'.$count;
    SetCookie ("myCookies",$CookieString, time() 3600); //设置cookie

  接着用html语句输出用户信息。

  最后,用新的计数器值更新数据库。

  假如这个cookie不存在,我们显示一个注册页(register.php)的链接。

PHP接收多个同名复选框信息不像ASP那样自动转换成为数组,这给使用带来了一定不便。但是还是有解决办法的,就是利用javascript做一下预处理。多个同名复选框在javascript中还是以数组的形式存在的,所以在表单提交之前可以利用javascript把复选框中的信息组合成一个字符数组赋值给表单中的隐藏元素,然后用PHP中的explode函数解析此数组,这样就可以实现复选框信息的传递了。下面举例说明。

  假设有这样一个表单:


<form name="form1" id="form1" method="post" action="myphp.php" onSubmit="return Checker()">
<input type="checkbox" name="item" value="1">1<br>
<input type="checkbox" name="item" value="2">2<br>
<input type="checkbox" name="item" value="3">3<br>
<input type="checkbox" name="item" value="4">4<br>
<input type="hidden" name="items" value="">
<input type="submit" value="Submit">
</form>


  这个表单有四个名字都是item的复选框,当用户单击Submit按钮的时候,Checker函数会被调用,并且假如Checker返回true表单就被提交,返回false表单就不会被提交。这里Checker函数就是我们要编写的预处理函数。在HTML的header部分添加下面的javascript:


<script language="javascript">
<!--
function Checker()
{
 form1.items.value = "";
 if ( !form1.item.length ) // 只有一个复选框,form1.item.length = undefined
 {
  if ( form1.items.checked )
   form1.items.value = form1.item.value;
 }
 else
 {
  for ( i = 0 ; i < form1.item.length ; i )
  {
   if ( form1.item(i).checked ) // 复选框中有选中的框
   {
    form1.items.value = form1.item(i).value;
    for ( j = i 1 ; j < form1.item.length ; j )
    {
     if ( form1.item(j).checked )
     {
      form1.items.value = " "; //用空格做分割符
      form1.items.value = form1.item(j).value;
     }
    }
    break;
   }
  }
 }
 return true;
}
-->
</script>


  这样就可以把所有选中的复选框的value组合成为一个字符串数组,在myphp.php使用这样的语句:


$items = explode(" ", $HTTP_POST_VARS["items"]);


  就可以把这些选项分离出来成为数组。需要注重的是选项中的value不能包含分割符(这里是空格)。

建立一个Exception对象后你可以将对象返回,但不应该这样使用,更好的方法是用throw要害字来代替。throw用来抛出异常:

throw new Exception("my message", 44 );

  throw 将脚本的执行中止,并使相关的Exception对象对客户代码可用。

  以下是改进过的getCommandObject() 方法:

  index_php5.php

<?php
 // PHP 5
 require_once('cmd_php5/Command.php');
 class CommandManager {
  private $cmdDir = "cmd_php5";

  function getCommandObject($cmd) {
   $path = "{$this->cmdDir}/{$cmd}.php";
   if (!file_exists($path)) {
    throw new Exception("Cannot find $path");
   }
   require_once $path;
   if (!class_exists($cmd)) {
   throw new Exception("class $cmd does not exist");
   }

   $class = new ReflectionClass($cmd);
   if (!$class->isSubclassOf(new ReflectionClass('Command'))) {
    throw new Exception("$cmd is not a Command");
   }
   return new $cmd();
  }
 }
?>

  代码中我们使用了PHP5的反射(Reflection)API来判定所给的类是否是属于Command 类型。在错误的路径下执行本脚本将会报出这样的错误:

Fatal error: Uncaught exception 'Exception' with message 'Cannot find command/xrealcommand.php' in /home/xyz/BasicException.php:10
Stack trace:
#0 /home/xyz/BasicException.php(26):
CommandManager->getCommandObject('xrealcommand')
#1 {main}
thrown in /home/xyz/BasicException.php on line 10

  默认地,抛出异常导致一个fatal error。这意味着使用异常的类内建有安全机制。而仅仅使用一个错误标记,不能拥有这样的功能。处理错误标记失败只会你的脚本使用错误的值来继续执行。

串行化可以把变量包括对象,转化成连续bytes数据,你可以将串行化后的变量存在一个文件里或在网络上传输,然后再反串行化还原为原来的数据。你在反串行化类的对象之前定义的类,PHP可以成功地存储其对象的属性和方法. 有时你可能需要一个对象在反串行化后立即执行。为了这样的目的,PHP会自动寻找_sleep和_wakeup方法。

  当一个对象被串行化,PHP会调用_sleep方法(假如存在的话). 在反串行化一个对象后,PHP 会调用_wakeup方法. 这两个方法都不接受参数. _sleep方法必须返回一个数组,包含需要串行化的属性. PHP会抛弃其它属性的值。假如没有_sleep方法,PHP将保存所有属性。

  例子1显示了如何用_sleep和_wakeup方法来串行化一个对象. Id属性是一个不打算保留在对象中的临时属性. _sleep方法保证在串行化的对象中不包含id属性. 当反串行化一个User对象,_wakeup方法建立id属性的新值. 这个例子被设计成自我保持. 在实际开发中,你可能发现包含资源(如图像或数据流)的对象需要这些方法。

  Listing1 Object serialization

class User
{
 public $name;
 public $id;

 function _construct()
 {
  //give user a unique ID 赋予一个不同的ID
  $this->id = uniqid();
 }

 function _sleep()
 {
  //do not serialize this->id 不串行化id
  return(array("name"));
 }

 function _wakeup()
 {
  //give user a unique ID
  $this->id = uniqid();
 }
}

//create object 建立一个对象
$u = new User;
$u->name = "Leon";

//serialize it 串行化 注重不串行化id属性,id的值被抛弃
$s = serialize($u);

//unserialize it 反串行化 id被重新赋值
$u2 = unserialize($s);

//$u and $u2 have different IDs $u和$u2有不同的ID
print_r($u);
print_r($u2);
?>

这两天项目开发中,需要实现一些比较实用的功能,用了两个使用的sql,总结一下,怕下次忘记了。

1. 检索数据库中跟提交的内容相匹配的内容

比如:提交的数据是“游泳”,那么数据库中有“我喜欢游泳”字样的就算是匹配,但是这样一来,还是不够,比如我提交的是“周末去游泳”,数据库中有“游泳”的内容,其实意思类似,但是却使用like找不到的,于是想到下面的sql,已经封装成函数了:

function getRelationTags($tagTitle,$cols="*")
{
$titleFeildStrLen = 24; //3*8 四个汉字或者24个字符.
if ("" == $tagTitle) return false;

$sql = "select $cols from ".$TableName." where title != '' and (LOCATE(title,'$tagTitle') or ((issystem = 1 or LENGTH(title) <= $titleFeildStrLen) and title like '%".$tagTitle."%' )) order by LENGTH(title) ";
$data =& $db->getAll($sql);
if(DB::isError($data)){
return $this->returnValue($data->getMessage());
}else{
return $data;
}
}

看sql:

select $cols from ".$TableName." where title != '' and (LOCATE(title,'$tagTitle') or ((issystem = 1 or LENGTH(title) <= $titleFeildStrLen) and title like '%".$tagTitle."%' )) order by LENGTH(title)

其实就是两次匹配,一次是正向匹配,就是把提交的标签跟数据库中标签进行匹配,第二次是把数据库中的标签跟提交的标签进行匹配。

要害在LOCATE()函数,同时也限制了长度,因为mysql中的编码是:

set names 'utf8'

就是是utf8的,那么一个汉字要占用3个字节,字符只占用1个字节,所以上面的:

$titleFeildStrLen = 24;

就是8个汉字和24个字符范围那的标签进行匹配。


2. 同类排序

数据库中比如是这样的内容:

北京 1023 1

天津 2301 1

上海 3450 1

天津 4520 1

北京 3902 1

那么我要提取所有的城市数据,并且把每种城市数据的总数跟别的城市总数进行比较后排序。

函数代码如下:

function getMostCity($num)

{

$sql = "select count(id) as num,city from ".$TableName." where city != '' group by city order by num desc limit 0,$num;";

$data =& $db->getAll($sql);

if($db->isError($data))

return false;

else

return $data;

}

我们关注一下上面的sql语句:

select count(id) as num,city from ".$TableName." where city != '' group by city order by num desc limit 0,$num

核心就是 group by city 把类似城市集中起来后按照多到少排序。

标签:[!--infotagslink--]

您可能感兴趣的文章: