0%

你从未珍惜眼前,你活该失去所有。

php各参数配置详解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
--prefix=/usr/local/php                      //指定 php 安装目录 
--with-apxs2=/usr/local/apache/bin/apxs //整合apache,
//apxs功能是使用mod_so中的LoadModule指令,
//加载指定模块到 apache,要求 apache 要打开SO模块
--with-config-file-path=/usr/local/php/etc //指定php.ini位置
--with-MySQL=/usr/local/mysql //mysql安装目录,对mysql的支持
--with-mysqli=/usr/local/mysql/bin/mysql_config
//mysqli扩展技术不仅可以调用MySQL的存储过程、处理MySQL事务,
//而且还可以使访问数据库工作变得更加稳定。
--enable-safe-mode //打开安全模式
--enable-ftp //打开ftp的支持
--enable-zip //打开对zip的支持

--with-bz2 //打开对bz2文件的支持
--with-jpeg-dir //打开对jpeg图片的支持
--with-png-dir //打开对png图片的支持
--with-freetype-dir //打开对freetype字体库的支持
--without-iconv //关闭iconv函数,各种字符集间的转换
--with-libXML-dir //打开libxml2库的支持
--with-XMLrpc //打开xml-rpc的c语言
--with-zlib-dir //打开zlib库的支持
--with-gd //打开gd库的支持
--enable-gd-native-ttf //支持TrueType字符串函数库
--with-curl //打开curl浏览工具的支持
--with-curlwrappers //运用curl工具打开url流
--with-ttf //打开freetype1.*的支持,可以不加了
--with-xsl //打开XSLT 文件支持,扩展了libXML2库 ,需要libxslt软件
--with-gettext //打开gnu 的gettext 支持,编码库用到
--with-pear //打开pear命令的支持,PHP扩展用的
--enable-calendar //打开日历扩展功能
--enable-mbstring //多字节,字符串的支持
--enable-bcmath //打开图片大小调整,用到zabbix监控的时候用到了这个模块
--enable-sockets //打开 sockets 支持
--enable-exif //图片的元数据支持
--enable-magic-quotes //魔术引用的支持
--disable-rpath //关闭额外的运行库文件
--disable-debug //关闭调试模式
--with-mime-magic=/usr/share/file/magic.mime //魔术头文件位置

CGI方式安装才用的参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
--enable-fpm                 //打上PHP-fpm 补丁后才有这个参数,CGI方式安装的启动程序
--enable-fastCGI //支持fastcgi方式启动PHP
--enable-force-CGI-redirect //重定向方式启动PHP
--with-ncurses //支持ncurses 屏幕绘制以及基于文本终端的图形互动功能的动态库
--enable-pcntl //freeTDS需要用到的,可能是链接mssql 才用到
--with-mcrypt //mcrypt算法的扩展
--with-mhash //mhash算法的扩展

//以上函数库需要安装

--with-gmp //应该是支持一种规范
--enable-inline-optimization //优化线程
--with-openssl //openssl的支持,加密传输时用到的
--enable-dbase //建立DBA 作为共享模块
--with-pcre-dir=/usr/local/bin/pcre-config //perl的正则库案安装位置
--disable-dmalloc
--with-gdbm //dba的gdbm支持
--enable-sigchild
--enable-sysvsem
--enable-sysvshm
--enable-zend-multibyte //支持zend的多字节
--enable-mbregex
--enable-wddx
--enable-shmop
--enable-soap

注意事项

指定了–with-apxs2=/usr/local/apache/bin/apxs以后,就不要再激活–enable-fpm和–enable-fastCGI,apxs是以php module的模式加载PHP的。

http://www.jianshu.com/p/0a79847c8151

我想我还是不习惯,从默默无闻到有人喜欢!

短路作用

1
2
$a = false || $b = 5;
echo $b;

当 || 前面的值为 false 时, || 后的表达式才会被执行, 此时结果为5;

1
2
3
$a = true || $b = 5;
echo $b;

当 || 前面的值为 true 时, || 后的表达式不会被执行, 此时结果就找不到 $b

1
2
3

$b = false && $a = 1;
echo $a;

