24 / 02 / 2017 buling

先执行 yum list installed|grep php查看安装的php
然后执行 rpm -e php-common.x86_64 删除掉所有php包
添加 最新的源:rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
再安装php:yum install –enablerepo=remi –enablerepo=remi-php56 php php-cli php-common php-devel php-fpm php-gd php-imap php-ldap php-mbstring php-mcrypt php-pecl-apc php-mysqlnd php-mysql php-odbc php-pdo php-gd php-mcrypt php-pear php-pecl-igbinary php-xml php-xmlrpc

但是重启/etc/init.d/php-fpm start时一直 ……….. failed
查看错误日志也正常,但就是一直卡住,然后检查/etc/init.d/php-fpm中pid配置和/etc/php-fpm.conf中的pid配置不一致导致,最终解决
但是nginx一直502,查看错误,[error] 29130#0: *5 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: 103.1.19.9, server: xx.com, request: “GET / HTTP/1.1″, upstream: “fastcgi://127.0.0.1:9000″
但php-fpm没有错误日志,执行php-fpm -t /etc/php-fpm.conf 也正常,需要配置/etc/php-fpm.d/www.conf 中 catch_workers_output=yes
再看错误日志:
WARNING: [pool www] child 29310 said into stderr: “ERROR: Unable to set php_value ‘soap.wsdl_cache_dir'”
不知道什么错误,解决办法,安装 php-soap
再看错误:WARNING: [pool www] child 29362 said into stderr: “ERROR: Connection disallowed: IP address ‘10.15.205.11’ has been dropped.”
解决办法,在/etc/php-fpm.d/www.conf修改listen.allowed_clients = 127.0.0.1,10.15.205.11解决

09 / 05 / 2015 buling

最近开始看discuz论坛,二次开发,填坑行动开始

一、discuz论坛安装后默认不开始手机访问
安装了触屏风格代码,发现死活都不生效,后来跟代码,发现检查了配置,最后找到 【全局】->【手机版访问设置】->开启手机版。哎

二、discuz设置门户为首页,手机端不自动跳转到门户
在【界面】->【导航设置】中设置门户为默认首页,手机端访问始终跳转到论坛页面,跟代码,在source/class/discuz/discuz_application.php中_init_mobile方法,大概在768行左右,下面这行代码

