2016年4月29日星期五

PHP 无法开启 OCI8 扩展原因

今天刚好有个需求,要用 PHP 把数据写入远程 Oracle 数据库,所以要用到 OCI8 扩展。但总是无法开启,查阅了大量资料才知道原来是因为本地机器没安装 Oracle 数据库, 系统缺少Oracle的几个关键DLL造成的,可以通过安装Oracle Instant Client 来添加这些DLL。

Oracle Instant Client下载地址如下:

下载后,将其解压到 D:\Program Files\instantclient_11_2 (非固定位置),并将该路径加入到系统PATH环境变量的最前面。
然后重启一下Webserver,再查看phpinfo,可以OCI8模块信息了。

总结一下,PHP OCI8扩展的开启步骤:
(1)去掉php.ini中extension=php_oci8.dll前面的注释。

(2)解压 Oracle Instant Client,并将解压目录加入到系统PATH环境变量中。

(3)重启Webserver,使用phpinfo查看OCI8模块是否出现。



下面是Oracle官方的安装说明,很详细:
《nstalling PHP and the Oracle Instant Client for Linux and Windows

另外关于PHP操作Oracle的资料,这个感觉不错:

OCI8操作Oracle的PHP手册:

2016年4月27日星期三

PHP 获取远程图片(文件)并把它保存到本地

// 获取远程图片并把它保存到本地,确定您有把文件写入本地服务器的权限
// 变量说明:
// $url 是远程图片的完整URL地址,不能为空。
// $filename 是可选变量: 如果为空,本地文件名将基于时间和日期
// 自动生成.

function grab_image($url,$filename='') {
    if($url=='') {
       return false;
    }

    if($filename=='') {
        $ext = strrchr($url,".");
        if($ext!=".gif" && $ext!=".jpg" && $ext!=".png") {
           return false;
         }
        $filename = date("dMYHis").$ext;
    }
    ob_start();
    readfile($url);
    $img = ob_get_contents();
    ob_end_clean();

    $fp2=@fopen($filename, "a");
    fwrite($fp2,$img);
    fclose($fp2);

    return $filename;
}


远程获取文件原理与获取图片原理是类似的。这一步判断不要就可以了。

        if($ext!=".gif" && $ext!=".jpg" && $ext!=".png") {
           return false;

         }

2016年4月26日星期二

微信登录获取 openid 失败原因



今天再开发网站微信登录的时候,用 curl_init 无法获取 openid,代码如下

<?php
    $code = isset($_GET['code']) ? trim($_GET['code']) : '';
    $url = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid='.WX_APPID.'&secret='.WX_SECRET.'&code='.$code.'&grant_type=authorization_code';
    $ch = curl_init();
    curl_setopt ($ch, CURLOPT_URL, $url);
    curl_setopt ($ch, CURLOPT_HEADER, 0);// 显示返回的Header区域内容   
    curl_setopt ($ch, CURLOPT_TIMEOUT, 30);// 设置超时限制
    curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回
    curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT,10);// 链接超时限制
    curl_setopt ($ch, CURLOPT_HTTPHEADER,array('Accept-Encoding: gzip, deflate'));//设置 http 头信息
    curl_setopt ($ch, CURLOPT_ENCODING, 'gzip,deflate');//添加 gzip 解码的选项,即使网页没启用 gzip 也没关系 
    $content = curl_exec($ch);

?>


后来发现跟 https 有关,加上下面这两个选项就可以了

    curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST,0);
    curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER,0); 


由于 CURLOPT_SSL_VERIFYPEER 的预设值为 TRUE 是要验证伺服器凭证的,所以当拜访 https 网站时,若未做任何 SSL 相关设定,会出现以下错误。
Error Number: 60
Error Message: SSL certificate problem, verify that the CA cert is OK. Details:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
如果只是要拜访 https 网站,但不会来回传递敏感信息,可以把 CURLOPT_SSL_VERIFYPEER 设定为 FALSE,代表可以盲目接受任何伺服器凭证。

而当 CURLOPT_SSL_VERIFYPEER 为 FALSE 时,其他诸如 CURLOPT_SSL_VERIFYHOST, CURLOPT_CAINFO, CURLOPT_CAPATH 等设定,都不具任何意义。

