分类目录归档:php

FastCgi与PHP-fpm之间是个什么样的关系

首先,CGI是干嘛的?CGI是为了保证web server传递过来的数据是标准格式的,方便CGI程序的编写者。

web server(比如说nginx)只是内容的分发者。比如,如果请求/index.html,那么web server会去文件系统中找到这个文件,发送给浏览器,这里分发的是静态数据。好了,如果现在请求的是/index.php,根据配置文件,nginx知道这个不是静态文件,需要去找PHP解析器来处理,那么他会把这个请求简单处理后交给PHP解析器。Nginx会传哪些数据给PHP解析器呢?url要有吧,查询字符串也得有吧,POST数据也要有,HTTP header不能少吧,好的,CGI就是规定要传哪些数据、以什么样的格式传递给后方处理这个请求的协议。仔细想想,你在PHP代码中使用的用户从哪里来的。

当web server收到/index.php这个请求后,会启动对应的CGI程序,这里就是PHP的解析器。接下来PHP解析器会解析php.ini文件,初始化执行环境,然后处理请求,再以规定CGI规定的格式返回处理后的结果,退出进程。web server再把结果返回给浏览器。

好了,CGI是个协议,跟进程什么的没关系。那fastcgi又是什么呢?Fastcgi是用来提高CGI程序性能的。

提高性能,那么CGI程序的性能问题在哪呢?”PHP解析器会解析php.ini文件,初始化执行环境”,就是这里了。标准的CGI对每个请求都会执行这些步骤(不闲累啊!启动进程很累的说!),所以处理每个时间的时间会比较长。这明显不合理嘛!那么Fastcgi是怎么做的呢?首先,Fastcgi会先启一个master,解析配置文件,初始化执行环境,然后再启动多个worker。当请求过来时,master会传递给一个worker,然后立即可以接受下一个请求。这样就避免了重复的劳动,效率自然是高。而且当worker不够用时,master可以根据配置预先启动几个worker等着;当然空闲worker太多时,也会停掉一些,这样就提高了性能,也节约了资源。这就是fastcgi的对进程的管理。

那PHP-FPM又是什么呢?是一个实现了Fastcgi的程序,被PHP官方收了。

大家都知道,PHP的解释器是php-cgi。php-cgi只是个CGI程序,他自己本身只能解析请求,返回结果,不会进程管理(皇上,臣妾真的做不到啊!)所以就出现了一些能够调度php-cgi进程的程序,比如说由lighthttpd分离出来的spawn-fcgi。好了PHP-FPM也是这么个东东,在长时间的发展后,逐渐得到了大家的认可(要知道,前几年大家可是抱怨PHP-FPM稳定性太差的),也越来越流行。

网上有的说,fastcgi是一个协议,php-fpm实现了这个协议

对。

有的说,php-fpm是fastcgi进程的管理器,用来管理fastcgi进程的

对。php-fpm的管理对象是php-cgi。但不能说php-fpm是fastcgi进程的管理器,因为前面说了fastcgi是个协议,似乎没有这么个进程存在,就算存在php-fpm也管理不了他(至少目前是)。 有的说,php-fpm是php内核的一个补丁

以前是对的。因为最开始的时候php-fpm没有包含在PHP内核里面,要使用这个功能,需要找到与源码版本相同的php-fpm对内核打补丁,然后再编译。后来PHP内核集成了PHP-FPM之后就方便多了,使用--enalbe-fpm这个编译参数即可。

有的说,修改了php.ini配置文件后,没办法平滑重启,所以就诞生了php-fpm

是的,修改php.ini之后,php-cgi进程的确是没办法平滑重启的。php-fpm对此的处理机制是新的worker用新的配置,已经存在的worker处理完手上的活就可以歇着了,通过这种机制来平滑过度。

还有的说PHP-CGI是PHP自带的FastCGI管理器,那这样的话干吗又弄个php-fpm出

不对。php-cgi只是解释PHP脚本的程序而已。

原文引自

搞不清FastCgi与PHP-fpm之间是个什么样的关系

brew install php56

Dupes

brew tap homebrew/dupes

加入版本

brew tap homebrew/versions

加入PHP

brew tap homebrew/homebrew-php

列出php5.6的选项

brew options php56

好了,开始安装吧,go

brew install php56

在安装的时候,没有顺利的安装成功,碰到倒了如下错误。

 wrong number of arguments (3 for 0..2)

这个错误猜测可能是因为之前已经有安装过的PHP版本,后来把这个给删掉就好了。删除方法点击这里

安装完成之后,记得设置php的lib目录,否则在cli的模式下不能使用最新的。

Error: Failed to update tap: josegonzalez/php

最近很久没有更新brew了,刚才执行了一下

brew update