1
if(strpos($this->var['setting']['domain']['defaultindex'], CURSCRIPT) !== false && CURSCRIPT != 'forum' && !$_GET['mod']) {

改为

1
if(strpos($this->var['setting']['domain']['defaultindex'], CURSCRIPT) === false && CURSCRIPT != 'forum' && !$_GET['mod']) {

对此我很难受

 早期造个对象,写了个php的rsa帮助类库,先看使用方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
$keys = RsaHelper::new_rsa_key();
 
//生成完key之后应该记录下key值,这里省略
$privkey = $keys['privkey'];
$pubkey  = $keys['pubkey'];
 
/* $privkey = '-----BEGIN PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKX0cHYmXyHhIx5/
k6GMneVKpUDsqP2PdKFGollWYCbxJUAHPsHsjILGI0ucGnC+VpfKVX6DEagoRBZv
tz+nnpcreVPtNbKMNzhukSY3Mt7Fo1rMaj0pbsaMom1noQjsKJlVgz6akP7RMm4W
zpnMvcDq/9PucfCQP1FGZTbg1hUxAgMBAAECgYBeGam/ROjChC9utrZWby6E+nuT
wd3c0QA4Bp49+/1Pd4NAuBr8yQ2vhXwz/lL7xOHC9ibeMqHLcPGSq0wEGx6P/XWM
0Ldpwu6cWv4qOdHdBDdqrO6mkyBljt4sq1WtTnkLgZ0cCTTeVnnFDmlc9Zr9oT5k
UezOEb55GziRD5XUxQJBANLx3kUjOFRyR1I/wZYHHJkcm8pSgpDe4b1G60orZa9J
nbUTM+cIvmNKzm99m9aIMvgjk/LBydpxV7W5YYDxHrcCQQDJZpcu5OPWNJ3TdrrK
KNa1lfUo5Vb0sCgpTueZdwngBr043XRTyJHqjziX/9Z19UWrE9Gz6U1Klpa7SBYo
O4NXAkEArsKRCahXJ6cRrXOClx/HMpY//0uCPjFYxa32ipkPgjwz+uswycw1px83
jah7ri1iRK99B9ZCu8XBC53MyL16WwJAISu+dsDILb2YyP1jImy7gEjkignL2p0w
4CzYxFPw0m8Jt1XyFOKR9doE7jP69I6jHNw0y7b/Peuzg8EJtTKoHQJBAITAjM7Q
QnIEgYHvw3gaQI8/6992Y0DSMaHt50peI6uJoMV+X9IcjY1eFUSOHV8nb0uI8xQ7
4SbU2yvLPTqUk50=
-----END PRIVATE KEY-----';
 
$pubkey = '-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCl9HB2Jl8h4SMef5OhjJ3lSqVA
7Kj9j3ShRqJZVmAm8SVABz7B7IyCxiNLnBpwvlaXylV+gxGoKEQWb7c/p56XK3lT
7TWyjDc4bpEmNzLexaNazGo9KW7GjKJtZ6EI7CiZVYM+mpD+0TJuFs6ZzL3A6v/T
7nHwkD9RRmU24NYVMQIDAQAB
-----END PUBLIC KEY-----'; */
 
//初始化rsaobject
RsaHelper::init($privkey, $pubkey);
 
//原文
$data = 'hello';
 
//私钥加密示例
$encode = RsaHelper::priv_encode($data);
$ret = RsaHelper::pub_decode($encode);
var_dump($ret);
 
//公钥加密示例
$encode = RsaHelper::pub_encode($data);
$ret = RsaHelper::priv_decode($encode);
var_dump($ret);

      类库源码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
class RsaHelper{
    private static $_privkey = '';
    private static $_pubkey = '';
    private static $_isbase64 = false;
 
    /**
     * 初始化key值
     * @param  string  $privkey  私钥
     * @param  string  $pubkey   公钥
     * @param  boolean $isbase64 是否base64编码
     * @return null
     */
    public static function init($privkey, $pubkey, $isbase64=false){
        self::$_privkey = $privkey;
        self::$_pubkey = $pubkey;
        self::$_isbase64 = $isbase64;
    }
 
    /**
     * 私钥加密
     * @param  string $data 原文
     * @return string       密文
     */
    public static function priv_encode($data){
        $outval = '';
        $res = openssl_pkey_get_private(self::$_privkey);
        openssl_private_encrypt($data, $outval, $res);
        if(self::$_isbase64){
            $outval = base64_encode($outval);
        }
        return $outval;
    }
 
    /**
     * 公钥解密
     * @param  string $data 密文
     * @return string       原文
     */
    public static function pub_decode($data){
        $outval = '';
        if(self::$_isbase64){
            $data = base64_decode($data);
        }
        $res = openssl_pkey_get_public(self::$_pubkey);
        openssl_public_decrypt($data, $outval, $res);
        return $outval;
    }
 
    /**
     * 公钥加密
     * @param  string $data 原文
     * @return string       密文
     */
    public static function pub_encode($data){
        $outval = '';
        $res = openssl_pkey_get_public(self::$_pubkey);
        openssl_public_encrypt($data, $outval, $res);
        if(self::$_isbase64){
            $outval = base64_encode($outval);
        }
        return $outval;
    }
 
    /**
     * 私钥解密
     * @param  string $data 密文
     * @return string       原文
     */
    public static function priv_decode($data){
        $outval = '';
        if(self::$_isbase64){
            $data = base64_decode($data);
        }
        $res = openssl_pkey_get_private(self::$_privkey);
        openssl_private_decrypt($data, $outval, $res);
        return $outval;
    }
 
    /**
     * 创建一组公钥私钥
     * @return array 公钥私钥数组
     */
    public static function new_rsa_key(){
        $res = openssl_pkey_new();
        openssl_pkey_export($res, $privkey);
        $d= openssl_pkey_get_details($res);
        $pubkey = $d['key'];
 
        return array(
            'privkey' => $privkey,
            'pubkey'  => $pubkey
        );
    }
}

      妈蛋,win平台下的php protobuf折腾死我了,又改成py了,所以,python版的rsa加密辅助类来了

View Code PYTHON
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
def new_keys():
    (bob_pub, bob_priv) = rsa.newkeys(1024)
    return {'pubkey':bob_pub.save_pkcs1(), 'privkey':bob_priv.save_pkcs1()}
 
class RsaHelper:
 
    def __init__(self, privkey, pubkey):
        self._privkey = privkey.decode('string-escape')
        self._pubkey = pubkey.decode('string-escape')
 
    def encode_priv(self, data):
        privkey = rsa.PrivateKey.load_pkcs1(self._privkey)
        crypto = rsa.encrypt(data, privkey)
        return crypto
 
    def decode_pub(self, data):
        pubkey = rsa.PublicKey.load_pkcs1(self._pubkey)
        msg = rsa.decrypt(data, pubkey)
        return msg
 
    def decode_priv(self, data):
        privkey = rsa.PrivateKey.load_pkcs1(self._privkey)
        msg = rsa.decrypt(data, privkey)
        return msg
 
    def encode_pub(self, data):
        pubkey = rsa.PublicKey.load_pkcs1(self._pubkey)
        crypto = rsa.encrypt(data, pubkey)
        return crypto
19 / 09 / 2014 buling

      发现wordpress慢是一个很大的问题,特开一博来总结优化的相关方法,介于我也是在优化中更新的,此文会长期更新。

一、优化博客中插件加载的js位置。

      很多插件在header中注册了js脚本,但希望脚本放在footer部分加载,如果修改插件可能会影响插件的升级,下面的方法来自于stackoverflow : How to put my javascript in the footer
【方法】把下面的代码添加到 主题中的functions.php中

1
2
3
4
5
6
remove_action('wp_head', 'wp_print_scripts');
remove_action('wp_head', 'wp_print_head_scripts', 9);
remove_action('wp_head', 'wp_enqueue_scripts', 1);
add_action('wp_footer', 'wp_print_scripts', 5);
add_action('wp_footer', 'wp_enqueue_scripts', 5);
add_action('wp_footer', 'wp_print_head_scripts', 5);

N、其它技巧

1、博客中投放了百度广告,延迟异步加载的方法:现在header中加一个全局变量

View Code JAVASCRIPT
1
var onLoadCalls = [];

再在小工具中或其它部分

View Code JAVASCRIPT
1
2
3
4
5
onLoadCalls.push(function(){
    loadScript("http://cpro.baidu.com/cpro/ui/c.js",function(){
         BAIDU_CLB_DUP2_fillSlotAsync('u432452', 'sidebar-ad'); //sidebar-ad为广告展示的div#id
    });
});

接下来在尾部的js代码中添加如下代码

View Code JAVASCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function loadScript(src, callback){
    var doc = document,
        body = doc.body,
        //创建一个新script来加载
        script = doc.createElement('script');
 
    script.type = 'text/javascript';
    script.src = src;
    script.onerror = script.onload = script.onreadystatechange = function(e){
        e = e || window.event;
        if(!script.readyState || /loaded|complete/.test(script.readyState) || e === 'error'){
            callback(src);
            script.onerror = script.onload = script.onreadystatechange = null;
        }
    };
    body.appendChild(script);
}
 
$(document).ready(function(){
    if(onLoadCalls && onLoadCalls.length){
        $.each(onLoadCalls, function(index, fn){
            fn.call(null, $);
        });
    }
});

上次有人说博客好丑,我仔细看了看,确实挺丑的/撇嘴。这一年来发现审美也有提高,很喜欢极简风格的事物,可是创造对我来说难度还是挺大,昨天中午搜了一下wordpress主题,知乎有:有哪些好看的极简的 WordPress 主题?,顶楼提供了自己博客,我看了一下,确实很漂亮,之前apple官网也用了类似线条来描述,但楼上不开源,唉,这….。

还好我们有微创新,其作用在于把别人好的东西抄过来发扬光大,这不,现在的主题(buling,姑且叫这个名字)出来了,这个主题是基于 chitose 更改过来的,基本没有原主题的特点了。

主题对不同屏做了适配,主要针对 大显示器/pad/手机浏览三种

目前主题设置包括如下几项:
1、影藏右边栏。隐藏掉也挺好看的
2、文章列表支持只显示N字长的摘要
3、页脚统计代码或备案信息等。

看到的表象就这么多了,主题由于是花昨天下班时间和今天中午午休时间赶出来的,所以肯定还有很多BUG,比如兼容性,我看了一下IE7还算正常,IE6就算了,我就不打算去支持了。so…现在还没有正式的主题供大家下载使用。

——————————–技术分割线—————————————
这也是第一次去学习wordpress主题开发,其中也涉及到很多api的使用,已经主题的一些设置配置信息,比如这篇文章:zh-cn:主题开发 这网站文章还是很不错,但访问速度实在是难受极了。

一、设置主题信息
在style.css中头部添加如下信息

1
2
3
4
5
6
7
8
/*
Theme Name: buling
Theme URI: http://www.mjix.com/archives/1417.html
Author: buling
Author URI: http://mjix.com
Description: 从chitose主题更改,铃不铃极简风格!
Version: 1.0
*/

二、设置主题预览图
截图screenshot.png放在主题根目录

三、设置主题相关信息
主题设置代码直接写在functions.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//设置主题相关信息
update_option('buling_key', $_POST[$opt]);
 
//获取主题相关设置
get_option('buling_key');
 
//注册侧边栏信息
register_sidebar(array(
    'name' => 'Topbar',
    'before_title' => '
<h3>',
    'after_title' =&gt; '</h3>
'
));
 
//include sidebar.php文件
get_template_part('sidebar');
 
//echo,第二个参数可以启用多语言支持
_e('some msg!');
 
//return some msg
__('some msg');

还有一堆the_xxx的api就不一一列举了,基本来说开发一套主题还是比较简单的,第一次可以拿一个现有主题来修改,很快就熟悉了。

30 / 10 / 2013 admin

      公司竟然还在用qee这N年没人维护的框架,所以就索性淘汰掉,在DB连接方面没有选择任何ORM框架,而是只提供了一个简单的mysql类库,好像这个sql是从emlog博客演变而来,我个人还是很喜欢用,但DB有个小问题,如有两个DB使用了不同权限的帐号进行操作时

1
2
3
4
5
6
7
//db1和db2的配置只是库不同,帐号密码一样
 $db1 = Db_Mysql::get_instance('db1');
 $sql = 'select * from xx where id=%d';
 $db1->query($sql, array(2));
 $db2 = Db_Mysql::get_instance('db2');
 $sql = 'select * from oo where id=%d';
 $db2->query($sql, array(2));

这样的代码会报错:db1.oo表不存在,之前也出现过,但实在解不了,所以就索性google了一下“php mutiple mysql connect”,然后答案就有了:
http://stackoverflow.com/questions/274892/how-do-you-connect-to-multiple-mysql-databases-on-a-single-webpage
他这么写到

//You can make multiple calls to mysql_connect(), but if the parameters are the same you need to pass true for the '$new_link' (fourth) parameter, otherwise the same connection is reused.
$dbh1 = mysql_connect($hostname, $username, $password);
$dbh2 = mysql_connect($hostname, $username, $password, true);

09 / 10 / 2013 admin

     之前说过现在的开发环境很差,做开发太难,几经周折无果后只能退而求其次在本地搭建了一个apache环境,凑合着用。所有的静态页面已经资源都访问本机,至少不影响开发,且多用ajax,运营支撑系统更是extjs开发,数据全是来自ajax,再本地搭建完成后配置的域与正是环境不一样,是为了方便开发,不再正式本地之间来回切换,如,线上是 xxx.qq.com,本地为vartu.qq.com来访问,只要不跨主域名还是没有问题,但是遇到一个问题,很多用了ajax请求,那么就跨域了,所以在apache做了一个rewrite,以前没发现rewrite竟然可以跨域,下面来说实现

     1、打开apache安装目录下面的conf/httpd.conf,去除下面配置前的“;”
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule rewrite_module modules/mod_rewrite.so

     2、修改站点配置信息如下

<VirtualHost *:80>
ServerAdmin webmaster@dummy-host.x
DocumentRoot "F:\AppServ\www\softadmin\public"
ServerName game.oa.com
ErrorLog "logs/dummy-host.x-error.log"
CustomLog "logs/dummy-host.x-access.log" common
RewriteEngine on
RewriteRule ^/index\.php(.*)$ http://xxx.qq.com/index.php$1 [L,R=301,P,NC]
</VirtualHost>

     3、如果有登录态,即是需要带cookie的情况下,可以修改vartu.qq.com的cookie信息为一个登录过的cookie即可,rewrite也支持发送cookie,如“^/index\.php(.*)$ http://xxx.qq.com/index.php$1 [L,R=301,P,NC,CO=PHPSESSID:sadf2323423sdfd:.qq.com:/:1440]”

更多rewrite的规则可以访问 http://httpd.apache.org/docs/current/rewrite/flags.html

08 / 05 / 2013 admin

不得不说dewen的验证码问题太有水准了,(http://www.dewen.org/account/reg)今天做了几个都错了,先说js这位吧

View Code JAVASCRIPT
1
2
3
4
var tmp = 'a';
if([] == false) tmp += 'b'; //类型不同转字符串比较
if(![]) tmp += 'c'; //这个[]是真
alert(tmp) //返回 ab

接下来看php这位

1
2
3
4
5
6
$a=3; $b=5;
if($a=5 || $b=7){
    $a++;
    $b++;
}
echo $a.'_'.$b; //输出是1_6,因为true++还是true
无标签信息 0 条
01 / 05 / 2013 admin

      在win7下的python中发现是gbk,出现utf8文字时乱码,设置命令提示符为utf8的方法:

1. 命令行里面输入 chcp 65001
2. 然后点击标题栏【属性】->【字体】为 Lucida Console
3. 设置chcp 936 可以转换为中文gbk

      在mysql下重置一个auto_increment字段的方法:

ALTER TABLE tablename AUTO_INCREMENT = 1

       shell下的sed不支持非贪婪模式,而且如果出现中文,不匹配时,可以使用 export LANG=C; 在tail -f和sed一起使用时不处理的问题,重现一下问题( http://stackoverflow.com/questions/8103385/log-parsing-with-sed-or-grep )
tail -f xxx.log|grep server|sed 's/\"//g' #这是执行的,server的log很频繁
tail -f xxx.log|grep mqsend|sed 's/\"//g' #mqsend的日志很少,不执行

       还是没有解决,参考:http://www.perkin.org.uk/posts/how-to-fix-stdio-buffering.html

       mysql中datetime精确到毫秒,用了varchar来存储,例如 2013-05-02 14:52:38,412,可以用下面的语句计算两个时间差
select f_sendtime, f_endtime, (UNIX_TIMESTAMP(STR_TO_DATE(left(f_endtime,19),'%Y-%m-%d %H:%i:%s'))+cast(right(f_endtime, 3)*0.001 as decimal(18,2)))-(UNIX_TIMESTAMP(STR_TO_DATE(left(f_sendtime,19),'%Y-%m-%d %H:%i:%s'))+cast(right(f_sendtime, 3)*0.001 as decimal(18,2))) f_totaltime from xxx;

无标签信息 0 条
19 / 04 / 2013 admin

      终于有机会写c++了,虽然现在还是摸着石头过河,但是能过河说明就再实践了,之前写了,python、java对c++的调用,和c++的动态链接库的创建,终于轮到写php对c++的调用了,这里不是单纯的helloworld,而是在ace基础上封装类,本文主要说c++开发php扩展的基本方法和php扩展类的创建方法,已经如何引用第三方库。

      因为php官方提供的示例是以c开发为基础,所以相对c++开发的资料还是有点难找,下面进入正题

一、c++扩展开发步骤

1、down一份php的源码,如我的php是5.3.3,我就down了一份php5.3.3的源码
2、解压进入ext目录下,执行:./ext_skel –extname=AceClient。我建的是一个名为aceclient的模块
3、按照提示应该是修改 config.m4,因为是c++所以需要这样

//1、找到以下三句类似代码去除前面的dnl(注释符)
PHP_ARG_WITH(AceClient, for AceClient support,
Make sure that the comment is aligned:
[ --with-AceClient Include AceClient support])
//2、在if test "$PHP_ACECLIENT" != "no"; then这句判断内加入如下代码
PHP_REQUIRE_CXX() #告诉它用c++来编译
PHP_ADD_LIBRARY(stdc++, "", EXTRA_LDFLAGS)
EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lACE" #需要引入的第三方模块ACE
CPPFILE="AceClient.cpp ace_client.cpp" #需要编译的cpp文件集合
PHP_NEW_EXTENSION(AceClient, $CPPFILE, $ext_shared)

2、更改php_AceClient.h,找到#ifdef ZTS,#include “TSRM.h”,#endif这三句前后加代码

1
2
3
4
5
6
//兼容c代码
extern "C" {
#ifdef ZTS
#include "TSRM.h"
#endif
}

3、把AceClient.c为AceClient.cpp,同样AceClient.cpp中找到#ifdef HAVE_CONFIG_H—#include “ext/standard/info.h”前后加代码

1
2
3
4
5
6
7
8
9
extern "C" {
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
 
#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
}

到此,php扩展需要兼容c的代码部分就修改完了

二、c++扩展类开发示例

下面先看需要实现的结果

1
2
3
4
5
6
7
8
//$b = get_loaded_extensions(); //可以查看扩展是否加载成功
//var_dump($b);
$a = new AceClient("127.0.0.1", 50050, 200);
var_dump($a);
$ret = $a->send("铃不铃不铃");
var_dump("send:".$ret);
$ret = $a->receive();
var_dump("receive:".$ret);

目前php的官方示例代码是都是提供了函数的开发,所以函数的开发略过,直接讲解类的开发过程,http://devzone.zend.com/1435/wrapping-c-classes-in-a-php-extension/ 这是zend官方的一篇类开发说明文,有点长,抽离了一下主要的部分讲解

1、加载一些需要的文件

1
2
#include "php_AceClient.h" //这个是本来就存在的,闲杂不需要放在extern "C"中了
#include "ace_client.h" //这个是业务类代码,目的是为了个语言统一

2、加入我们的业务代码,即新建类,基本是模板,直接改就行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
/****************************extension class***************************/
zend_class_entry *ace_ce;
zend_object_handlers ace_object_handlers;
 
struct ace_object { //声明个结构体存储业务代码的ace instance对象
    zend_object std;
    Esun_Ace_Client *ace_ins;
};
 
//创建php的构造函数
PHP_METHOD(Esun_Ace_Client, __construct){
    long port, timeout;
    char *ip; int ip_len;
    Esun_Ace_Client *ecli = NULL;
    zval *object = getThis();
 
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sll", &ip, &ip_len, &port, &timeout) == FAILURE) {
        RETURN_NULL();
    }
 
    ecli = new Esun_Ace_Client(ip, (int)port);
    ace_object *obj = (ace_object *)zend_object_store_get_object(object TSRMLS_CC);
    obj->ace_ins = ecli;
}
 
//创建ace发送方法
PHP_METHOD(Esun_Ace_Client, send){
    char *data; int data_len, ret = -1; 
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len) == FAILURE) {
        RETURN_NULL();
    }
 
    Esun_Ace_Client *ecli = NULL;
    ace_object *obj = (ace_object *)zend_object_store_get_object(
        getThis() TSRMLS_CC);
    ecli = obj->ace_ins;
    if (ecli != NULL) {
        ret = ecli->send_data(data);
    }
 
    RETURN_LONG(ret);
}
 
//创建php的接收方法
PHP_METHOD(Esun_Ace_Client, receive){
    char *data;
    Esun_Ace_Client *ecli = NULL;
    ace_object *obj = (ace_object *)zend_object_store_get_object(
        getThis() TSRMLS_CC);
    ecli = obj->ace_ins;
    if (ecli != NULL) {
        data = ecli->receive_data();
    }else{
        RETURN_NULL();
    }
    RETURN_STRING(data, strlen(data));
}
 
//说明php类存在的几个方法
function_entry ace_methods[] = {
    PHP_ME(Esun_Ace_Client,              __construct,  NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
    PHP_ME(Esun_Ace_Client,              send,         NULL, ZEND_ACC_PUBLIC)
    PHP_ME(Esun_Ace_Client,              receive,      NULL, ZEND_ACC_PUBLIC)
    {NULL, NULL, NULL}
};
 
//这基本是模板函数,拷贝,替换一下相关值就行了
void ace_free_storage(void *object TSRMLS_DC){
    ace_object *obj = (ace_object *)object;
    delete obj->ace_ins; 
 
    zend_hash_destroy(obj->std.properties);
    FREE_HASHTABLE(obj->std.properties);
 
    efree(obj);
}
 
//一样的模板函数,拷贝,用于创建类对象保存
zend_object_value ace_create_handler(zend_class_entry *type TSRMLS_DC){
    zval *tmp;
    zend_object_value retval;
 
    ace_object *obj = (ace_object *)emalloc(sizeof(ace_object));
    memset(obj, 0, sizeof(ace_object));
    obj->std.ce = type;
 
    ALLOC_HASHTABLE(obj->std.properties);
    zend_hash_init(obj->std.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
    zend_hash_copy(obj->std.properties, &type->default_properties,
        (copy_ctor_func_t)zval_add_ref, (void *)&tmp, sizeof(zval *));
 
    retval.handle = zend_objects_store_put(obj, NULL,
        ace_free_storage, NULL TSRMLS_CC);
    retval.handlers = &ace_object_handlers;
 
    return retval;
}
/****************************************************************/

3、业务代码就完了,现在只剩下通知PHP_MINIT_FUNCTION(模块初始化需要处理的方法)

1
2
3
4
5
6
7
8
9
10
11
12
13
PHP_MINIT_FUNCTION(AceClient)
{
    zend_class_entry ce;
    INIT_CLASS_ENTRY(ce, "AceClient", ace_methods); //注册php类并注册相关方法
    ace_ce = zend_register_internal_class(&ce TSRMLS_CC);
    ace_ce->create_object = ace_create_handler;
    memcpy(&ace_object_handlers,
    zend_get_std_object_handlers(), sizeof(zend_object_handlers));
 
    ace_object_handlers.clone_obj = NULL;
 
    return SUCCESS;
}

一、编译php的扩展模块AceClient

如果上面就操作完了,接下来的动作就简单多了
1、初始化一下模块的环境,执行 phpize。
2、配置,./configure
3、编译,make
4、如果没有问题的情况下,modules下面应该会出现一个 AceClient.so 模块
5、在php.ini中加载,为了尽可能不改php.ini,所以就加载php.d目录下,vi AceClient.ini;添加:extension=/home/xxx/php-5.3.3/ext/AceClient/modules/AceClient.so
6、重启一下apache,注意看看错误日志,如我出现libACE.so.6.1.7: cannot open shared object file,这是因为第三方库libACE模块在/usr/local/lib下面,所以我就软连了一份到/usr/lib64下面。还有一个错误出现了Backtrace: zend_objects_store_del_ref_by_handle,原来是我在接收port值时忘了加&
7、大功告成,乐你的吧