php复习

WBOY
Release: 2016-06-23 13:25:38
Original
1258 people have browsed it

最近要用php,好久不用感觉手生。抓起《零基础学PHP》一书复习了下,顺带学了smarty模板语言,然后到慕课网看了些php中级视频教程,这里记录下。

php最基本的文件上传

不用任何第三方库,纯html+php的文件上传。想想很简单,其实从文件传输出错的返回码也能看出程序写的怎么样,是否考虑到了所有情况。

从upload.html提交表单,上传文件到upload.php页面

upload.html:

<!DOCTYPE HTML><html><head>	<title>文件上传练习</title></head><body>	<h1>上传文件练习,最基本的形式</h1>	<form enctype="multipart/form-data" action="upload.php" method="post">		上传此文件:<input type="file" name="myfile" />		<input type="submit" value="提交上传" />	</form></body></html>
Copy after login

upload.php

<?php$upload_path = $_SERVER['DOCUMENT_ROOT']."/upload/";//basename():返回路径中的文件名部分$dest_file = $upload_path.basename($_FILES['myfile']['name']);if(move_uploaded_file($_FILES['myfile']['tmp_name'], $dest_file)){	echo "文件已经上传至服务器根目录的webbasic/upload目录下";}else{	echo "文件上传中发生了一个错误,错误代码:".$_FILES['myfile']['error']."<br/><br/>";	//var_dump($_FILES);	//测试发现:如果upload路径不存在,则上传肯定失败,但是$_FILES['myfile']['error']返回值为0,看不出错误。	//也就是说,分成“上传”和“移动”两部分,$_FILES['myfile']['error']只负责“上传”,而是否移动成功则需要根据move_uploaded_file()返回值来判断。	echo "错误分析:";	$err_num = $_FILES['myfile']['error'];	//参考:http://php.net/manual/zh/features.file-upload.errors.php	switch($err_num){		case 0:			$err_msg = "服务器上传文件存放目录出错";			break;		case 1:			$err_msg = "上传的文件超过了 php.ini 中 upload_max_filesize 选项限制的值";			break;		case 2:			$err_msg = "上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值";			break;		case 3:			$err_msg = "文件只有部分被上传";			break;		case 4:			$err_msg = "没有文件被上传";			break;		case 6:			$err_msg = "找不到临时文件夹";			break;		case 7:			$err_msg = "文件写入失败";			break;		default:			$err_msg = "其他错误!!";	}	echo $err_msg;}?>
Copy after login

PHP处理HTTP请求和SESSION管理

HTTP是无状态协议,服务器无法仅根据HTTP协议来判断发起请求的用户们谁是谁,要用SESSION来区分。实际上这里还需要客户端浏览器开启cookie来配合,cookie先不表。

最简单的场景:用户提交用户名和密码进行登录,发送的是POST请求,这个表单放到html页面就可以;表单提交后希望查看用户名和密码的具体值,要求刷新页面(再次发POST请求)、直接访问该页面(在浏览器地址栏后面敲回车,GET请求),都能正常显示用户名和密码的具体值。当然,如果是没有登陆过就来查看这个页面,也不应当显示用户名和密码,要重定向到登录页。

值得注意的一点:php中重定向比较常见,转发则比较麻烦。转发用header("Location:http://www.example.com/some.html")

登录页代码:

<!DOCTYPE html><html><head>	<meta charset="utf-8" />	<title>练习题3.4.1</title></head><body>	<form name="login" action="prac_bowl.php" method="post" onsubmit="return check_name()">	<table border="0" width="300px" align="center">		<tr>			<td>用户名:</td>			<td><input type="text" name="user_name"></td>		</tr>		<tr>			<td>密码:</td>			<td><input type="password" name="user_pass"></td>		</tr>		<tr>			<td><input type="submit" value="提交"></td>		</tr>	</table></form></body></html>
Copy after login

请求处理页:

