邢栋博客

邢栋博客,Action博客,记录工作和生活中的点点滴滴

php关于猴子选大王的算法题
<?php
    
    /**
     *  $m 猴子总数
     *  $n 出局数
     */
    function king($m,$n){
        $arr = range(1, $m);
        $i = 0;
        while (count($arr)>1) {
            if(($i+1)%$n == 0){
                unset($arr[$i]);
            }else{
                array_push($arr, $arr[$i]);
                unset($arr[$i]);
            }
            $i++;
        }
        return reset($arr);
    }

    function king2($m,$n){
        $arr = range(1, $m);
        $unsetNum = 0;
        for($i=2;$i<= $m*$n;$i++){
            foreach ($arr as $key => $value) {
                $unsetNum++;
                if($unsetNum == $n){
                    unset($arr[$key]);
                    $unsetNum = 0;
                }
                if(count($arr) == 1){
                    return reset($arr);
                }
            }
        }
    }

    function ysf($m,$n){
        $num=0; 
        for($i=2; $i<=$m; $i++){
            $num=($num+$n)%$i; 
        }
        return $num+1; 
    }

    $res = king(5,3);
    var_dump($res);

    $res2 = king2(5,3);
    var_dump($res2);

    $res3 = ysf(5,3);
    var_dump($res3);

php还原java中gzip压缩方法
有个需求,要把java代码里面的jzip压缩方法还原成php
java jzip压缩代码如下


 /*** 
     * 压缩GZip 
     *  
     * @param data 
     * @return 
     */  
    public static byte[] gZip(byte[] data) {  
        byte[] b = null;  
        try {  
            ByteArrayOutputStream bos = new ByteArrayOutputStream();  
            GZIPOutputStream gzip = new GZIPOutputStream(bos);  
            gzip.write(data);  
            gzip.finish();  
            gzip.close();  
            b = bos.toByteArray();  
            bos.close();  
        } catch (Exception ex) {  
            ex.printStackTrace();  
        }  
        return b;  
    }  



    php代码

     
class {

   /*
     * 把字符串进行gzip压缩,并转换成byte数组
     * @param $str 需要进行压缩的字符串
     * @param $bytes 目标byte数组
     */

   public static function myGzencode($str){

       $res = gzencode($str);
       $res = self::getBytes($res);
       $res[9] = 0; //这步完全是为了和java压缩后的头部保持一致,也许是个坑
       return $res;
   }

   /*
    * 转换一个String字符串为byte数组
    * @param $str 需要转换的字符串
    * @param $bytes 目标byte数组
    * @author Zikie
    */

   public static function getBytes($str) {

       $len = strlen($str);
       $bytes = array();
       for($i=0;$i<$len;$i++) {
           if(ord($str[$i]) >= 128){
               $byte = ord($str[$i]) - 256;
           }else{
               $byte = ord($str[$i]);
           }
           $bytes[] =  $byte ;
       }
       return $bytes;
   }  
    }
ps:https://tools.ietf.org/html/rfc1952#section-2.2

    同学给推荐了这边文章,如下内容 
0 - FAT filesystem (MS-DOS, OS/2, NT/Win32)
         1 - Amiga
         2 - VMS (or OpenVMS)
         3 - Unix
         4 - VM/CMS
         5 - Atari TOS
         6 - HPFS filesystem (OS/2, NT)
         7 - Macintosh
         8 - Z-System
         9 - CP/M
        10 - TOPS-20
        11 - NTFS filesystem (NT)
        12 - QDOS
        13 - Acorn RISCOS
       255 - unknown

    我压缩后转换成byte数组,第九位是11,java那边是0,可能我的文件系统是NTFS filesystem (NT),java可能是FAT filesystem (MS-DOS, OS/2, NT/Win32)


PHP不用第三变量交换2个变量的值
<?php
	
	$a = 'a';
	$b = 'b';
	//第一种方法 字符串截取
	$a .= $b;
	$b = substr($a,0,strlen($a)-strlen($b));
	$a = substr($a,strlen($a)-strlen($b));

	echo $a;
	echo "<br>";
	echo $b;
	echo "<br>";

	//第二种方法 字符串替换
	$a .=$b;
	$b = str_replace($b,"",$a);
	$a = str_replace($b,"",$a);
	echo $a;
	echo "<br>";
	echo $b;
	echo "<br>";

	//第三种方法 数组转换
	list($b,$a) = array($a,$b);
	echo $a;
	echo "<br>";
	echo $b;
	echo "<br>";

	//第四种方法 异或运算
	$a=$a^$b;
	$b=$b^$a;
	$a=$a^$b;
	echo $a;
	echo "<br>";
	echo $b;