当 && 前面的值为false 时, 后面的表达式不会被执行

1
2
$b = true && $a = 1;
echo $a;

只有当 && 前面的值为true 时, 后面的表达式才会被执行

位运算

左移 <<

左移运算的实质是将对应的数据的二进制值逐位左移若干位,并在空出的位置上填0,最高位溢出并舍弃。
左移一位, 就实现了乘2运算

1
2
3
4
echo 40 << 1;
//结果是 80
echo 40 << 2;
//结果是160

右移 >>

可以实现 除 2 运算

1
2
3
4
5
6
echo 40 >> 1;
//结果是 20
echo 40 >> 2;
//结果是 10
echo 9 >> 1;
//结果是4

只是我回首来时路的每一步都走的好孤独。
Profiling只是针对单个session的,如果session结束,profiling信息将丢失,可以在 `INFORMATION_SCHEMA`中的`profiling`表中获取profiling信息. ### 查看profiling系统变量
1
2
3
4
5
6
7
8
mysql> show variables like '%profil%';  
+------------------------+-------+
| Variable_name | Value |
+------------------------+-------+
| have_profiling | YES | #只读变量,用于控制是否由系统变量开启或禁用profiling;
| profiling | OFF | #开启或关闭SQL语句剖析功能;
| profiling_history_size | 15 | #设置保留profiling的数目,缺省为15,范围为0100,为0时将禁用profiling;
+------------------------+-------+
### 查看是否开启
1
SELECT @@profiling;
### 设置开启
1
SET profiling = 1;
### 查看
1
show profiles;
### 查看具体的某一条sql
1
show profile all for query 18 ;
### 查看cpu信息
1
show profile cpu for query 18 ;
### 查看内存
1
show profile memory for query 18 ;
> http://www.ywnds.com/?p=8677

普通玩家选择标准配置,高级玩家选择自定义配置
Linux是一个多用户多任务的操作系统,可以在Linux中为不同的用户设置不同的运行环境,具体做法是设置不同用户的环境变量。 ### Linux环境变量分类

按照生命周期来分

1、永久的:需要用户修改相关的配置文件,变量永久生效。
2、临时的:用户利用export命令,在当前终端下声明环境变量,关闭Shell终端失效。

按照作用域来分

1、系统环境变量:系统环境变量对该系统中所有用户都有效。
2、用户环境变量:顾名思义,这种类型的环境变量只对特定的用户有效。

Linux设置环境变量的方法

在/etc/profile文件中添加变量 对所有用户生效(永久的)

用vim在文件/etc/profile文件中增加变量,该变量将会对Linux下所有用户有效,并且是“永久的”。
例如:编辑/etc/profile文件,添加CLASSPATH变量

1
2
vim /etc/profile    
export CLASSPATH=./JAVA_HOME/lib;$JAVA_HOME/jre/lib

注:修改文件后要想马上生效还要运行source /etc/profile不然只能在下次重进此用户时生效。

在用户目录下的.bash_profile文件中增加变量 【对单一用户生效(永久的)】

用vim ~/.bash_profile文件中增加变量,改变量仅会对当前用户有效,并且是“永久的”。

1
2
vim ~/.bash.profile
export CLASSPATH=./JAVA_HOME/lib;$JAVA_HOME/jre/lib

注:修改文件后要想马上生效还要运行$ source ~/.bash_profile不然只能在下次重进此用户时生效。

直接运行export命令定义变量 【只对当前shell(BASH)有效(临时的)】

在shell的命令行下直接使用export 变量名=变量值
定义变量,该变量只在当前的shell(BASH)或其子shell(BASH)下是有效的,shell关闭了,变量也就失效了,再打开新shell时就没有这个变量,需要使用的话还需要重新定义。

http://www.jianshu.com/p/ac2bc0ad3d74

我临睡前想做件大事改变世界激动得睡不着第二天早上连早起都做不到

主从复制的原理

