使用php curl的方式调用对方提供的接口,收到了如下错误提示
HTTP Status 415
The server refused this request because the request entity is in a format not supported by the requested resource for the requested method.
Curl 的代码片段如下:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, FALSE);
curl_setopt($ch, CURLOPT_NOBODY, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
curl_setopt($ch, CURLOPT_AUTOREFERER, TRUE);
curl_setopt($ch, CURLOPT_TIMEOUT, 120);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($postData));
$data = curl_exec($ch);
curl_close($ch);
多次检查curl设置已经接口的说明没有发现问题。对方的服务器使用的是Tomcat 7, 一度怀疑是对方web配置有误,后来仔细研究文档,其中提到Response是jason格式文档,而上述curl中没有指定Request Header 信息, 所以尝试加入一个header, 结果问题解决。 代码如下:
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: application/json; charset=utf-8"));
在一台Centos6.4 64位编译安装php时候,出现Cannot find OpenSSL’s libraries,前提是已经确认通过yum 安装过OpenSSL库,在网上搜索,基本上得到的结果是安装OpenSSL库,对我的问题无济于事。最后在一个论坛发现,因为是64位系统,OpenSSL库安装在/usr/lib64/,但在安装php时,它还是去/usr/lib/ 下查找该库,故报上述错误。清楚了问题所在,解决办法就是做一个软链接如下:
ln -s /usr/lib64/libssl.so /usr/lib/
自php5.3.3开始,php源码中包含了php-fpm,不需要单独通过补丁的方式安装php-fpm,在源码安装的时候直接 configure 中增加参数 –enable-fpm 即可。
所以启动、关闭和重新加载的方式和以前不同,需要使用信号控制:
php-fpm master 进程可以理解一下信号:
SIGINT, SIGTERM 立刻终止
SIGQUIT 平滑终止
SIGUSR1 重新打开日志文件
SIGUSR2 平滑重载所有worker进程并重新载入配置和二进制模块
例如:关闭php-fpm
kill -SIGINT `cat /usr/local/php/var/run/php-fpm.pid`
php-fpm 重启
kill -SIGUSR2 `cat /usr/local/php/var/run/php-fpm.pid`
注意:/usr/local/php/var/run/php-fpm.pid 指存储master进程号的文件,这里是默认地址,在配置中可以修改,另外可以使用ps命令找到master的进程号,然后使用 kill 信号 进程号 的方式。
include和require的用途是包含并运行指定的文件。在官方手册没有说明被包含的文件类型,那么PHP到底能不能include一个非PHP文件呢?实践出真理,写一个简单文件PHP文件include一个js文件,执行后没有报错或警告信息,同时看到被包含js的文件的内容被打印出来。因此得出结论:include 目标文件可以是任意类型。
现在再回头看include的官方文档,其中有这么一段话:“当一个文件被包含时,语法解析器在目标文件的开头脱离 PHP 模式并进入 HTML 模式,到文件结尾处恢复。由于此原因,目标文件中需要作为 PHP 代码执行的任何代码都必须被包括在有效的 PHP 起始和结束标记之中。” 注意其中提到“HTML模式,PHP代码必须包括在有效的PHP标记符中”,仔细体会其含义,它其实隐式的说明了include可以是任意类型的文件。
另外在4.3.0以后,include 目标文件还可以是一个url,当然前提是需要在配置中设置 allow_url_include 为 on。
一个php脚本通过crontab每5分钟执行一次,考虑到脚本执行时间会超过5分钟,特意用set_time_limit(290)来控制脚本在290秒退出。某天突然发现后台有多个该脚本的进程在执行,也就是说set_time_limit(290)没有起作用。为了证明,特意使用如下代码测试。
set_time_limit(5);
for ($i = 0; $i < 100; $i++) {
echo date('Y-m-d H:i:s') . "\n";
sleep(1);
}
无论是在web还是CLI下,上述脚本并没有在5秒钟后退出。后来加上ini_set(‘max_execution_time’, 5)测试,结果一样。那是不是说明set_time_limit函数根本就没有用呢?其实不然,在 http://stackoverflow.com/questions/5874950/set-max-execution-time-in-php-cli 这里找到根源所在,其实是上面的写法有问题,例如使用下述代码:
set_time_limit(5);
for (;;) {
}
执行后,大概5秒钟就可以看到”Fatal error: Maximum execution time of 5 seconds exceeded in”类似这样的错误提示。说明set_time_limit是起作用的。现在在去看看官方文档(http://www.php.net/manual/en/function.set-time-limit.php)上关于此函数的说明,在Note中写到:
The set_time_limit() function and the configuration directive max_execution_time only affect the execution time of the script itself. Any time spent on activity that happens outside the execution of the script such as system calls using system(), stream operations, database queries, etc. is not included when determining the maximum time that the script has been running. This is not true on Windows where the measured time is real.
注意:sleep函数暂停的时间也是不计入脚本的执行时间的。所以也是第一个测试失败的原因。
如果你还想着通过解析swf文件头信息来获取flash文件的尺寸信息,那真的有点走远了。因为从PHP 4开始已经内置getimagesize函数来做这个事。其功能测定任何 GIF,JPG,PNG,SWF,SWC,PSD,TIFF,BMP,IFF,JP2,JPX,JB2,JPC,XBM 或 WBMP 图像文件的大小并返回图像的尺寸以及文件类型和一个可以用于普通 HTML 文件中 IMG 标记中的 height/width 文本字符串。而且从PHP 4.0.5起还支持参数是一个url。例如:
print_r(getimagesize('http://www.google.com.hk/images/srpr/logo4w.png'));
输出的结果为:
Array
(
[0] => 550
[1] => 190
[2] => 3
[3] => width="550" height="190"
[bits] => 8
[mime] => image/png
)
对应标题所提的问题,php内部自带了函数提供检测。
常量检测使用defined,定义常量则是define。注意待检测的常量需要使用引号(单双均可),如:
if (defined('CONST_NAME')) {
//do something
}
变量检测则是使用isset,注意变量未声明或声明时赋值为NULL,isset均返回FALSE,如:
if (isset($var_name)) {
//do something
}
函数检测用function_exists,注意待检测的函数名也需要使用引号,如:
if (function_exists('fun_name')) {
fun_name();
}
借助于date和strtotime函数,可以轻松的获取本月、下月以及上月的第一天和最后一天,下面分别给出其实现。其中函数的参数date格式为yyyy-MM-dd。
1、给定一个日期,获取其本月的第一天和最后一天
function getCurMonthFirstDay($date) {
return date('Y-m-01', strtotime($date));
}
function getCurMonthLastDay($date) {
return date('Y-m-d', strtotime(date('Y-m-01', strtotime($date)) . ' +1 month -1 day'));
}
2、给定一个日期,获取其下月的第一天和最后一天
function getNextMonthFirstDay($date) {
return date('Y-m-d', strtotime(date('Y-m-01', strtotime($date)) . ' +1 month'));
}
function getNextMonthLastDay($date) {
return date('Y-m-d', strtotime(date('Y-m-01', strtotime($date)) . ' +2 month -1 day'));
}
3、给定一个日期,获取其下月的第一天和最后一天
function getPrevMonthFirstDay($date) {
return date('Y-m-d', strtotime(date('Y-m-01', strtotime($date)) . ' -1 month'));
}
function getPrevMonthLastDay($date) {
return date('Y-m-d', strtotime(date('Y-m-01', strtotime($date)) . ' -1 day'));
}
其中strtotime函数参数“+1 month”,php会根据具体月份来确定增加多少天,可能是28、29(2月)、30(小月)或 31(大月);某月的第一天 “-1 day” 自然就是上个月最后一天,php也会根据月来智能确定是28、29、30或31。
strtotime 的功能很强大,详细用法可以查看官方文档:http://php.net/manual/zh/function.strtotime.php 。
1、获取文件名:basename();
2、获取文件所在的目录:dirname();
3、pathinfo()获取文件信息,返回结果为一个array,包括路径、文件全名、文件名和扩展名。例如:
$file = '/com/netingcn/error.log';
print_r(pathinfo($file));
结果为:
Array(
[dirname] => /com/netingcn
[basename] => error.log
[extension] => log
[filename] => error
)
4、判断文件是否存在:is_file();
5、判断目录是否存在:is_dir();
6、判断文件或目录是否存在:file_exists();
7、读取文件所有内容:file()或file_get_contents(),其中file()返回的是一个一行为元素的array,file_get_contents()把文件全部内容作为一个String返回;
8、写文件fwrite,如:
$handler = fopen($file, 'w'); // w 会冲掉以前的内容、a 是追加
fwrite($handler, 'content');
fclose($handler); //记得关闭打开的文件句柄
9、文件读取操作有很多,下面简单介绍几个:
$handler = fopen($file, 'r');
while(!feof($handler)) {
$datas[] = fgets($handler); //读取一行内容
}
while(!feof($handler)) {
$datas[] = fgetss($handler); //读取一行内容并过来html标记
}
while(!feof($handler)) {
$datas[] = fgetcsv($handler); //读取一行内容并解析csv字段
}
$content = fread($handler, $strLength); //读取指定长读的字符
fclose($handler);
删除数组中的元素,第一想法是使用unset函数,它确实可以删除,但是可能会在后面操作该数组的时候出现问题。通过下面的例子来说明:
$arr = array(0, 1, 2, 3, 4);
$index = 2;
unset($arr[$index]);
echo count($arr);
if (empty($arr[$index])) {
echo "arr[$index] is empty";
}
print_r($arr);
输出为:
4
arr[2] is empty
Array([0] => 0 [1] => 1 [3] => 3 [4] => 4)
从上面的输出结果可以看到数组的长度是正常的,但是下标还是保持原来的,所以按照下标去获取元素就会出问题。另外此方法对key-value形式的数组是安全的。
如何安全的删除元素呢?可以使用array_splice函数。array_splice()的用途是删除原始数组中指定的一系列元素,并用其他值代替(如果指定),返回值是被删除的元素。更多信息可以参考官方文档:http://php.net/manual/zh/function.array-splice.php。例如:
$arr = array(0, 1, 2, 3, 4);
$rtn = array_splice($arr, 2, 1);
echo count($arr);
print_r($arr);
print_r($rtn);
输出为:
4
Array
([0] => 0 [1] => 1 [2] => 3 [3] => 4)
Array([0] => 2)
如果想获取删除首位元素后的数组,则可以有两种方法:
1、
$arr = array(0, 1, 2, 3, 4);
array_splice($arr, 0, 1);
2、
$arr = array(0, 1, 2, 3, 4);
$arr = array_splice($arr, 1);