php格式化输出json数据
<?php  
  
/** Json数据格式化 
* @param  Mixed  $data   数据 
* @param  String $indent 缩进字符,默认4个空格 
* @return JSON 
*/  
function jsonFormat($data, $indent=null){  
  
   	// json encode  
    $data = json_encode($data,JSON_UNESCAPED_UNICODE);  //php5.4版本以上,如果低版本只能先urlencode然后再urldecode,保护中文
 
    // 缩进处理  
    $ret = '';  
    $pos = 0;  
    $length = strlen($data);  
    $indent = isset($indent)? $indent : '    ';  
    $newline = "\n";  
    $prevchar = '';  
    $outofquotes = true;  
  
    for($i=0; $i<=$length; $i++){  
  
        $char = substr($data, $i, 1);  
  
        if($char=='"' && $prevchar!='\\'){  
            $outofquotes = !$outofquotes;  
        }elseif(($char=='}' || $char==']') && $outofquotes){  
            $ret .= $newline;  
            $pos --;  
            for($j=0; $j<$pos; $j++){  
                $ret .= $indent;  
            }  
        }  
  
        $ret .= $char;  
          
        if(($char==',' || $char=='{' || $char=='[') && $outofquotes){  
            $ret .= $newline;  
            if($char=='{' || $char=='['){  
                $pos ++;  
            }  
  
            for($j=0; $j<$pos; $j++){  
                $ret .= $indent;  
            }  
        }  
  
        $prevchar = $char;  
    }  
  
    return $ret;  
}  
  

  
header('content-type:application/json;charset=utf8');  
  
$arr = array(  
    'member' =>array(  
        array(  
            'name' => '小矿工',  
            'gender' => '传奇卡'  
        ),  
        array(  
            'name' => '电磁炮',  
            'gender' => '传奇卡'  
        )  
    )  
);  
  
echo jsonFormat($arr);  
  
?>  

phpize版本问题

我的php环境是5.5,升级5.6之后,编译扩展的时候 最后执行make install 后,扩展安装到了5.5下面

最后解决办法

/usr/local/bin/phpize --clean  //我的phpize的路径,最好在执行./configure --with-php-config=/usr/local/bin/php-config,也用绝对路径


php实现异步调用无阻塞
php实现异步调用无阻塞


之前web端的数据统计用的是嵌入一个img标签,src指向脚本文件/index.php?name=xingdong,这种方法倒是挺快,不过需要的是页面加载,现在是在给客户端写接口,就不太合适.于是找了下解决办法

1.popen() (转)
resource popen ( string command, string mode );
//打开一个指向进程的管道,该进程由派生给定的 command 命令执行而产生。打开一个指向进程的管道,该进程由派生给定的 command 命令执行而产生。

所以可以通过调用它,但忽略它的输出。
pclose(popen("/home/xinchen/backend.php &", 'r'));
这个方法避免了第一个方法的缺点,并且也很快。但是问题是,这种方法不能通过HTTP协议请求另外的一个WebService,只能执行本地的脚本文件。并且只能单向打开,无法穿大量参数给被调用脚本。
并且如果,访问量很高的时候,会产生大量的进程。如果使用到了外部资源,还要自己考虑竞争。


2.curl
这个方法,设置CUROPT_TIMEOUT为1(最小为1,郁闷)。也就是说,客户端至少必须等待1秒钟
$ch = curl_init();
$curl_opt = array(CURLOPT_URL, 'http://www.example.com/backend.php',CURLOPT_RETURNTRANSFER, 1,CURLOPT_TIMEOUT, 1,);
curl_setopt_array($ch, $curl_opt);
curl_exec($ch);
curl_close($ch);

3.fsockopen和stream_socket_client,可以直接替换
ps:PHP5中可以使用新增的stream_socket_client()函数直接替换掉fsocketopen()
在使用之前出现了很多问题,我的服务器配置比较低,nginx配置中worker_processes为1,出现了请求后没有异步处理,改成2解决
执行一个时间比较长的异步请求后,不能全部执行,查看php-fpm日志发现
WARNING: [pool www] child 19307, script '/work/www/live/manage/index.php' (request: "GET /index.php") execution timed out (130.098597 sec), terminating
修改php-fpm.ini中的request_terminate_timeout=0解决(不知道还有什么别的坑没有),默认是120