分为同步复制和异步复制,实际复制架构中大部分为异步复制。 复制的基本过程如下:
1).Slave上面的IO进程连接上Master,并请求从指定日志文件的指定位置(或者从最开始的日志)之后的日志内容;
2).Master接收到来自Slave的IO进程的请求后,通过负责复制的IO进程根据请求信息读取制定日志指定位置之后的日志信息,返回给Slave
的IO进程。返回信息中除了日志所包含的信息之外,还包括本次返回的信息已经到Master端的bin-log文件的名称以及bin-log的位置;
3).Slave的IO进程接收到信息后,将接收到的日志内容依次添加到Slave端的relay-log文件的最末端,并将读取到的Master端的
bin-log的文件名和位置记录到master-info文件中,以便在下一次读取的时候能够清楚的告诉Master“我需要从某个bin-log的哪个位置开始往后的日志内容,请发给我”;
4).Slave的Sql进程检测到relay-log中新增加了内容后,会马上解析relay-log的内容成为在Master端真实执行时候的那些可执行的内容,并在自身执行。

环境描述

  • OS:CentOS
  • 主服务器master:192.168.11.120
  • 从服务器slave:192.168.11.139

mysql主服务器配置(master)

master服务器配置:

1
vim /etc/my.cnf
1
2
3
4
5
[mysqld]
server-id=120
log-bin=/var/lib/mysql/mysql-bin # 启用二进制日志
binlog-do-db=jasontest #指定数据库,如果不指定就是全部数据库
#binlog-ignore-db = mysql,information_schema #忽略写入binlog的库

重启服务器:

1
service mysqld  restart #systemctl restart mysqld.service --- centos7.x重启mysql

在主服务器上建立帐户并授权slave:
创建slave帐号,密码123456

1
mysql> GRANT REPLICATION SLAVE ON *.* to 'slave'@'192.168.11.%' identified by '123456' WITH GRANT OPTION;

更新数据库权限

1
mysql>flush privileges;

查询master的状态:

1
mysql> show master status;

显示结果:

1
slave status

注:执行完这个步骤后不要再操作主数据库了,防止主数据库状态值变化

mysql从服务器配置(slave)

slave服务器配置:

1
vim /etc/my.cnf
1
2
3
4
[mysqld]
server-id=139
log-bin=/var/lib/mysql/mysql-bin # 启用二进制日志
binlog-do-db=jasontest #指定数据库,如果不指定就是全部数据库

重启服务器:

1
service mysqld  restart #systemctl restart mysqld.service --- centos7.x重启mysql

设置同步源:

1
2
3
4
5
mysql> CHANGE MASTER TO MASTER_HOST='192.168.11.120', #主服务器master的ip
MASTER_USER='slave',
MASTER_PASSWORD='123456',
MASTER_LOG_FILE='mysql-bin.000022', #对应show master status中File
MASTER_LOG_POS=245; #对应show master status中Position

启用同步:

1
mysql>start slave

停止同步:

1
mysql>stop slave

检查从服务器状态:

1
mysql> SHOW SLAVE STATUS\G;

注意:Slave_IO_RunningSlave_SQL_Running进程必须正常运行,即YES状态,否则说明同步失败

下面介绍几个比较关键的参数,全面的说明可阅读参考手册。

Slave_IO_Running: IO线程是否正常运行
Slave_SQL_Running: SQL线程是否正常运行
Master_Log_File: IO线程正在读取的主服务器日志文件
Read_Master_Log_Pos: IO线程正在读取的主服务器日志文件的位置
Relay_Log_File: SQL线程正在读取和执行的本地日志文件
Relay_Log_Pos: SQL线程正在读取和执行的本地日志文件的位置
Relay_Master_Log_File: SQL线程正在重演的事件所在的主服务器日志文件
Exec_Master_Log_Pos: SQL线程正在重演的事件在主服务器日志文件中的位置
Seconds_Behind_Master:如果网络没有明显的延迟,该参数标志着SQL线程的事件重演速度。如果该值较大且不断递增,调整innodb_flush_log_at_trx_commit会有比较明显的效果,但是可能会在MySQL进程崩溃时丢失数据。
mysql数据库同步验证

主从数据库设置工作已经完成,可以在master新建数据库和表,插入和修改数据,查看slave是否获得同步,测试一下是否成功。