<?phpsession_start();if(isset($_SESSION['user'])){	$user = $_SESSION['user'];	$pass = $_SESSION['pass'];}else{	//第一次发起POST请求,那么检查POST中相应字段是否不为空	if(isset($_POST['user_name']) && isset($_POST['user_pass'])){		//POST相应字段不为空,则取出值并赋值给SESSION存储		$user = $_POST['user_name'];		$pass = $_POST['user_pass'];		$_SESSION['user'] = $user;		$_SESSION['pass'] = $pass;		}else{		//POST相应字段有空值,或者不是POST请求,那么重定向到登录页面		header("Location:http://localhost/snowball/prac_login.html");		exit();	}}echo "用户名:".$user.'<br/>';echo "密码:".$pass.'<br/>';?>
Copy after login

cookie

学习Cookie

概述

HTTP是无状态协议。如果一个服务器不需要识别不同的用户,也就不需要维持不同用户的状态,就不用SESSION和COOKIE。

服务器为了识别当前请求发起者的身份,通过COOKIE和SESSION一起,进行识别,流程:
服务器会在客户端首次发起请求时,生成独一无二的SESSION_ID,并以Cookie的形式返还给用户,存储在用户浏览器中。
每次浏览器加载网站,浏览器都会把cookie发送给服务器,以通知服务器本用户先前的活动。

/*
Question:Cookie是通过HTTP协议发送的吗?SESSION是通过HTTP协议发送的吗?
是和表单请求和请求相应一起发送的吗?
Guess:应该是放在HTTP报文中的,和表单请求一起、和请求相应一起。
Answer:是一起的。

Cookie的获取:

通过浏览器上抓包发现,HTTP响应中的响应头包含Set-Cookie字段,值为“PHPSESSID=0e2vloo8fv35qpj448quostco1; path=/”形式

*/

分类

Session cookie (会话cookie)

当用户浏览网站时被存储在临时内存中,关掉浏览器就会被删除的一种cookie

Persistent cookie (持久cookie)

有确定的过期时间。生命周期内,每次用户访问相应网站时持久cookie的信息会被传送给服务器。
也称tracking cookie(跟踪cookie)

Secure cookie(安全cookie)

仅在使用加密连接(比如HTTPS)时被使用。

HttpOnly cookie

...

总结起来:
Session cookie(会话cookie)不带expire时间,那么相应地,HTTP响应中的Set-Cookie字段的值如果不带"Expires"或者"Max-Age"字样,那么一定是Session cookie。
/*
开个脑洞:wikipedia上说指定了Expires的cookie,会由浏览器在特定时间删除它。特定时间是什么?应该是Expires指定的deadline吧。那么我如果我的cookie还有24小时才过期,我现在关机,过了两天后我打开电脑但是不运行浏览器,或者干脆把硬盘拆下来接到另一个电脑上去读取原有的cookie,不行吗?

或许把这样的cookie传送给server已经不行了,但是拿到这原始的cookie后我们可以去修改cookie的过期时间,去hack。

所以我觉得wikipedia上的说法不正确。不能说浏览器删除cookie,而是cookie自动过期,浏览器检测到他们过期了,所以才删除他们。
额,好纠结,好像绕进去了,反正就是过期的cookie不能用,要用就需要hack。
*/

/
新问题:服务器端怎样设定发送给客户端的cookie类型?主要是session cookie和track cookie。
/

页面静态化

静态化就是把动态页面的内容,输出到缓冲区(而不是直接给用户),缓冲区内容再输出到文件(静态文件),然后用户访问静态文件。
我认为模板技术就是复杂版的静态化技术:简单的静态化就是把标准输出进行缓存,然后将缓存写入文件;模板技术在进行缓冲的同时还包括变量替换、编译等。两者本质是相同的。
模板文件一般是html代码为主,php脚本语句穿插其中。

静态化的步骤:

ob_start();   //开启缓冲区get_variables();  //获取变量,相关计算等。比如从数据库获取查询结果require_once('./templates/xxx.tpl');  //引入模板文件。其实是执行了模板文件,只不过输出被重定向到缓冲区了。file_put_contents($targetStaticFile, ob_get_clean());   //把缓冲区内容取出并清空,然后把取出的内容写入到目标静态文件。  以后访问目标静态文件$targetStaticFile就可以查看结果了
Copy after login

一个更加完整的例子:
用户访问index.php,如果缓存文件距离上次修改时间在300秒(5分钟)之内,那么读取原有的缓存文件index.shtml;否则,重新从数据库读取数据并写入静态缓存文件index.shtml,并且在页面上显示。
index.php内容如下:

<?php/*页面静态化步骤1.连接数据库,然后从数据库里面获取数据2.把获取到的数据填充到模板文件里面3.需要把动态的页面转化为静态页面,生成纯静态化文件*/$targetStaticFile = './index.shtml';//页面静态化的第一种方法:利用缓存时间判断//在静态文件上次修改的300秒之内,那么不更新,直接取静态文件if(is_file($targetStaticFile) && (time() - filemtime($targetStaticFile)) < 300) {	require_once($targetStaticFile);}else{	//获取数据库中的数据	require_once('./db.php');	$connect = mysql_connect("localhost","root","");	mysql_select_db("test", $connect);	$sql = "select * from news where `category_id`=1 and `status`='open' order by id desc limit 5";	$result = mysql_query($sql, $connect);	$news = array();	while($row = mysql_fetch_array($result)){		$news[] = $row;	}	ob_start(); //开启output buffering	require_once('./templates/singwa.tpl');	file_put_contents($targetStaticFile, ob_get_contents());	//引入模板文件	}
Copy after login

这里使用了ob_get_contents()函数,表示去出缓冲区的内容。ob_get_clean()函数则与之不同,是取出缓冲区内容后要清空缓冲区。这里index.php页面被调用,显然用户是要看到内容的,因此不能把缓冲区内容清空,因而要使用ob_get_contents()而不是ob_get_clean()函数。

缓存

现学现卖,看了imook网上的视频,自己敲了一下。
所谓缓存其实就是把从数据库中等地方取出的数据,存储到磁盘文件(哦,内存缓存?我还没有学到那里,先说磁盘的缓存好了)。

缓存操作包括:读取缓存,写入缓存,删除缓存。修改缓存就算了,直接删除后重新写入好了。
这里缓存文件内容使用了json格式进行存储,因而使用了json_encode和json_decode来进行编码解码。

编写了两个php文件:test.php用来调用缓存, response.php是缓存具体操作的实现

test.php:

<?phprequire_once('./response.php');$data = array(	'id'=>1,	'name'=>'singwa',	'type'=>array(4,5,6),	'test'=>array(1,45,67=>array(123, 'tsysa'),),);$file = new File();//缓存操作,请分别注释掉其他行来验证缓存操作是否OK$result = $file->cacheData('index_mk_cache', $data);  //写入缓存//$result = $file->cacheData('index_mk_cache', null);    //删除缓存//$result = $file->cacheData('index_mk_cache');      //查询缓存echo "<pre class="brush:php;toolbar:false">";if($result){	var_dump($result);	echo "success";}else{	echo "error";}echo "
Copy after login
";?>

缓存操作的具体实现:

<?php/*$arr = array(	'id'=>1,	'name'=>'Chris'	);$data = "输出json数据";$newData = iconv('UTF-8', 'GBK', $data);echo $newData;echo json_encode($newData);*///静态缓存class File{	private $_dir;	const EXT = ".txt";	public function __construct(){		$this->_dir = dirname(__FILE__).'/files/';	}	public function cacheData($key, $value='', $path=''){		$filename = $this->_dir.$path.$key.self::EXT;				if($value===''){			return $this->getCache($filename);//value为空,则获取缓存		}else if(is_null($value)){			return $this->removeCache($filename);		}else{			return $this->putCache($filename, $value);		}	}	private function getCache($filename){		//获取缓存		if(!is_file($filename)){			return FALSE;		}else{			//第二个参数为true,表示返回一个array,而不是object			return json_decode(file_get_contents($filename), true);		}	}	private function removeCache($filename){		//删除缓存(文件)		return unlink($filename);	}	private function putCache($filename, $value){		//写入缓存		$dir = dirname($filename);//dirname:返回路径中目录的部分		if(!is_dir($dir)){			mkdir($dir, 0777);		}		//写入缓存文件的内容,可以是json格式,也可以是序列化的格式		return file_put_contents($filename, json_encode($value));	}}?>
Copy after login

php与内存缓存redis

脑补

就像使用mysql一样,需要一个client和一个server。server不管它,client可以是terminal形式,也可以是web页面形式。
比如说terminal的形式好了。那么使用redis也一样,也需要一个terminal。我们可以用redis-cli命令进入redis,类似于mysql进入到mysql的交互界面一样。

redis默认使用6379端口

安装redis

看你用什么系统了,Fedora下安装:

yum install redissystemctl enable redissystemctl start redis
Copy after login

windows下安装:
到这里下载

redis基本命令使用

redis-cli 进入交互式命令行
set 变量名字 变量值 #设置缓存
get 变量名字 #获取缓存
setex 变量名字 失效时间 变量值 #设置缓存值和失效时间

del 变量名字 #删除缓存

如果缓存变量不存在,返回(nil)

php配置redis

要先安装phpredis扩展。php默认带了mysql的扩展所以感受不到,其实都是需要扩展的。
当前(2015年9月4日14:40:46)phpredis扩展在windows下只支持

从网上直接下载编译好的dll文件即可,一定要选择和php对应的版本。
php_redis-5.5-vc11-ts-x86-00233a.zip http://d-h.st/4A5
php_igbinary-5.5-vc11-ts-x86-c35d48.zip http://d-h.st/QGH

php_redis-5.5-vc11-nts-x86-00233a.zip http://d-h.st/uGS
php_igbinary-5.5-vc11-nts-x86-c35d48.zip http://d-h.st/bei

php_redis-5.5-vc11-ts-x64-00233a.zip http://d-h.st/1tO
php_igbinary-5.5-vc11-ts-x64-c35d48.zip http://d-h.st/rYb

php_redis-5.5-vc11-nts-x64-00233a.zip http://d-h.st/N0d
php_igbinary-5.5-vc11-nts-x64-c35d48.zip http://d-h.st/c1a

下载后将php_igbinary.dll和php_redis.dll放入php的ext目录下,

然后修改php.ini,加入这两个扩展,注意顺序不要反了。

extension=php_igbinary.dll

extension=php_redis.dll

重新启动Apache即可。

运行

先开redis-server

在fedora下就是:

sudo systemctl start redis
Copy after login

在windows下通过mintty进入到redis安装目录,执行:

redis-server.exe redis.conf
Copy after login

再开redis-client

我的意思是,以终端的形式开启redis,即执行:

redis-cli
Copy after login

严格讲,php.ini中加载了redis,那么只要php代码中定义了一个redis对象并进行了连接,那也是redis的客户端了。

执行php代码

在php代码中执行redis相关的操作。无非就是设置、读取、删除缓存,以及设置缓存失效时间。

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template