我尝试着用了swoole扩展解决异步,暂时没发现问题,但是要是用swoole的话,所有的服务器都得装,太麻烦了,先这样,如果再出现问题,在用swoole扩展试下

无数据传输
<?php
 
    $fp = fsockopen("www.example.com", 80, $errno, $errstr, 30);
  if (!$fp){
        echo 'error fsockopen';
  }else{
         //stream_set_blocking($fp,0);//为资源流设置阻塞或者阻塞模式
         $http = "GET /index.php HTTP/1.1\r\n";
         $http .= "Host:www.example.com\r\n";
         $http .= "Connection: Close\r\n\r\n";
         fwrite($fp,$http);
         //while (!feof($fp)) {
           //  echo fgets($fp, 128);

         // }
        //usleep(1000);//如果异步调用不成功,可以加上这句话

         fclose($fp);
  }
?>

get数据
<?php
$param = array(  
    'name' => 'xingdong'    
);  
  
$url = $url.'?'.http_build_query($param); 

    $fp = fsockopen("www.example.com", 80, $errno, $errstr, 30);
  if (!$fp){
        echo 'error fsockopen';
  }else{
         //stream_set_blocking($fp,0);//为资源流设置阻塞或者阻塞模式
         $http = "GET ${url} HTTP/1.1\r\n";
         $http .= "Host:www.example.com\r\n";
         $http .= "Connection: Close\r\n\r\n";
         //fputs($fp,$http);
         fwrite($fp,$http);
         fclose($fp);
  }

?>


post数据
<?php
$param = array(  
    'name' => 'xingdong'    
);  
  $data = http_build_query($param); 
$url = '/index.php'; 

    $fp = fsockopen("www.example.com", 80, $errno, $errstr, 30);
  if (!$fp){
        echo 'error fsockopen';
  }else{
         //stream_set_blocking($fp,0);//为资源流设置阻塞或者阻塞模式
         $http = "POST ${url} HTTP/1.1\r\n";
         $http .= "Host:www.example.com\r\n";
         $http .= "Connection: Close\r\n\r\n";
         $http .= "Content-type:application/x-www-form-urlencoded\r\n";  
         $http .= "Content-length:".strlen($data)."\r\n";  
         $http .= "Connection:close\r\n\r\n";  
         $http .= "${data}"; 
         //fputs($fp,$http);
         fwrite($fp,$http);
         fclose($fp);
  }

?>


php的$GLOBALS["HTTP_RAW_POST_DATA"]为空
php的$GLOBALS["HTTP_RAW_POST_DATA"]为空

微信公众号开发用$GLOBALS["HTTP_RAW_POST_DATA"]接收数据为空

解决方案
1.php7 的话改为  file_get_contents('php://input')
2.php.ini中设置 always_populate_raw_post_data = On,适用于php7之前版本,因为php7的时候废除了HTTP_RAW_POST_DATA


liunx下升级openssl并重新编译php的openssl扩展
liunx下升级openssl并重新编译php的openssl扩展

openssl的坑太多了
1.查看openssl版本
openssl version -a   
2.去官网下载所需要版本 并编译安装
cd /envionment    //我一般吧环境放到这个目录
wget https://www.openssl.org/source/openssl-1.0.2h.tar.gz
tar zxvf openssl-1.0.2h.tar.gz
cd openssl-1.0.2h
./config --prefix=/usr/local/ssl  shared zlib //一定记得加上shared选项,我之前没注意,最后重新编译php的opensll扩展的时候,发现OpenSSL Library Version 和OpenSSL Header Version不一致 ,--prefix 安装路径
make 
make install
mv /usr/bin/openssl /usr/bin/openssl.bak
mv /usr/include/openssl /usr/include/openssl.bak
ln -s /usr/local/ssl/bin/openssl /usr/bin/openssl //*** 必须步骤
ln -s /usr/local/ssl/include/openssl /usr/include/openssl//**必须步骤,否则编译php的openssl会报错
echo “/usr/local/ssl/lib” >> /etc/ld.so.conf
ldconfig -v
3.查看是否升级成功
openssl version -a  //OpenSSL 1.0.2h  3 May 2016

-------------------------------

重新编译php的时候注意事项

liunx升级openssl后,重新编译php的openssl扩展后仍然不是最新版本
解决办法:
./configure 的时候 --with-openssl=/usr/local/ssl 一定要指定刚才装的路径,否则php的openssl还会是之前的版本


优惠券
广告位-淘宝
最新微语