https://jasonhzy.github.io/2016/02/05/master-slave/

这个妹妹我曾见过的。
不是我自身的,却是我需要的,都是我所依赖的。一切需要外部提供的,都是需要进行依赖注入的。

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
/*
*
* 汽车 需要 run, 就必须需要 轮胎 roll
*
*/
class Luntai
{
public function roll()
{
echo "轮胎滚";
}
}

class Car
{
public function run()
{
$luntai = new Luntai();
$luntai->roll();
echo "汽车跑起来了";
}
}

这种 在一个类里实例化另外一个类,耦合程度太高,改写:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?php

/*
*
* 汽车 需要 run, 就必须需要 轮胎 roll
*
*/
class Luntai
{
public function roll()
{
echo "轮胎滚";
}
}

class Car
{
public $luntai;
// 在这里将 实例化后的 轮胎 类传递进来
public function __construct($luntai)
{
$this->luntai = $luntai;
}
public function run()
{
$this->luntai->roll();
echo "汽车跑起来了";
}

}
(new Car(new Luntai()))->run();

控制反转和依赖注入的关系

有时候我们会把控制反转和依赖注入等同,但实际上它们有着本质上的不同。
控制反转是一种思想
依赖注入是一种设计模式
IoC框架使用依赖注入作为实现控制反转的方式,但是控制反转还有其他的实现方式,所以不能将控制反转和依赖注入等同。

是谁来自山川湖海,却囿于昼夜、厨房与爱。
### 举个例子 如果你使用过PHP的框架,你应该使用过此类代码: 如在laravel框架中:
1
DB::table('xx')->select('xxxx')->where('xxxx','=','xx')->orderBy('xx','desc')->get();
在CI(codeigniter)框架中:
1
$res =$this->db->from('blogs')->select('*')->join('comments', 'comments.id = blogs.id')->get();
### 创建链式方法 如果我们有这么一个类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
class test
{
public $var = array();

public function setName($name)
{

$this->var['name'] = $name;
}

public function setYear($year)
{
$this->var['year'] = $year;
}

public function getVar()
{

return $this->var;
}
}

$test = new test();
那么只需要在相应的方法后添加 return $this,就可以了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
class test
{
public $var = array();

public function setName($name)
{
$this->var['name'] = $name;
return $this;
}

public function setYear($year)
{
$this->var['year'] = $year;
return $this;
}

public function getVar()
{
return $this->var;
}
}
调用时:
1
2
$test = new test();
var_dump($test->setName('fc')->setYear('23')->getVar());
这种技术虽然不会让你的PHP代码在本质上发生变化(如性能),但可使你的代码看起来更整洁,并且更容易维护。

静态方法(static)如何处理

要让静态方法也能使用链式调用,只需要加入 return new self

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class test2
{
public static $var = array();
public static function setName($name)
{
self::$var['name'] = $name;
return new self;
}

public static function getVar()
{
return self::$var;
}
}

http://fc-lamp.blog.163.com/blog/static/1745666872013106111248929/

醉后不知天在水,满船清梦压星河

PHP是单继承的语言,在PHP 5.4 Traits出现之前,PHP的类无法同时从两个基类继承属性或方法。php的Traits和Go语言的组合功能类似,通过在类中使用use关键字声明要组合的Trait名称,而具体某个Trait的声明使用trait关键词,Trait不能直接实例化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
trait Drive {
public $carName = 'trait';
public function driving() {
echo "driving {$this->carName}\n";
}
}
class Person {
public function eat() {
echo "eat\n";
}
}
class Student extends Person {
use Drive;
public function study() {
echo "study\n";
}
}
$student = new Student();
$student->study();
$student->eat();
$student->driving();

输出结果:
study
eat
driving trait
上面的例子中,Student类通过继承Person,有了eat方法,通过组合Drive,有了driving方法和属性carName。

如果Trait、基类和本类中都存在某个同名的属性或者方法,最终会保留哪一个呢?通过下面的代码测试一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php 
trait Drive {
public function hello() {
echo "hello drive\n";
}
public function driving() {
echo "driving from drive\n";
}
}
class Person {
public function hello() {
echo "hello person\n";
}
public function driving() {
echo "driving from person\n";
}
}
class Student extends Person {
use Drive;
public function hello() {
echo "hello student\n";
}
}
$student = new Student();
$student->hello();
$student->driving()

