PHP ob_start()用途

PHP网站上的一条comment,写的非常的好:

These are two usages of ob_start():

1-Well, you have more control over the output. Trivial example: 
say you want to show the user an error message, but the script has 
already sent some HTML to the browser. It'll look ugly, with a 
half-rendered page and then an error message. Using the output buffering 
functions, you can simply delete the buffer and sebuffer and send only 
the error message, which means it looks all nice and neat buffer and send
2-The reason output buffering was invented was to create a seamless 
transfer, from: php engine -> apache -> operating system -> web user

If you make sure each of those use the same buffer size, the system 
will use less writes, use less system resources and be able
 to handle more traffic.

 

Matomo安装完成后的注意步骤

Matomo的前身是Piwik, 按照官网的步骤安装好以后需要优化下面几点:

  1. auto archiving

详细的内容需要参见这里:

How to Set up Auto-Archiving of Your Reports

但是如果你使用的是军哥的LNMP的话,如果你的domain 是example,可以这么写crontab:

5 * * * * /usr/bin/php /home/wwwroot/example.com/console core:archive –url=https://example.com > /home/wwwlogs/matomo-archive.log

2. 强制使用SSL, 在config/config.ini.php 的General 下面添加 force_ssl = 1

3. maxmind 的免费数据库,目前需要注册一个才能开始使用

 

 

最后,测试失败。Matomo的统计能力太差,一天超过百万的PV就撑不住了。。。

 

放弃!

PHP7 兼容性检测

PHP 7 都出到7.4 了,是时候把手中的discuz论坛升级到PHP 7了,考虑了半天兼容性的问题,准备升级到php 7.3

discuz 的主程序已经升级到最新的discuz 20191201版本了,兼容PHP 7.3应该是没有问题,剩下的就是安装的那些插件的兼容性的问题.

检测PHP7 的兼容性,我们这里使用主流的PHPCompatibility 配合PHP Code_Sniffer

https://github.com/squizlabs/PHP_CodeSniffer
https://github.com/PHPCompatibility/PHPCompatibility

PHPCompatibility 是PHP Code_Sniffer 的插件,因此我们应该先安装PHP Code_Sniffer, 在github上有很多中的安装方式,这里我们选择最近的wget 或者curl下载二进制程序,然后把二进制程序放到全局去

# Download using curl
curl -OL https://squizlabs.github.io/PHP_CodeSniffer/phpcs.phar
curl -OL https://squizlabs.github.io/PHP_CodeSniffer/phpcbf.phar

# Or download using wget
wget https://squizlabs.github.io/PHP_CodeSniffer/phpcs.phar
wget https://squizlabs.github.io/PHP_CodeSniffer/phpcbf.phar

# register as global commands
mv phpcs.phar phpcs
mv phpcbf.phar phpcbf
chmod 755 phpcs
chmod 755 phpcbf
mv phpcs /usr/local/bin/
mv phpcbf /usr/local/bin/

这样就安装完了phpcs,下一步我们需要下载PHPCompatibility这个插件,并且让phpcs使用这个插件

# Download PHPCompability
cd ~
wget https://github.com/PHPCompatibility/PHPCompatibility/archive/9.3.5.zip
unzip 9.3.5.zip
# path is /root/PHPCompability9.3.5
# config phpcs to use PHPCompatibility
phpcs --config-set installed_paths /root/PHPCompability9.3.5

这样phpcs就可以使用PHPCompatibility9.3.5了,当然了也可以使用git的形式来下载,这样更新PHPCompatibility比较方便

加入说我们需要检查的文件folder 是/home/plugin, 那么我们就可以用

phpcs -p --standard=PHPCompatibility --runtime-set testVersion 7.3 --report-full=/home/php.log /home/plugin

-p: 打印progress到console上面

–standard: 表示使用哪个标准

–runtime-set testVersion 7.3 : 表示用PHP7.3的标准来检查

–report-full: 表示将结果输出到某一文件

 

检查完毕,删掉了不兼容php7.3 的插件,然后就开始准备升级discuz到7.3了

PHP SimpleXMLElement 对象

今天在用RedbeanPHP 写数据库接口的时候,发现从SimpleXMLElement对象里面出来的值,按理说都是string, 怎么也不能赋值给RedbeanPHP, 用var_dump看了一下,发现SimpleXMLElement对象比较有意思,里面嵌套的对象以及property 的type 都是object,而且都是SimpleXMLElement 对象,在google上搜了一下发现问这个问题的不少。

