php复习
最近要用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>
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;
}
?>
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>
请求处理页:
<?php
session_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/>';
?>
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就可以查看结果了
一个更加完整的例子:
用户访问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());
//引入模板文件
}
这里使用了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:
<?php
require_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>";
if($result){
var_dump($result);
echo "success";
}else{
echo "error";
}
echo "</pre>";
?>
缓存操作的具体实现:
<?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));
}
}
?>
php与内存缓存redis
脑补
就像使用mysql一样,需要一个client和一个server。server不管它,client可以是terminal形式,也可以是web页面形式。
比如说terminal的形式好了。那么使用redis也一样,也需要一个terminal。我们可以用redis-cli
命令进入redis,类似于mysql进入到mysql的交互界面一样。
redis默认使用6379端口
安装redis
看你用什么系统了,Fedora下安装:
yum install redis
systemctl enable redis
systemctl start redis
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
在windows下通过mintty进入到redis安装目录,执行:
redis-server.exe redis.conf
再开redis-client
我的意思是,以终端的形式开启redis,即执行:
redis-cli
严格讲,php.ini中加载了redis,那么只要php代码中定义了一个redis对象并进行了连接,那也是redis的客户端了。
执行php代码
在php代码中执行redis相关的操作。无非就是设置、读取、删除缓存,以及设置缓存失效时间。
php复习的更多相关文章
- iOS总结_UI层自我复习总结
UI层复习笔记 在main文件中,UIApplicationMain函数一共做了三件事 根据第三个参数创建了一个应用程序对象 默认写nil,即创建的是UIApplication类型的对象,此对象看成是 ...
- vuex复习方案
这次复习vuex,发现官方vuex2.0的文档写得太简略了,有些看不懂了.然后看了看1.0的文档,感觉很不错.那以后需要复习的话,还是先看1.0的文档吧.
- 我的操作系统复习——I/O控制和系统调用
上篇博客介绍了存储器管理的相关知识——我的操作系统复习——存储器管理,本篇讲设备管理中的I/O控制方式和操作系统中的系统调用. 一.I/O控制方式 I/O就是输入输出,I/O设备指的是输入输出设备和存 ...
- 复习(1)【Maven】
终于开始复习旧知识了,有输入必然要有输出.输入和输出之间的内化过程尤为重要,在复习的同时,真正把学到的东西积淀下来,加深理解. Maven项目概念与配置 Maven是一个项目管理和综合工具.Maven ...
- 《CSS权威指南》基础复习+查漏补缺
前几天被朋友问到几个CSS问题,讲道理么,接触CSS是从大一开始的,也算有3年半了,总是觉得自己对css算是熟悉的了.然而还是被几个问题弄的"一脸懵逼"... 然后又是刚入职新公司 ...
- JS复习--更新结束
js复习-01---03 一 JS简介 1,文档对象模型 2,浏览器对象模型 二 在HTML中使用JS 1,在html中使用<script></script>标签 2,引入外部 ...
- jQuery 复习
jQuery 复习 基础知识 1, window.onload $(function(){}); $(document).ready(function(){}); 只执行函数体重的最后一个方法,事 ...
- jQuery5~7章笔记 和 1~3章的复习笔记
JQery-05 对表单和表格的操作及其的应用 JQery-06 jQuery和ajax的应用 JQery-07 jQuery插件的使用和写法 JQery-01-03 复习 之前手写的笔记.实在懒得再 ...
- HTML和CSS的复习总结
HTML(Hypertext Markup Language)超文本标记语言:其核心就是各种标记!<html> HTML页面中的所有内容,都在该标签之内:它主要含<head>和 ...
- 2017年1月1日 java学习第二天复习
今天是新年的第一天,以前学习没有总结习惯,学习效率和成果都很不好. 学习的过程就是反复的复习和不断学习的过程,开始今天的学习总结 学习java的第二天. 今天学习了java最基础的一些内容,照着 ...
随机推荐
- linux命令学习-复制(cp,scp)
linux为我们提供了两个用于文件的copy的命令,一个是cp,一个是scp.但是它们略有不同: cp主要用于在同一台电脑上,在不同的目录之间来回copy文件,scp主要是在不同的linux系统之间来 ...
- emberjs创建类
创建一个Person类Person = Ember.Object.extend({ say: function(thing) { alert(thing); } }); 创建一个Person对象也就是 ...
- JS 浮点数运算丢失精度解决方案
除法 function accDiv(arg1,arg2){ var t1=0,t2=0,r1,r2; try{t1=arg1.toString().split(".")[1].l ...
- 纯CSS3画出小黄人并实现动画效果
前言 前两天我刚发布了一篇CSS3实现小黄人动画的博客,但是实现的CSS3动画是基于我在站酷网找到的一张小黄人的jpg格式图片,并自己用PS抠出需要实现动画的部分,最后才完成的动画效果.但是,其实我的 ...
- 10SpringMvc_springmvc快速入门小案例(注解版本)
第一步:新建案例工程:
- python学习三
输入与输出 print()在括号中加上字符串,就可以向屏幕上输出指定的文字. >>>print('hello world')hello world print()函数也可以接受多个字 ...
- python package 的两种组织方式
方式一/package1/ .../__init__.py # 空文件 .../class1.py class Class1: def __init__(self): self.name = &quo ...
- Android 动画之TranslateAnimation应用详解
TranslateAnimation比较常用,比如QQ,网易新闻菜单条的动画,就可以用TranslateAnimation实现, 通过TranslateAnimation(float fromXDel ...
- Android Edittext点击全选输入框内容
- Navicat for mysql 显示中文乱码问题
使用navicat for mysql 打开数据库时,使用Console插入和查询数据显示乱码 处理过程 1.查看数据库编码为" utf8 -- UTF-8 Unicode",也就 ...