2014年5月23日星期五

curl 和 file_get_contents 抓取网页乱码的解决之道

    今天用 curl_init 函数抓取搜狐的网页时,发现采集的网页时乱码,经过分析发现原来是服务器开启了gzip压缩功能。只要往函数 curl_setopt 添加多个选项 CURLOPT_ENCODING 解析 gzip 就可以正确解码了。


    还有如果抓取的网页时 GBK 编码,但是脚本确是 utf-8 编码,还得把抓取的网页再用函数 mb_convert_encoding 转换下。

<?php

    $tmp = sys_get_temp_dir();

    $cookieDump = tempnam($tmp, 'cookies');
    $url = 'http://tv.sohu.com';
    $ch = curl_init();
    curl_setopt ($ch, CURLOPT_URL, $url);
    curl_setopt ($ch, CURLOPT_HEADER, 1);// 显示返回的Header区域内容
    curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转
    curl_setopt ($ch, CURLOPT_TIMEOUT, 10);// 设置超时限制
    curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回
    curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT,10);// 链接超时限制
    curl_setopt ($ch, CURLOPT_HTTPHEADER,array('Accept-Encoding: gzip, deflate'));//设置 http 头信息
    curl_setopt ($ch, CURLOPT_ENCODING, 'gzip,deflate');//添加 gzip 解码的选项,即使网页没启用 gzip 也没关系
    curl_setopt ($ch, CURLOPT_COOKIEJAR, $cookieDump);  // 存放Cookie信息的文件名称
    $content = curl_exec($ch);
    // 把抓取的网页由 GBK 转换成 UTF-8 
    $content = mb_convert_encoding($content,"UTF-8","GBK");
?>


<?php
    $url = 'http://tv.sohu.com';
    // 只要添加 compress.zlib 选项,即使服务器启用了gzip 压缩功能,就能够解码了
    $content = file_get_contents("compress.zlib://".$url);
    // 把抓取的网页由 GBK 转换成 UTF-8 
    $content = mb_convert_encoding($content,"UTF-8","GBK");

?>


2014年5月15日星期四

PHP 设置动态网页在浏览器的缓存


很多人可能不知道,动态网页在浏览器也是可以缓存的。下面就以 PHP 脚本为例子,阐述如何设置动态网页在浏览器缓存

<?php

//设置网页过期时间为1小时
$duetime = 3600*24*30;

//获取浏览器会向服务器传送 Last-Modified 报头
$modify_time =  $_SERVER['HTTP_IF_MODIFIED_SINCE'];

//当浏览器在设置时间之内再次访问该网页时,发送 HTTP 304 的状态码,这样就节省了传输数据量。
if(strtotime($modify_time) + $duetime > time())
{
header('HTTP/1.1 304');
exit(1);
}

header('Connection: keep-alive');
//设置网页 Last-Modified 报头
header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
//设置网页过期时间
header('Expires: '.gmdate('D, d M Y H:i:s',time()+$duetime).' GMT');
//执行缓存时间长,跟 Expires 有点类似,让我们可以更全面的控制网页过期时间,因为浏览器时间可能跟服务器时间不协调,用  Cache-Control 报头可以得到限制
header('Cache-Control: max-age='.$duetime);

//输出内容
……
?>

2014年5月8日星期四

普通用户 mysqldump 导出数据库出现错误的解决办法

今天用 mysql 的一个普通用户 admin 用 mysqldump 工具进行备份的时候,出现以下错误

mysqldump: Got error: 1044: Access denied for user 'admin'@'localhost' to database 'mydatabase' when using LOCK TABLES


后来查阅网上资料,终于得到解决办法。只需添加 --single-transaction 选项。

$ mysqldump --single-transaction -u admin -p mydatabase > mydatabase.sql

2014年4月21日星期一