结果出现了如下错误:

Error: Failed to update tap: josegonzalez/php

错误原因是因为现在php的源发生了变更,所以这里出现了无法更新的问题。解决方案是可以把这个源给删掉。

brew untap josegonzalez/php

当然,删掉之后,需要增加新的源,看一下brew 升级 php56

 

imagecopyresized和imagecopyresampled的区别

imagecopyresized和imagecopyresampled都是拷贝部分图像并调整大小,但是这两个函数有一个很大的区别,就是imagecopyresized生成的图像不如imagecopyresampled清晰,但是imagecopyresized生成的速度要比imagecopyresampled快,图片要比imagecopyresampled小。

PHP实现下载文件

$fileName = "text.pdf";
$file = fopen ($fileName, "r" );
//输入文件标签
Header ("Content-type: application/octet-stream");
Header ("Accept-Ranges: bytes");
Header ("Accept-Length: " . filesize ($fileName));
Header ("Content-Disposition: attachment; filename=" . time() . ".pdf");
//输出文件内容
//读取文件内容并直接输出到浏览器
echo fread ($file, filesize ($fileName));
fclose ($file);

 

php curl 直接导致进程崩溃的问题

刚才在项目中,图片上传的地方,碰见了一个很奇葩的问题。项目的图片会通过curl上传到其它部门的接口。结果在上传的时候,直接导致进程都死了。。收到了如下的错误:8DFA5F21-FF5B-4034-8001-305C9D4EAF04

 

结果就在google上查了很久,无解。。。在apache上收到的错误,也仅仅有这么一句话:

[Thu May 21 16:35:48.050307 2015] [core:notice] [pid 7084] AH00052: child pid 7095 exit signal Segmentation fault (11)

不过发现在apache的errorlog上有这么一句话:

PHP Warning:  Module 'http' already loaded in Unknown on line 0

这个http的module是在项目中用的一个httpRequest的封装。。那么就试着在php.ini中将这个module暂时禁用,发现curl居然好用了。。难道是因为php在启动的时候,这个warning导致的curl不能用了?看来在php启动的时候,warning还是要解决掉。以免引起其它的问题。。。

PHP实现BF算法

BF算法(Brute Force)

从字符串主S中查找到字符串T的位置。每次一个字符串的对比,若相等,则继续查找后面的字符串。不相等,则从S的下一个字符串继续查找。最后找不到,则返回了-1,否则返回T在S中的开发位置。

下面是PHP的实现:

<?php
 function index($str, $reg, $startPos = 0) {
    $strArr = str_split($str);
    $regArr = str_split($reg);

    if ($startPos >= count($strArr)) {
        return -1;
    }

    $i = $startPos;
    $j = 0;

     while($i < count($strArr) && $j < count($regArr)) {
         if ($strArr[$i] == $regArr[$j]) {
             $i++;
             $j++;
         } else {
             $i = $i - $j + 1;
             $j = 0;
         }

         if ($j >= count($regArr))
         {
             return $i - count($regArr);
         }
     }

     return -1;
 }

 $str = "abdsfasjdkfl";
 $reg = "dkfl";
 print_r(index($str, $reg, 9));

 

php 快速排序

之前写冒泡,选择排序的算法。今天就抽空看看快速排序,快速排序先选择一个基数,将数组中的数据分别与这个基数对比。小于基数的放在一组,大于基数的放在一组。最后在递归对这两个数组继续排序。最后merge返回就是排序好的数据了。

function quick_sort(array $arr) {
    $length = count($arr);

    if ($length <= 1) return $arr;

    $leftArr = $rightArr = array();
    $baseValue = $arr[0];

    for ($i = 1; $i <= $length - 1; $i++) {
        if ($arr[$i] <= $baseValue)
            $leftArr[] = $arr[$i];
        else
            $rightArr[] = $arr[$i];
    }

    return array_merge(quick_sort($leftArr), array($baseValue), quick_sort($rightArr));
}

print_r(quick_sort(array(1,5,3,6,7,2)));

 

 

php Invalid photo dimension

刚才线上的项目,图片旋转的功能,不能使用了。奇怪的是这功能,很久没有变动了。突然就失灵了。后来在本地服务器上测试,正常使用。估计很有可能跟服务器的配置有关。于是把服务器的log下载下来,看了看。硬盘满载了。。原因是因为getimagesize的函数报了一个warning:Invalid photo dimension。估计这个方法,在计算图片的高宽的时候,将远程服务器的地址下载下来了。本地没有空间造成的。

list($width, $height) = getimagesize($url);

 

php二分查找

二分查找法,每次查找的数据,都是上一次的一半。所以速度很快。不过需要建立在已经排序好的数组上。