https://stackoverflow.com/questions/416548/forcing-a-simplexml-object-to-a-string-regardless-of-context

比如说XML是这样的:

<channel>
<item>
<title>This is title 1</title>
</item>
</channel>

下面这样确实能够输出string:

$xml = simplexml_load_string($xmlstring);
echo $xml->channel->item->title;

但是除了echo 以外,下面这样就不能被当成string了

$foo = array( $xml->channel->item->title );

这是因为$XML->channel->item->title 的type 其实仍然为SimpleXMLElement的对象

我们可以用typecast来解决这个问题:

$foo = array( (string) $xml->channel->item->title );

The above code internally calls __toString() on the SimpleXMLObject. This method is not publicly available, as it interferes with the mapping scheme of the SimpleXMLObject, but it can still be invoked in the above manner.

另外看到有人这么写也可以:

$foo = array( $xml->channel->item->title.'' );

通过gettype查看确实变成了string,具体原理不知道

nginx 和 cgi, fcgi 以及php-cgi, php-fpm

在apache 称雄的时代,经常会看到cgi,但是随着nginx 的出现以及时代的进步, cgi 的程序越来越少了.

最近有需求安装smokeping,因此cgi 又被拿了出来

CGI是common gateway interface的缩写,大家都译作通用网关接口,但很不幸,我们无法见名知意。

我们知道,web服务器所处理的内容都是静态的,要想处理动态内容,需要依赖于web应用程序,如php、jsp、python、perl等。但是web server如何将动态的请求传递给这些应用程序?它所依赖的就是cgi协议。没错,是协议,也就是web server和web应用程序交流时的规范。换句话说,通过cgi协议,再结合已搭建好的web应用程序,就可以让web server也能”处理”动态请求(或者说,当用户访问某个特定资源时,可以触发执行某个web应用程序来实现特定功能),你肯定知道处理两字为什么要加上双引号。CGI可以是任何的可执行程序,可以是Shell脚本,二进制应用,或者其他的脚本(Python脚本,Ruby脚本等)

简单的cgi工作方式如下:

有多种方式可以执行cgi程序,但对http的请求方法来说,只有get和post两种方法允许执行cgi脚本。实际上post方法的内部本质还是get方法,只不过在发送http请求时,get和post方法对url中的参数处理方式不一样而已。

任何一种语言都能编写CGI,只不过有些语言比较擅长,有些语言则非常繁琐,例如用bash shell开发,那么需要用echo等打印语句将执行结果放在巨多无比的html的标签中输出给客户端。常用于编写CGI的语言有perl、php、python等,java也一样能写,但java的servlet完全能实现CGI的功能,且更优化、更利于开发

总体上来说,CGI(common gateway interface) 就是所谓的短生存应用程序,Fast CGI 就是所谓的长生存应用程序. FastCGI 像是一个常驻 long-live 型的CGI, 它可以一直执行者,不会每次都要话费时间去fork一次

CGI 和 fastcgi 有自己输入和输出标准,比如HTTP头部, CGI环境变量,get和post等等

CGI, Fast-CGI 是protocols, CGI 慢点, Fast-CGI 要快很多

CGI程序能够用 Python, PERL, Shell, C or C++等语言来实现,尽管没有明确的规定,但是一般用C写的cgi,我们会用.cgi作为后缀,用perl 的用.pl作为后缀,其实我们都可以用.cgi作为后缀. Perl由于其跨操作系统、易于修改的特性成为了CGI的主流编写语言,以至于一般的“cgi程序”就是Perl程序

nginx + fastcgi: nginx只能处理静态文件,对于动态文件,一般用fastcgi 来作为“沟通”的协议. fastcgi 进程由fastcgi 进程管理器管理,而不是nginx,这样就需要一个fastcgi 管理器,这里可以使用spawn-fcgi 作为fastcgi 的进程管理器

nginx + cgi: nginx 不能直接执行外部可执行程序,因此nginx天生不支持cgi的, nginx 虽然不支持cgi,但是他“支持”fastCGI, 这样我们可以fastcgi 来wrap 一下cgi,这样变相的支持cgi,常见的fastcgi wrapper 有fcgiwrap

另外其实cgi 程序也可以被当成fastCGI,因此也可以用nginx + spawn-fcgi 来执行cgi

Spawn-FCGI是一个通用的FastCGI管理服务器,它是lighttpd中的一部份,很多人都用Lighttpd的Spawn-FCGI进行FastCGI模式下的管理工作,不过有不少缺点。而PHP-FPM的出现多少缓解了一些问题