Linux 下的软件管家 YUM

    yum 是透过分析 RPM 的标头资料后, 根据各软件的相关性制作出属性相依时的解决方案,然后可以自动处理软件的依赖属性问题,以解决软件安装或移除与升级的问题。

    举个形象的例子:你要安装 NetBeans 集成开发环境,你首先要 rpm 命令先安装 JDK ,然后才能够成功安装 NetBeans 。如果用 YUM 命令,系统会自动先帮你安装 JDK,再帮你安装 NetBeans 。

    注释:关于 RPM机制 参考这儿:http://woqilin.blogspot.com/2014/02/linux.html

    简单来说,它相当于360软件管家、腾讯电脑管家。不同的是,YUM 是通过命令行来管理的。

利用 yum 进行查询


[root@www ~]# yum [option] [查询工作项目] [相关参数]
选项与参数:
[option]:主要的选项,包括有:
  -y :当 yum 要等待使用者输入时,这个选项可以自动提供 yes 的回应;
  --installroot=/some/path :将该软件安装在 /some/path 而不使用预设路径
[查询工作项目] [相关参数]:这方面的参数有:
  search  :搜寻某个软件名称或者是描述 (description) 的重要关键字;
  list    :列出目前 yum 所管理的所有的软件名称与版本,有点类似 rpm -qa;
  info    :同上,不过有点类似 rpm -qai 的执行结果;
  provides:从文件去搜寻软件!类似 rpm -qf 的功能!

范例一:搜寻磁碟阵列 (raid) 相关的软件有哪些?
[root@www ~]# yum search raid
....(前面省略)....
mdadm.i386 : mdadm controls Linux md devices (software RAID arrays)
lvm2.i386 : Userland logical volume management tools
....(后面省略)....
# 在冒号 (:)  左边的是软件名称,右边的则是在 RPM 内的 name 设定 (软件名)
# 瞧!上面的结果,这不就是与 RAID 有关的软件吗?如果想了解 mdadm 的软件内容呢?

范例二:找出 mdadm 这个软件的功能为何
[root@www ~]# yum info mdadm
Installed Packages      <==这说明该软件是已经安装的了
Name   : mdadm          <==这个软件的名称
Arch   : i386           <==这个软件的编译架构
Version: 2.6.4          <==此软件的版本
Release: 1.el5          <==释出的版本
Size   : 1.7 M          <==此软件的文件总容量
Repo   : installed      <==容器回报说已安装的
Summary: mdadm controls Linux md devices (software RAID arrays)
Description:            <==看到否?这就是 rpm -qi 
mdadm is used to create, manage, and monitor Linux MD (software RAID)
devices.  As such, it provides similar functionality to the raidtools
package.  However, mdadm is a single program, and it can perform
almost all functions without a configuration file, though a configuration
file can be used to help with some common tasks.


范例三:列出 yum 服务器上面提供的所有软件名称
[root@www ~]# yum list
Installed Packages <==已安装软件
Deployment_Guide-en-US.noarch            5.2-9.el5.centos       installed
Deployment_Guide-zh-CN.noarch            5.2-9.el5.centos       installed
Deployment_Guide-zh-TW.noarch            5.2-9.el5.centos       installed
....(中间省略)....
Available Packages <==还可以安装的其他软件
Cluster_Administration-as-IN.noarch      5.2-1.el5.centos       base
Cluster_Administration-bn-IN.noarch      5.2-1.el5.centos       base
....(底下省略)....
# 上面提供的意义为:『 软件名称   版本   在那个容器内 』

范例四:列出目前服务器上可供本机进行升级的软件有哪些?
[root@www ~]# yum list updates  
Updated Packages
Deployment_Guide-en-US.noarch            5.2-11.el5.centos      base
Deployment_Guide-zh-CN.noarch            5.2-11.el5.centos      base
Deployment_Guide-zh-TW.noarch            5.2-11.el5.centos      base
....(底下省略)....
# 上面就列出在那个容器内可以提供升级的软件与版本!

范例五:列出提供 passwd 这个文件的软件有哪些
[root@www ~]# yum provides passwd
passwd.i386 : The passwd utility for setting/changing passwords using PAM
passwd.i386 : The passwd utility for setting/changing passwords using PAM
# 找到!就是上面的这个软件提供了 passwd 这个程序!


上一篇:Linux 的软件管理器