<?php
function binarySearch(array $arr, $target) {
    $low = 0;
    $max = count($arr) - 1;

    while($low <= $max) {
        $mid = (int)(($max + $low) / 2);

        if ($arr[$mid] > $target) $max = $mid - 1;

        if ($arr[$mid] < $target) $low = $mid + 1;

        if ($arr[$mid] == $target) return $mid;
    }

    return false;
}

echo binarySearch(array(1,2,3,4,5,6,7,8,9,10), 3);

 

php 选择排序

选择排序的算法也很简单。第二层循环,每次就是找出最小的数,然后交换。很简单,但是效率不是很高。

function select_sort(array $arr) {
    $length = count($arr);

    if ($length <= 1) {
        return $arr;
    }

    for ($i = 0; $i < $length; $i++) {      
        for ($j = $i; $j < $length; $j++) {
            if ($arr[$i] > $arr[$j]) {
                $tmp = $arr[$i];
                $arr[$i] = $arr[$j];
                $arr[$j] = $tmp;
            }
        }
    }

    return $arr;
}

$arr = array(1,4,6,2,100,10,9);
print_r(select_sort($arr));

 

PHP冒泡排序

网上关于冒泡的排序的算法,已经很多了。这个算法也很简单。下面是两种冒泡的方式,一个是每次筛选出最大的数,放到最后面。一个是每次找到最小的数,放到最前面。

<?php
$arr = array(10,6,3,8,1,9,33,22,0,-1);

function bubble_sort_one(array $arr) {
    $length = count($arr);

    if ($length <= 1) {
        return $arr;
    }

    for ($i = 0; $i < $length - 1; $i++) {
        for ($j = 0; $j < $length - 1 - $i; $j++) {
            if ($arr[$j] > $arr[$j + 1]) {
                $tmp = $arr[$j];
                $arr[$j] = $arr[$j+1];
                $arr[$j + 1] = $tmp;
            }
        }
    }

    return $arr;
}

function bubble_sort_two(array $arr) {
    $length = count($arr);

    if ($length <= 1) {
        return $arr;
    }

    for ($i = 0; $i < $length - 1; $i++) {
        for ($j = $length - 1; $j > $i; $j--) {
            if ($arr[$j] < $arr[$j - 1]) {
                $tmp = $arr[$j];
                $arr[$j] = $arr[$j - 1];
                $arr[$j - 1] = $tmp;
            }
        }
    }

    return $arr;
}

print_r(bubble_sort_one($arr));
echo "<br/>";
print_r(bubble_sort_two($arr));

 

php ${} 可变变量

记得之前看过这样的php变量写法:

$hello = "Hello world";
$test = "hello";

echo $$test;

结果输出的Hello world。今天又发现,这样可以做到:

$hello = "Hello world";
$test = "hello";

echo ${$test};

${} 大括号中间的字符串,再加上外面的$,就变成$hello变量了。。

后来又查了查资料,这叫可变变量。

php pear No releases for package 错误

最近服务器由于升级到了5.4。公司用的第三方打电话的库,出现了一些问题。由于是php5.4将一些函数放弃了。而第三方的库,却还在采用。所以决定将第三方的库升级一下。
由于很多的库,都是通过pear安装的。所以这次升级也是通过pear升级。代码如下:

sudo pear install pear/Services_Twilio-3.12.4

结果出现了以下错误:

No releases for package "twilio/Services_Twilio" exist
install failed

这个错误信息,还是很奇怪的。在去第三方提供的pear页面去查看,发现包是存在的。那为什么安装失败呢?在google大神的指导下,找到了答案:

pear clear-cache
pear update-channels

 

php call_user_func_array

call_user_func_array() 调用回掉函数,并把一个数组参数坐位回掉函数。也可以执行类中的方法。

例子:

<?php
function foobar($arg, $arg2) {
    echo __FUNCTION__, " got $arg and $arg2</br>";
}
class foo {
    static function bar($arg, $arg2) {
        echo __METHOD__, " got $arg and $arg2</br>";
    }

    function food($arg, $arg2) {
        echo __METHOD__, " got $arg and $arg2</br>";
    }
}

call_user_func_array("foobar", array("one", "two"));

$foo = new foo;
call_user_func_array(array($foo, "food"), array("three", "four"));
//这种方式是错误的
//call_user_func_array(array("foo", "food"), array("three", "four"));
//下面这种办法,通过PHP的对象的方式调用一个静态方法,并不会报错。但是静态方法中不可以出现$this关键字
call_user_func_array(array($foo, "bar"), array("three", "four"));
//个人感觉调用静态方法还是这样会好些
call_user_func_array(array("foo", "bar"), array("three", "four"));
?>

结果:

foobar got one and two
foo::food got three and four
foo::bar got three and four
foo::bar got three and four