fastcgi 是一个协议, php-fpm 实现了这个协议

通过webserver 来运行php, 一般有两种方式,一个是php-cgi, 另外一个php-fpm (php FastCGI Process Manager) (apache 的mod_php, 把php当作一个模块来执行,以及cli 和 isapi 不在考虑范围之内, php总共来说有5种执行模式)

php-fpm 比传统的CGI方式 (suPHP) 要快,

php-cgi是php自带的fastcgi进程管理器,php-cgi变更php.ini配置后需重启php-cgi才能让新的php-ini生效,不可以平滑重启。另外直接杀死php-cgi进程,php就不能运行了,但是php-fpm和 spawn-fcgi就没有此类问题

php-fpm 就是一个支持php 解析的 fastcgi进程管理器,只能适用于php,其余语言写的cgi,例如perl,python,C,都不能使用

mod_php 和 php-fpm 是运行php 的两种方式,mod_php 是running php as apache module

在segmentfault上看到了一个文章,写的很不错https://segmentfault.com/q/1010000000256516

你(PHP)去和爱斯基摩人(web服务器,如 Apache、Nginx)谈生意

你说中文(PHP代码),他说爱斯基摩语(C代码),互相听不懂,怎么办?那就都把各自说的话转换成英语(FastCGI 协议)吧。

怎么转换呢?你就要使用一个翻译机(PHP-FPM)
(当然对方也有一个翻译机,那个是他自带的)

我们这个翻译机是最新型的,老式的那个(PHP-CGI)被淘汰了。不过它(PHP-FPM)只有年轻人(Linux系统)会用,老头子们(Windows系统)不会摆弄它,只好继续用老式的那个。

军哥LNMP 安装后一些基本的php 优化

军哥的LNMP 确实异常的稳定,但是一些安全措施做得太好了以至于好多程序不能好好运行,因此需要做一些基本的优化

php.ini 位于/usr/local/php/etc/php.ini, 你可以用php –ini 来查看ini 的具体位置

1) 编辑disable_functions, 去掉一些常用的函数,比如说scandir, chroot, exec, shell_exec 等等
2) 编辑memory_limit, 改为1024或者2048M 等等,根据你的实际情况而定
3) 编辑timezone, 可以改为America/New_York

Piwik 使用GeoIP 以及优化(一)

接上篇文章,开始给我的大部分网站使用piwik,但是使用piwik 首先需要的就是enable GeoIP

  1. GeoIP Module for Piwik

         Piwik 有四种方式来使用GeoIP, 分别是default, GeoIP(PHP), GeoIP(PECL), GeoIP(http or nginx)

        在高流量的网站,GeoIP PHP 就会显得速度慢很多,因此这里 GeoIP PECL 成为了piwik 的首选

      在piwik 的官方文档上有在ubuntu/debian 上安装pecl geoip 的办法,因此这里不再多说. 这篇文章主要说说如何安装GeoIP PECL 在RHEL系列的OS 上

      以CentOS为例,首先确保你的系统安装了PECL,如果没有的话就先google 一下安装PECL

     然后以root 执行下列命令

pecl install geoip

  然后有很大的可能性你会得到下面的error:

shtool at '/tmp/pear/temp/geoip/build/shtool' does not exist or is not executable.

  出现这个error 的原因在于/tmp 这个目录不允许执行可执行文件

  解决办法也很简单,就是更改pecl 的默认tmp 目录,比如改为/root/tmp

mkdir /root/tmp 
 pecl config-set temp_dir /root/tmp
 or
 pear config-set temp_dir /root/tmp

pecl config-set这个命令经常会出问题,因此建议使用pear config-set这个命令

更改完pecl 的tmp 默认目录以后,就可以顺利的执行pecl install geoip的命令了

安装完毕后,还剩下最后一件事: 配置php.ini, 添加geoip extension 和 目录

用你喜欢的编辑器,无论是是vi, vim 还是nano,编辑php.ini,添加如下代码:

[PHP]
 ;AFTER THE PHP SECTION NOT BEFORE
 extension=geoip.so

 

[gd] 
;AFTER THE gd SECTION NOT BEFORE 
geoip.custom_directory=/full/linux/path/to/piwik/misc

注意当使用pecl install geoip 的时候, extension=geoip.so 一般会自动添加到php.ini配置文件中,在这里你需要确定下