一、 Introduction
用户每次访问网站的时候,apache和php都需要执行,耗费服务器资源。如果有的网站内容比较稳定(比如,新闻信息页面),不会随便发生变化。那么,就给其制作一个静态页面。后续的访问,就直接访问静态页面即可,节省了apache、php等相关服务器资源的消耗。
把php执行生成好的内容制作为一个静态页面,这个过程就是php的静态化。大量应用于新闻信息页面。
使用静态化,可以节省php、apache等服务器资源,节省用户等待时间,访问速度快。搜索引擎更喜欢收录静态页面。
二、 实现静态化
1. php代码实现静态化
比如,一个简单的php代码
<?php
//实现一个简单静态化过程
for($i=0; $i<10; $i++){
echo $i."<hr/>";
}
利用php把对应的静态内容从php缓冲区里给抓取出来,并制作静态内容。
<?php
//1,开启php缓冲区(ob,output_buffering)
ob_start();
//实现一个简单静态化过程
for($i=0; $i<10; $i++){
echo $i."<hr/>";
}
//2,抓取php缓冲区内容
$cont = ob_get_contents();
//3,利用抓取到的内容制作静态页面
file_put_contents('./01.html', $cont);
//4,删除缓冲区内容并关闭
ob_end_clean();
这个程序代码执行的时候,浏览器页面就没有输出内容,因为ob_end_clean已经把内容从缓冲区删除了。使用ob_end_flush();//关闭并刷新缓存区。刷新就是数据从php缓冲区中输出并提供给用户的过程。不使用flush(),内容会自然刷新出来。
<?php
//1,开启php缓冲区(ob,output_buffering)
ob_start();
//实现一个简单静态化过程
for($i=0; $i<10; $i++){
echo $i."<hr/>";
}
//2,抓取php缓冲区内容
$cont = ob_get_contents();
//3,利用抓取到的内容制作静态页面
file_put_contents('./01.html', $cont);
//4,删除缓冲区内容并关闭
//ob_end_clean();//关闭并清除缓存区
ob_end_fulsh();//关闭并刷新缓存
当没有调用flush相关函数时,每个php脚本会自动flush刷新。
<?php
//开启缓冲区
ob_start();
$time = date("Y-m-dH:m:s");
?>
<!DOCTYPE html>
<html lang="en">
<head>
<metacharset="UTF-8">
<title>Document</title>
</head>
<body>
<h2>php静态化</h2>
<h2>22222<?phpecho $time; ?></h2>
<?php
$cont =ob_get_contents();//ob_get_contents收集当前行往上的静态内容
file_put_contents('./02.html',$cont);
// ob_end_flush();
ob_end_clean();
?>
<p>3333今天该3</p>
<p>静态44444444444</p>
</body>
</html>
2. 相关缓冲函数
开启缓冲
ob_start()//开启缓冲区
php.ini中也可以设置开启,output_buffering = 4096//4096是因为设计者希望缓冲区最大内容是4k,现在实际上没有限制,4096就表示开启。关闭是off。
ob_get_level()//获得当前ob的层数
获取内容
ob_get_contents();//获取
ob_get_clean();//获取后清空缓冲区
ob_get_flush();//获取后刷新
清空
ob_clean()//删除缓冲区内容
ob_get_clean()//获取并删除缓冲区内容
ob_end_clean()//清空并关闭缓冲区
刷新
ob_flush()//数据向下推送
ob_get_flush()//获取内容并推送内容
ob_end_flush()//推送内容并关闭缓冲区
关闭
ob_end_clean()//清空关闭
ob_end_flush()//刷新关闭
三、 thinkphp项目对静态化的应用
1. 在项目后台添加商品的时候,就给商品的详情生成静态页面。
前台就直接访问商品的静态详情页面。
后台商品控制器中添加商品的方法
public functiontianjia(){
$goods = D('Goods');
//判断是展示还是收集信息
if (!empty($_POST)) {
// dump($_POST);
//处理上传的商品图片
if($_FILES['goods_pic']['error'] == 0) {
$cfg = array(
'rootPath'=> './uploads/',//保存根目录
);
$up = new\Think\Upload($cfg);
//uploadOne()会返回上传文件的存储在服务器的名字和路径等信息
$z = $up->uploadOne($_FILES['goods_pic']);
// dump($up ->getError());
//把上传的图片保存到数据表记录里面
$bigpathname =$up -> rootPath . $z['savepath'] . $z['savename'];
$_POST['goods_big_img'] = ltrim($bigpathname, './');
//给上传图片制作缩略图
$im = new\Think\Image();
$im -> open($bigpathname);//打开被处理的图片
$im ->thumb(125,125);//制作缩略图
//保存缩略图到服务器
$smallpathname =$up -> rootPath . $z['savepath'] . "small_" . $z['savename'];
$im ->save($smallpathname);//保存缩略图到服务器
//把制作好的缩略图保存到数据表记录
$_POST['goods_small_img'] = ltrim($smallpathname, './');
}
//exit;
$info = $goods->create();
$z = $goods ->add($info);
if ($z) {
//把添加好的商品顺便生成静态页面
//前台查看商品详情页面就直接查看静态页面就可以
ob_start();
//内容输出前台商品详情的模版页面
$info =D('Goods')->find($z);
$this->assign('info',$info);
$this ->display('Home@Goods:detail');//在后台展现前台模板页面
$cont =ob_get_contents();
//把$cont的内容制作成静态文件
file_put_contents("./product/goods_".$z.".html",$cont);
ob_end_clean();
//页面跳转
//$this->redirect(分组/控制器/操作方法,参数array,间隔时间,提示信息);
// $this ->redirect("showlist",array(), 2, '数据添加成功');
//如果设置参数,可以get方法传递,比如
$this ->redirect("showlist",array('name' => 'hah','age' => 12), 2, '数据添加成功');
} else {
$this ->redirect("tianjia",array(), 2, '数据添加失败');
}
} else {
$this ->display();
}
}
然后把前台访问商品的链接由动态改为静态地址。
href="{$smarty.const.SITE_URL}product/goods_{$v.goods_id}.html"
如果后期商品数据有修改,就根据修改后的信息,重新生成静态页面。
这样为了面向对象,可以给生成html静态页面,创建一个私有方法。
private functionmakeHtml($goods_id){
ob_start();
//内容输出前台商品详情的模版页面
$info =D('Goods')->find($goods_id);
$this->assign('info',$info);
$this ->display('Home@Goods:detail');//在后台展现前台模板页面
$cont =ob_get_contents();
//把$cont的内容制作成静态文件
file_put_contents("./product/goods_".$goods_id.".html",$cont);
ob_end_clean();
}
那么直接调用即可
public function upd($goods_id){
$goods = D('Goods');
//dump($goods_id);
// dump($height);
// dump($addr);
//find()方法获得数据表记录,每次通过一维数组返回一个记录结果
//$model对象->find();没有设置参数获得第一条结果
//$model对象->find(数字);获得主键为参数值的记录结果
// $info = D('Goods')-> select($goods_id);
// 两个业务逻辑,展示和收集
if (!empty($_POST)) {
$z = $goods->save($_POST);
//获得全部的商品信息,给前台页面制作新缓存,删除旧缓存
S(array('type'=>'memcache','host'=>"localhost",'port'=>11211));
$info =D("Goods")->order('goods_iddesc')->field("goods_name,goods_price,goods_small_img")->select();
//把获得的信息存储在memcache中
S("goods_category_info",$info,0);
//或者直接删除旧的缓存也可以
//S("goods_category_info",null);
if ($z) {
$this->makeHtml($goods_id);
//页面跳转
//$this->redirect(分组/控制器/操作方法,参数array,间隔时间,提示信息);
// $this ->redirect("showlist",array(), 2, '数据添加成功');
//如果设置参数,可以get方法传递,比如
$this ->redirect("showlist",array(), 2, '数据修改成功');
} else {
$this ->redirect("upd",array('goods_id' => $goods_id), 2, '数据修改失败');
}
} else {
$info = D('Goods')-> find($goods_id);
$this ->assign('info', $info);
$this ->display();
}
}
2. 通过ajax实现生成的静态页面的动态信息显示
一个静态页面的内容都是固定的,有时候局部数据是随时需要变化的,可以利用ajax随时感知变化的信息再显示。
<scriptsrc="{$smarty.const.JS_URL}jquery-1.4.4.js" ></script>
<scripttype="text/javascript">
// alert($);
//感知用户的登陆状态
var urlSite ="{$smarty.const.SITE_URL}index.php/Home/User/loginCheck";
$.ajax({
url:urlSite,
type:'get',
dataType:'html',
success:function(msg){
$('#userlogin_flag').html(msg);
}
});
</script>
四、 php缓冲区与session_start()和header()和setcookie()的关系
session_start()、header()和setcookie()等语句在使用的时候,前边不能有输出,否则报错。如果使用php的缓冲区,在session_start()等函数前开启缓冲区,将这些函数之前的数据存放在缓冲区中。这样这些数据就不会在session_start()等函数到达用户之前而先达到用户了。
<?php
ob_end_clean();
echo "abc";
session_start();
$_SESSION['sur'] = 'haha';
echo $_SESSION['sur'];
关于缓存和缓冲的区别,缓存是可以看得见的,例如缓存文件,数据较持久;缓冲是一个临时区域,其数据都是运行在内存中的,数据容易消失。
五、 伪静态
伪静态是相对真实静态来讲的,通常为了增强搜索引擎的友好面,都将文章内容生成为静态页面,但有的时候为了实时的显示一些信息,或者想使用脚本展示网站内容。为了在静态和实时展示、脚本展示间取得平衡,产生了伪静态技术。实际上就是展示以html一类的静态页面形式,但其实是用动态脚本语言来处理的。
伪静态的好处
对百度等搜索引擎的收录有好处;
用户体验非常好;
1. 配置伪静态
apache(iis tomcat nginx)可以配置使用伪静态。
在httpd.conf文件中开启伪静态重写模块支持,
LoadModulerewrite_module modules/mod_rewrite.so
在httpd-vhost.conf中
<VirtualHost *:80>
ServerName www.php2.com
DocumentRoot "d:/002php/test1 "
<Directory"D:/002php/test1>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
DirectoryIndex index.php
</Directory>
</VirtualHost>
添加AllowOverride All,这样就允许在test1下面的任何目录,设置伪静态。
然后重启apache。
2. 伪静态的使用
访问的路径为:http://www.php2.com/fakestatic/static.xml
真实指向的地址为:http://www.php2.com/fakestatic/static.php
在被操作的目录下创建一个伪静态规则文件,”.htaccess”
文件较特殊,需要DOS命令行中,echo a > .htaccess创建
在.htaccess内部编辑伪静态规则,
#开启伪静态开关,或者开启重写开关
RewriteEngine on
RewriteRule ^static\.xml$ static\.php
编写一个static.php
<?php
echo"weijingtaiweijing";
访问,http://www.php2.com/fakestatic/static.xml 执行的是static.php
3. 带参数的指向
访问的路径为:http://www.php2.com/fakestatic/static_12.html
真实指向的地址为:http://www.php2.com/fakestatic/static.php?id=12
在规则文件中配置
#开启伪静态开关,或者开启重写开关
RewriteEngine on
#static2_12.html ===> static2.php?id=12
#$1表示重复使用第一个括号内容
RewriteRule ^static_(\d+)\.html$ static2\.php?id=$1
编写static2.php
<?php
print_r($_GET);
访问的路径为:http://www.php2.com/fakestatic/static3_12_haha_shs.html
真实指向的地址为:http://www.php2.com/fakestatic/static3.php?id=12&name=haha&addr=shs
在规则文件中配置
RewriteRule ^static\.xml$ static\.php
#static2_12.html ===> static.php?id=12
#$1表示重复使用第一个括号内容
RewriteRule ^static2_(\d+)\.html$ static2\.php?id=$1
#static3.html ===> static3.php
RewriteRule ^static3_(\d+)_([a-z]+)_([a-z]+)\.html$static2\.php?id=$1&name=$2&addr=$3
编写static3.php
<?php
print_r($_GET);
4. 域名地址跳转
如果网站做升级,旧域名已经停止使用,但是老用户还习惯使用旧域名。需要将旧域名跳转到新域名。
访问的路径为:http://www.php1.com/fakestatic2/haha.php
真实指向的地址为:http://www.php2.com/fakestatic2/haha.php
访问php1域名的时候,自动跳转到php2的域名。
在旧域名和新域名的fakestatic2目录下,分别创建haha.php
<?php
echo "这是旧域名的";
<?php
echo "这是新域名的";
在旧域名的fakestatic2目录下,创建.htaccess,编写规则
#开启伪静态开关,或者开启重写开关
RewriteEngine on
#如果访问的主机域名地址是通过www.php1.com开始就要走规则
RewriteCond %{HTTP_HOST} ^www.php1.com
#(.*)代表www.php1.com访问时除了主机域名外的信息
RewriteRule ^(.*) http://www.php2.com/$1
5. 隐藏index.php入口文件
在index.php的同目录下,创建一个controller,里面创建haha.php。
index.php的内容
<?php
echo "yinchangindexphp";
print_r($_GET);
haha.php的内容
在index.php目录下创建.htaccess文件,编写规则
#开启伪静态开关,或者开启重写开关
RewriteEngine on
#访问的不是文件file也不是目录directory,就走规则
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
#(.*)代表请求的时候后续给传递的内容
#例如:http://www.php2.com/index/index.php/haha/hehe
#(.*)代表haha/hehe
RewriteRule ^(.*)$ index\.php/$1
6. 给tp框架隐藏入口文件
将上述设置的隐藏入口文件复制到tp框架的index.php同级目录下就可以。
7. tp框架的伪静态
php层面的伪静态。
表现一,路径结尾的.html,比如,http://www.php2.com/tp/shop/home/goods/showlist.html
表现二,路径中的pathinfo的路径模式,比如http://www.php2.com/tp/shop/home/goods/detail
表现三,路由设置伪静态
在配置文件中配置,config.php
/*tp项目路由层面的伪静态*/
'URL_ROUTER_ON' => true,
'URL_ROUTE_RULES'=>array(
//'news/:year/:month/:day' => array('News/archive', 'status-1'),
//http://网址/index.php/分组/news/2017/10/13
//真实地址:http://网址/index.php/分组/News/archive/status/1/year/2017/modth/12/day/13
//比如
'login/:year/:month'=> array('User/login','status=1'),
)