输出结果如下:

hello student
driving from drive

因此得出结论:当方法或属性同名时,当前类中的方法会覆盖 trait的 方法,而 trait 的方法又覆盖了基类中的方法。

如果要组合多个Trait,通过逗号分隔 Trait名称:

1
use Trait1, Trait2;

如果多个Trait中包含同名方法或者属性时,会怎样呢?答案是当组合的多个Trait包含同名属性或者方法时,需要明确声明解决冲突,否则会产生一个致命错误。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
trait Trait1 {
public function hello() {
echo "Trait1::hello\n";
}
public function hi() {
echo "Trait1::hi\n";
}
}
trait Trait2 {
public function hello() {
echo "Trait2::hello\n";
}
public function hi() {
echo "Trait2::hi\n";
}
}
class Class1 {
use Trait1, Trait2;
}

结果:

PHP Fatal error: Trait method hello has not been applied, because there are collisions with other trait methods on Class1 in ~/php54/trait_3.php on line 20

使用insteadof和as操作符来解决冲突,insteadof是使用某个方法替代另一个,而as是给方法取一个别名,具体用法请看代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?php
trait Trait1 {
public function hello() {
echo "Trait1::hello\n";
}
public function hi() {
echo "Trait1::hi\n";
}
}
trait Trait2 {
public function hello() {
echo "Trait2::hello\n";
}
public function hi() {
echo "Trait2::hi\n";
}
}
class Class1 {
use Trait1, Trait2 {
Trait2::hello insteadof Trait1;
Trait1::hi insteadof Trait2;
}
}
class Class2 {
use Trait1, Trait2 {
Trait2::hello insteadof Trait1;
Trait1::hi insteadof Trait2;
Trait2::hi as hei;
Trait1::hello as hehe;
}
}
$Obj1 = new Class1();
$Obj1->hello();
$Obj1->hi();
echo "\n";
$Obj2 = new Class2();
$Obj2->hello();
$Obj2->hi();
$Obj2->hei();
$Obj2->hehe();

输出结果如下:

Trait2::hello
Trait1::hi

Trait2::hello
Trait1::hi
Trait2::hi
Trait1::hello

as关键词还有另外一个用途,那就是修改方法的访问控制:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
trait Hello {
public function hello() {
echo "hello,trait\n";
}
}
class Class1 {
use Hello {
hello as protected;
}
}
class Class2 {
use Hello {
Hello::hello as private hi;
}
}
$Obj1 = new Class1();
$Obj1->hello(); # 报致命错误,因为hello方法被修改成受保护的
$Obj2 = new Class2();
$Obj2->hello(); # 原来的hello方法仍然是公共的
$Obj2->hi(); # 报致命错误,因为别名hi方法被修改成私有的

Trait 也能组合Trait,Trait中支持抽象方法、静态属性及静态方法,测试代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php
trait Hello {
public function sayHello() {
echo "Hello\n";
}
}
trait World {
use Hello;
public function sayWorld() {
echo "World\n";
}
abstract public function getWorld();
public function inc() {
static $c = 0;
$c = $c + 1;
echo "$c\n";
}
public static function doSomething() {
echo "Doing something\n";
}
}
class HelloWorld {
use World;
public function getWorld() {
return 'get World';
}
}
$Obj = new HelloWorld();
$Obj->sayHello();
$Obj->sayWorld();
echo $Obj->getWorld() . "\n";
HelloWorld::doSomething();\
$Obj->inc();
$Obj->inc();

输出结果如下:

Hello
World
get World
Doing something
1
2

http://tabalt.net/blog/php-traits/
https://stackoverflow.com/questions/47269922/php-traits-how-to-circumvenient-constructors-or-force-them-to-be-called

