PHP7捕获错误异常

公司最近一个项目使用的是PHP7,发现使用 php5里面的 Exception 类捕获不到致命错误。
查了一下手册,PHP7的错误报告机制已改变,大多数错误被作为 Error 异常抛出

php官网说明是
这种 Error 异常可以像 Exception 异常一样被第一个匹配的 try / catch 块所捕获。如果没有匹配的 catch 块,则调用异常处理函数(事先通过 set_exception_handler() 注册)进行处理。 如果尚未注册异常处理函数,则按照传统方式处理:被报告为一个致命错误(Fatal Error)。

Error 类并非继承自 Exception 类,所以不能用 catch (Exception $e) { … } 来捕获 Error。你可以用 catch (Error $e) { … },或者通过注册异常处理函数( set_exception_handler())来捕获 Error。

来一段代码实例

try {
    echo asdfasdf('1');  //未定义的函数
} catch (Exception $e) {
    // Handle exception
    echo 'Exception';
} catch (Error $e) { // Clearly a different type of object
    // Log error and end gracefully
    echo 'Error';
}

最后输出的是 Error 。。。
所以用PHP7捕获异常防止错误的话,建议 catch :Exception 和 Error

php使用curl设置超时的重要性

这段时间用PHP写了个爬虫程序,但是经常执行了一段时间后程序就卡住了。
程序是用的curl方式进行抓取,后来设置了 CURLOPT_TIMEOUT 参数就没有出现这个问题了
平常如果测试curl都直接设置了url就直接执行了。
curl功能还是很强大的,如果线上使用最好还是把 所有参数都设置一遍,还可以设置毫秒级超时
最后分享一段 curl 方法

function http_request($URI, $isHearder = false, $post = false)
{
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $URI);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_TIMEOUT, 60);          //单位 秒,也可以使用
#curl_setopt($ch, CURLOPT_NOSIGNAL, 1);     //注意,毫秒超时一定要设置这个
#curl_setopt($ch, CURLOPT_TIMEOUT_MS, 200); //超时毫秒,cURL 7.16.2中被加入。从PHP 5.2.3起可使用
    curl_setopt($ch, CURLOPT_HEADER, $isHearder);
    curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36');
    curl_setopt($ch, CURLOPT_COOKIEFILE, dirname(__FILE__)."/tmp.cookie");
    curl_setopt($ch, CURLOPT_COOKIEJAR, dirname(__FILE__)."/tmp.cookie");
    if(strpos($URI, 'https') === 0){
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
    }
    if($post){
        curl_setopt ($ch, CURLOPT_POST, 1);
        curl_setopt ($ch, CURLOPT_POSTFIELDS, $post);
    }
    $result = curl_exec($ch);
    curl_close($ch);
    return $result;
}

HTML5之FileReader对象在浏览器中读取本地文件内容、预览图片

在一些项目中,经常会遇到图片上传的情况,为了提高用户体验,一般会要求选择图片后 能预览一下图片。
以前的做法是 通过 ajax上传图片后,然后再显示出来,这样会产生大量的无用的图片文件,在HTML5的时代,有了FileReader对象,可以在浏览器选择本地的图片后,立马就可以在浏览器中显示选择的图片
具体也不对说了,手册百度一搜就是,就贴一下示例代码

<!doctype html>
<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
<title>Image preview example</title>
<script type="text/javascript">
oFReader = new FileReader(), rFilter = /^(?:image\/bmp|image\/cis\-cod|image\/gif|image\/ief|image\/jpeg|image\/jpeg|image\/jpeg|image\/pipeg|image\/png|image\/svg\+xml|image\/tiff|image\/x\-cmu\-raster|image\/x\-cmx|image\/x\-icon|image\/x\-portable\-anymap|image\/x\-portable\-bitmap|image\/x\-portable\-graymap|image\/x\-portable\-pixmap|image\/x\-rgb|image\/x\-xbitmap|image\/x\-xpixmap|image\/x\-xwindowdump)$/i;

oFReader.onload = function (oFREvent) {
  document.getElementById("uploadPreview").src = oFREvent.target.result;
};

function loadImageFile() {
  if (document.getElementById("uploadImage").files.length === 0) { return; }
  var oFile = document.getElementById("uploadImage").files[0];
  if (!rFilter.test(oFile.type)) { alert("You must select a valid image file!"); return; }
  oFReader.readAsDataURL(oFile);
}
</script>
</head>

<body onload="loadImageFile();">
  <form name="uploadForm">
    <table>
      <tbody>
        <tr>
          <td><img id="uploadPreview" style="width: 100px; height: 100px;" src="" alt="Image preview" /></td>
          <td><input id="uploadImage" type="file" name="myPhoto" onchange="loadImageFile();" /></td>
        </tr>
      </tbody>
    </table>

    <p><input type="submit" value="Send" /></p>
  </form>
</body>
</html>

FileReader对象 配合 FormData对象 就可以完成一个体验很好的图片上传功能。不过这两个对象都是 HTML5新增的,兼容性不是很高,目前还比较时候用来做内部系统或者网站后台

过滤utf8mb4字符转为mysql支持的utf8

最近做开发 发现,有些字符不能存进mysql,后来百度后,得出的结论是,mysql的utf8编码并不是真正完整的utf8,在mysql新版本里选择utf8mb4这才是完整的utf8编码。
手机上有些图标比如: Emoji表情图标 在mysql里面需要选择utf8mb4才能存储和显示,网上大部分用mysql存Emoji表情相关的解决办法是 把mysql的字符集改为 utf8mb4,但是 最近有个需求就是截取掉对于mysql的utf8mb4的字符集。想了几天,突然想在wordpress看代码,结果 果然找到,分享之。此方案为过滤掉 utf8mb4 的字符

我这里的mysql本来就不支持utf8mb4的,所以就这样基本上看不到效果….

    $str = '□测试,测试!123□';
    $charset = 'utf8';
    $regex = '/
        (
            (?: [\x00-\x7F]                  # single-byte sequences   0xxxxxxx
            |   [\xC2-\xDF][\x80-\xBF]       # double-byte sequences   110xxxxx 10xxxxxx
            |   \xE0[\xA0-\xBF][\x80-\xBF]   # triple-byte sequences   1110xxxx 10xxxxxx * 2
            |   [\xE1-\xEC][\x80-\xBF]{2}
            |   \xED[\x80-\x9F][\x80-\xBF]
            |   [\xEE-\xEF][\x80-\xBF]{2}';

    if ( 'utf8mb4' === $charset ) {
        $regex .= '
            |    \xF0[\x90-\xBF][\x80-\xBF]{2} # four-byte sequences   11110xxx 10xxxxxx * 3
            |    [\xF1-\xF3][\x80-\xBF]{3}
            |    \xF4[\x80-\x8F][\x80-\xBF]{2}
        ';
    }

    $regex .= '){1,40}                          # ...one or more times
        )
        | .                                  # anything else
        /x';
    $str1 = preg_replace( $regex, '$1', $str );
    var_dump($str1);

    //另一种解决方法
    $str1 = preg_replace('/[\x{10000}-\x{10FFFF}]/u', '', $str);
    var_dump($str1);

利用CSS3属性background-size做响应式布局背景图

现在响应式布局越来越流行,但是网站的logo一般是用的 background(背景图片) 属性实现,而不是直接在页面使用img标签。
如果使用背景,在css2里面宽高是固定的值,那么这就不适合响应式布局了,网站百度一下搜到 css3里面新增了 background-size,可以实现自适应div的宽高改变背景图片的大小。

/*只要这样就对了*/
background-size:contain;

继续阅读

PHP实现linux下tail命令功能

发现很久没更新博客了,前几天写了个微信爬虫,但是想要实时查看爬虫的情况,所以爬虫会把记录写到一个文件里面。
如果是在linux shell直接用 tail -f 命令就可以实时查看更新了。但是每次都要ssh登录,觉得还是太麻烦。
干脆用PHP写个tail功能的脚本,然后再用 ajax请求 php文件 获取文件最后几行,这样就可以直接在浏览器上面实现 linux命令行里面tail功能了。 继续阅读

ThinkPHP框架使用Smarty模板引擎

最近公司使用ThinkPHP框架,所以比较关注,想到之前公司使用的框架用的模板引擎是 Smarty,而且用的还挺顺手的。
转到使用ThinkPHP自带的模板引擎还有点不习惯,所以在想换成Smarty模板引擎,网上看了一下,结果还是比较简单。
以此记录一下 继续阅读

树莓派+aria2+yaaw搭建下载机

网上有很多树莓派搭建下载机的方法,用yaaw通过rpc方式访问 aria2,但是都没有加密,这就很不安全了。

网上查了
Set --rpc-secret= if you are using aria2 1.18.4(or higher) with 'JSON-RPC PATH' like http://token:secret@hostname:port/jsonrpc
Set --rpc-user= --rpc-passwd= if you are using aria2 1.15.2(or higher) with 'JSON-RPC PATH' like http://username:passwd@hostname:port/jsonrpc

aria2 1.18.4版本以上的已经不在支持 –rpc-user= –rpc-passwd= 这种加密方式了,只能用 token和secret方式加密。就是这里我一直用设置 username和passwd一直没效果,原来现在只支持token和secret方式加密。 继续阅读

shell中$0,$?,$!,$$,$*,$#等特殊变量说明及用法

闲来无事看了下关于<>,看到书上说shell可以获取程序的返回值,故百度一下(google最近太不稳定了),发现shell里还有很多特殊变量没有记住,还是写篇博客记录下,以后也方便查找

变量说明:

$$
Shell本身的PID(进程ID)
$!
Shell最后运行的后台Process的PID
$?
最后运行的命令的结束代码(返回值),可以得到之前运行程序的返回值,可以判断程序是否运行正确(一般程序运行正确返回0)
$-
使用Set命令设定的Flag一览
$*
所有参数列表。如”$*”用「”」括起来的情况、以”$1 $2 … $n”的形式输出所有参数。
$@
所有参数列表。如”$@”用「”」括起来的情况、以”$1″ “$2” … “$n” 的形式输出所有参数。
$#
添加到Shell的参数个数
$0
Shell本身的文件名
$1~$n
添加到Shell的各参数值。$1是第1参数、$2是第2参数…。

我们先写一个简单的脚本,执行以后再解释各个变量的意义
# touch variable
# vi variable
脚本内容如下:
#!/bin/sh
echo “number:$#”
echo “scname:$0”
echo “first :$1”
echo “second:$2”
echo “argume:$@”
保存退出
赋予脚本执行权限
# chmod +x variable
执行脚本
# ./variable aa bb
number:2
scname:./variable
first: aa
second:bb
argume:aa bb
通过显示结果可以看到:
$# 是传给脚本的参数个数
$0 是脚本本身的名字
$1是传递给该shell脚本的第一个参数
$2是传递给该shell脚本的第二个参数
$@ 是传给脚本的所有参数的列表
$?