中年以后的男人,时常会觉得孤独,因为他一睁开眼睛,周围都是要依靠他的人,却没有他可以依靠的人
### 创建命令 运行命令行创建命令
1
php artisan make:console MultithreadingRequest --command=test:multithreading-request
### 注册命令 编辑 app/Console/Kernel.php,在 $commands 数组中增加:
1
Commands\MultithreadingRequest::class,
### 测试命令 修改 app/Console/Commands/MultithreadingRequest.php 文件,在 handle 方法中增加:
1
$this->info('hello');

安装 Guzzle

1
composer require guzzlehttp/guzzle "6.2"

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
<?php namespace App\Console\Commands;

use GuzzleHttp\Client;
use GuzzleHttp\Pool;
use GuzzleHttp\Psr7\Request;
use GuzzleHttp\Exception\ClientException;
use Illuminate\Console\Command;

class MultithreadingRequest extends Command
{
private $totalPageCount;
private $counter = 1;
private $concurrency = 7; // 同时并发抓取

private $users = ['CycloneAxe', 'appleboy', 'Aufree', 'lifesign',
'overtrue', 'zhengjinghua', 'NauxLiu'];

protected $signature = 'test:multithreading-request';
protected $description = 'Command description';

public function __construct()
{
parent::__construct();
}

public function handle()
{
$this->totalPageCount = count($this->users);

$client = new Client();

$requests = function ($total) use ($client) {
foreach ($this->users as $key => $user) {

$uri = 'https://api.github.com/users/' . $user;
yield function() use ($client, $uri) {
return $client->getAsync($uri);
};
}
};

$pool = new Pool($client, $requests($this->totalPageCount), [
'concurrency' => $this->concurrency,
'fulfilled' => function ($response, $index){

$res = json_decode($response->getBody()->getContents());

$this->info("请求第 $index 个请求,用户 " . $this->users[$index] . " 的 Github ID 为:" .$res->id);

$this->countedAndCheckEnded();
},
'rejected' => function ($reason, $index){
$this->error("rejected" );
$this->error("rejected reason: " . $reason );
$this->countedAndCheckEnded();
},
]);

// 开始发送请求
$promise = $pool->promise();
$promise->wait();
}

public function countedAndCheckEnded()
{
if ($this->counter < $this->totalPageCount){
$this->counter++;
return;
}
$this->info("请求结束!");
}
}

https://laravel-china.org/topics/2130/laravel-under-the-use-of-guzzle-to-prepare-multi-threaded-crawler-combat

某天,你无端想起一个人,她曾让你对明天有所期许,但是却完全没有出现在你的明天里。
缓冲(buffer)是为了协调吞吐速度相差很大的设备之间数据传送而采用的技术,用来存放缓冲数据的区域叫缓冲区,在计算机科学领域,当数据从一个地方传送到另一个地方时,缓冲区被用来临时存储数据。与缓冲相似的一个技术是缓存(cache),它们都是为了解决数据存储和传输速度不同而带来的问题,不同的是,缓冲主要在写时使用,而缓存主要用来在读时使用。

PHP在执行的过程中,嵌入的HTML代码,’echo’,’print_r’等指令都是一次数据输出,正是因为有缓冲区的存在,系统可以在php执行完之后再一次把数据发送给浏览器,运行如下代码:

1
2
3
4
5
6
7
<?php
echo "这里是第一行数据";
echo "这里是第二行数据,下面睡眠5秒";
sleep(5);
echo "这里是第三行数据,下面是HTML代码";
?>
<h1>标题</h1>

发现浏览器是同时显示所有内容,而不是先显示第一行和第二行数据,等待5秒后再显示后面的数据。不仅这样,PHP的缓冲区还提供给我们更加强大的功能,我们可以在数据发送之前对其作出捕获,更改等。PHP提供给我们”ob_”系列函数,例如如下代码,可以对某些字符进行替换:

1
2
3
4
5
6
7
<?php
ob_start();
echo "Hello world, this is http://www.hitoy.org/";
$content = ob_get_contents();
ob_end_clean();
echo str_replace("http://","https://",$content);
?>

上面中的ob_start,ob_get_contents,ob_end_clean分别用来开启用户缓冲区,获取缓存内容和关闭缓存区.

https://www.hitoy.org/php-output-buffer.html