手机浏览 RSS 2.0 订阅 膘叔的简单人生 , 腾讯云RDS购买 | 超便宜的Vultr , 注册 | 登陆
浏览模式: 标准 | 列表全部文章

MD,又被长宽劫持了

啥也不说,就上一张图。。。。

大小: 181.31 K
尺寸: 500 x 360
浏览: 1451 次
点击打开新窗口浏览全图

心都碎了

Tags: 长宽

关于SOAP的几篇文章

PHP操作soap我总觉得是一件非常痛苦的事情,但没有办法,现在很多功能都是基于WebService的,比如那个amazon的,但其实很多公司都也还是提供了restful之类的接口,使得PHP与其他系统的数据交换比较方便。但让人痛苦的,有时候,你PHP不得不充当soapServer,这时候,怎么做呢?zendstudio可以根据你的函数和类,帮你生成wsdl,但大多数情况下,你没有直接生成的手段,怎么办?官方的soapServer功能也太少了一点。你是否还准备用nuSoap来充当server呢?

搜集了一些资料,用来方便的协助你生成soap接口。如果只是自己的内部调用,可以尝试用phprpc或者它的升级版hprose进行尝试。

1、利用NuSOAP发布wsdl。这是PHP5之前的做法了,因为在PHP5之后,直接有soap库支持,如何发布wsdl,请看:http://hi.baidu.com/arlon/blog/item/d8267d1e6ca4adf01ad576cc.html,然而这个网址打开是白屏的,内容可以稍看这里:

PHP代码
  1. 2.4.1 创建支持 WSDL 的 WEB 服务  
  2. 为了实现 WEB 服务程序对 WSDL 的支持,需要使用 soap_server 的 configureWSDL 方法,并且在调用 soap_server 的 register 方法注册 WEB 服务程序时,需要提供更详细的参数。看下面的代码,代码的文件名是 “/nusoap/nusoap_server3.php”。  
  3.   
  4. <?php  
  5. require_once("lib/nusoap.php");  
  6.   
  7. function concatenate($str1,$str2) {  
  8.       if (is_string($str1) && is_string($str2))  
  9.           return $str1 . $str2;  
  10.       else  
  11.           return new soap_fault(' 客户端 ','','concatenate 函数的参数应该是两个字符串 ');  
  12. }  
  13.   
  14. $soap = new soap_server;  
  15. $soap->configureWSDL('concatenate'); // 初始化对 WSDL 的支持  
  16.   
  17. // 注册服务  
  18. $soap->register('concatenate',  
  19. array("str1"=>"xsd:string","str2"=>"xsd:string"), // 输入参数的定义  
  20. array("return"=>"xsd:string"// 返回参数的定义  
  21. );  
  22.   
  23. $HTTP_RAW_POST_DATA = isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : '';  
  24. $soap->service($HTTP_RAW_POST_DATA);  
  25. ?>  
  26. 现在打开浏览器,访问刚才建立的文件,http://127.0.0.1/nusoap/nusoap_server3.php,结果如下:   
  27.   
  28. concatenate  
  29. View the WSDL for the service. Click on an operation name to view it's details.  
  30.   
  31. concatenate   
  32. 点击函数名称concatenate,可以看到对函数的描述。点击"WSDL",或者访问WEB服务文件,并在后面加上查询字符串"?wsdl"(http://127.0.0.1/nusoap/nusoap_server3.php?wsdl),可以得到WEB服务的WSDL内容。  
  33.   
  34. 2.4.2 通过 WSDL 调用 WEB 服务  
  35. 通过 WSDL 调用 WEB 服务,与不通过 WSDL 调用 WEB 服务,程序的结构大体相同。区别在于,通过 WSDL 调用 WEB 服务,初始化 soapclient 类时,传入两个参数到 soapclient 的构造函数,第一个参数是 WSDL 文件的地址,第二个参数指定是否使用 WSDL ,指定为 true 即可。看下面的代码,代码的文件名是 “ /nusoap/nusoap_client3.php ”  
  36.   
  37. <?php  
  38. require_once("lib/nusoap.php");  
  39.   
  40. $client = new soapclient('http://127.0.0.1/nusoap/nusoap_server3.php?wsdl',true);  
  41. $parameters=array(' 字符串 1',' 字符串 2');  
  42.   
  43. $str=$client->call('concatenate',$parameters);  
  44. if (!$err=$client->getError()) {  
  45.       echo " 程序返回 :",$str;  
  46. else {  
  47.       echo " 错误 :",$err;  
  48. }  
  49. ?>  
  50. 2.4.3 代理的使用  
  51. NuSOAP 提供代理的方法调用远程 WEB 服务。这种方法,在客户端程序里面创建一个远程服务的代理对象,通过代理直接调用远程的 WEB 服务,而不需要通过 soalclient 类的 call 方法。看下面的代码。  
  52.   
  53. <?php  
  54. require_once("lib/nusoap.php");  
  55.   
  56. $client = new soapclient('http://127.0.0.1/nusoap/nusoap_server3.php?wsdl',true);  
  57. $proxy=$client -> getProxy(); // 创建代理对象 (soap_proxy 类 )  
  58.   
  59. $str=$proxy->concatenate(" 参数 1"," 参数 2"); // 直接调用 WEB 服务  
  60. if (!$err=$proxy->getError()) {   
  61.       echo " 程序返回 :",$str;  
  62. else {  
  63.       echo " 错误 :",$err;  
  64. }  
  65. ?>  

 

2、利用PHP5自带的soapServer,在手册上,关于如何创建,写了很多例子,就象:

PHP代码
  1. <?php  
  2. $server = new SoapServer("some.wsdl");  
  3. $server = new SoapServer("some.wsdl"array('soap_version' => SOAP_1_2));  
  4. $server = new SoapServer("some.wsdl"array('actor' => "http://example.org/ts-tests/C"));  
  5. $server = new SoapServer("some.wsdl"array('encoding'=>'ISO-8859-1'));  
  6. $server = new SoapServer(null, array('uri' => "http://test-uri/"));  
  7.   
  8. class MyBook {  
  9.     public $title;  
  10.     public $author;  
  11. }  
  12.   
  13. $server = new SoapServer("books.wsdl"array('classmap' => array('book' => "MyBook")));  
  14. ?>   

 

反正,我是觉得很痛苦,不过所幸现在的IDE都支持了直接发布wsdl文件,netbeans可以,zendstudio也可以。所以,也就方便了开发

3、利用开源组件,比如:webservice helper,http://www.jool.nl/new/1,webservice_helper.html,虽然它也是其于soapServer,但是集成的一些代码可以让你少走很多弯路。

比如,它默认就自带了一个contactManager的发布,具体的一些配置,可以看config.php,当然你也可以参考它的一些类,也充实你自己的类库(本来官网有教程的,可能是因为时间太久远了,该教程已经跳到ipublisher的教程上去了)

4、利用框架实现webService。在这里,估计又有很多分支了,比如zend framework,比如xxx和xxxx等,我由于最近在用yii,所以就看了yii的一个小小的实现

介绍页在这里:http://www.yiiframework.com/doc/guide/1.0/zh_cn/topics.webservice

看它的实现是非常简单,在Controller里增加一个转换wsdl的Action,然后,在要提供的方法上面用phpdoc来进行注释。定义传入参数的数据类型等

  • str/string: 对应 xsd:string;
  • int/integer: 对应 xsd:int;
  • float/double: 对应 xsd:float;
  • bool/boolean: 对应 xsd:boolean;
  • date: 对应 xsd:date;
  • time: 对应 xsd:time;
  • datetime: 对应 xsd:dateTime;
  • array: 对应 xsd:string;
  • object: 对应 xsd:struct;
  • mixed: 对应 xsd:anyType.

不过我也确实没有过多的细看,没仔细看它对于AUTH验证支持怎么样(第三点里介绍的工具是有验证的,而且就设在config.php里,非常方便)

好了,我就针对现在的soap server的建立,介绍了四种方法,事实上,我到现在为止是一种都没有用过,nusoap也就用过客户端,那也是几年前的事情了,soapClient也是,在构建soapHeader的时候也走过很多弯路。第三步介绍的工具,我也只是下载了看看源码,第四步我是看了看手册。只是先集中一下,以后总会用到而已。
虽然说,PHPRPC和hprose 在andot他们介绍来说,开发速度和处理上,都有较为明显的提高,但如果想做一个公用的web service,那还是用大家都能接受的方法吧。
如果是自己的项目,那可能就会用phprpc或者hprose来了。hprose测试版用过,感觉还是不错的。phprpc,我也做了一个sae平台的移植版,目前也能够正常的使用。。在这里也有个简单的测试:http://nsblog.sinaapp.com/。有兴趣的朋友也可以去看看的。

Tags: soap, webservice, phprpc, hprose, restful

关于oauth的几篇文章

本文只是一个收集的链接,关于oauth,可以去看一下wiki百科,对于PHP的oauth支持,可以看一下手册
国内很早就有不少网站支持oauth,只是更多的网站都没有做出此类开放的功能。不过,疯狂的时候来的总是那么突然(这让我想起在单位的年夜饭上,刚吃了一小时,突然副总说了一句,快乐的时光总是短暂的)。国内对Oauth的支持也就突然间的多了起来,可能,最让人记的清楚的还是新浪。但当时关于oauth的文章还不是特别多,只是在QQ开放oauth后,突然间文章就多了很多,理由是,QQ所支持的oauth协议居然是非标的。。。。

好吧,让我们看看其他人是怎么说的:

1、使用QOAuth来进行新浪/腾讯微博验证(一)

2、老王的:基于PECL OAuth打造微博应用

3、android下的:android开发我的新浪微博客户端-OAuth篇(2.1)

4、腾讯微博开放平台的PECL的OAuth封装

5、腾讯微博开放平台练手:微博擂台

6、使用 PECL 的 OAuth 库访问 QQ 微博 API

其中4、5、6都是mikespook写的,他说,QQ 微博的API里有点重要的事情,并列出来了。看例子:

PHP代码
  1. <?php  
  2. include('define.php');  
  3. try {  
  4.     $oauth = new OAuth(OAUTH_KEY, OAUTH_SECRET, OAUTH_SIG_METHOD_HMACSHA1, OAUTH_AUTH_TYPE_URI);  
  5.     $oauth->enableDebug();  
  6.     // 很重要!!!在 OAuth 标准里是没有规定 nonce 的长度的,但是 QQ 对 nonce 的长度做了要求——32 字节长。如果不设置一下,会返回 400 错误。我为此纠结了一天。  
  7.     $oauth->setNonce(md5(rand()));  
  8.     // CALLBACK 一定要设置,OAuth 扩展的文档上是没设置的,但是 QQ 这里不设会报错  
  9.     $requestTokenInfo = $oauth->getRequestToken(REQUEST_TOKEN, CALLBACK);  
  10.     $_SESSION['oauth_token_secret'] = $requestTokenInfo['oauth_token_secret'];  
  11.     // header("Location: ……") 亦可  
  12.     echo "<p><a href='" . AUTHORIZE . "?oauth_token=" . $requestTokenInfo['oauth_token'] . "'>authorize</a></p>";  
  13. } catch (OAuthException $e) {  
  14.     var_dump($e);  
  15. }  
  16.   
  17. callback.php  
  18.   
  19. <?php  
  20. include('define.php');  
  21. try {  
  22.     $oauth = new OAuth(OAUTH_KEY, OAUTH_SECRET, OAUTH_SIG_METHOD_HMACSHA1, OAUTH_AUTH_TYPE_URI);  
  23.     $oauth->enableDebug();  
  24.     // 很重要!!!如果不设置一下,会返回 401 错误。  
  25.     $oauth->setNonce(md5(rand()));  
  26.     $oauth->setToken($_GET['oauth_token'], $_SESSION['oauth_token_secret']);  
  27.     $accessTokenInfo = $oauth->getAccessToken(ACCESS_TOKEN, null, $_GET['oauth_verifier']);  
  28.     $_SESSION['access_token'] = $accessTokenInfo['oauth_token'];  
  29.     $_SESSION['access_secret'] = $accessTokenInfo['oauth_token_secret'];  
  30.     header('Location: room.php');  
  31. } catch (OAuthException $e) {  
  32.     var_dump($e);  
  33. }  
7、这是针对新浪微博的OAuth协议分析一

 

8、对新浪微博的OAUTH开发,居然还有一个总结:新浪微博OAuth认证总结

9、又是老王发的牢骚:OAuth那些事儿

好吧,就先列出这么多,真要查出oauth之类的东西,google随便一下就有很多,我贴出来的地址,都是我订阅的一些RSS的地址,也算是做一个集中罢了。

 

Tags: php, qq, sina, oauth, pecl

转:jQuery1.5的改进细节

jQuery 1.5beta出来了?看到这篇博客的时候,我很惊讶,1.4开始,jQuery的更新速度就越来越快了。现在,居然1.5beta都同来了。文中说了,ajax完全重写,但没介绍,不过对于使用者来说,这些都无需关心,或者应该开心才是,因为它带来了更多的兼容性,说不定速度也更快了。(猜测而已,最近实在没时间 看这些代码)

下面是原文:

jQuery 1.5 beta1出来了,从学习跟进上来说,这一次已经比较晚了(我竟然不知道1.5什么时候出的alpha,就这么beta了)。

这个1.5版本最大的更新是AJAX的完全重写,提供了更强的可扩展性。但是受制于精力和篇幅,对新的AJAX的分析还是放到下回,本篇先简单介绍一下细节方面的改进。

jQuery._Deferred和jQuery.Deferred

首先不得不说这两个新生事物,因为他们是作为基础设施存在,不把这两个东西讲明白了,有些问题根本没办法解释。

首先,jQuery.Deferred是jQuery._Deferred的增强版,因此对于这个问题,从jQuery._Deferred入手,就能说明一大半的问题。

什么是Deferred?从字面上看,我的第一反应是“延迟加载”,首字母大写的应该是“类型”的定义,所以这大概是一个“透明提供延迟加载功能”的类型吧。然而实际上,虽然确实带有那么一点点“延迟”的意思,这个东西却不是用来实现延迟加载的。

简单来说,jQuery._Deferred是一个函数队列,他的作用有以下几点:

  • 保存若干个函数。
  • 在特定的时刻把保存着的函数全部执行掉。
  • 执行过后,新进来的函数会立刻执行。

感觉是不是和啥东西很像?对,jQuery的ready函数就是这样的逻辑,实际中jQuery 1.5中的ready函数也确实被嫁接到这上面去了。

jQuery._Deferred提供下面的接口:

  • done:function(fn1, fn2, ...)的形式,用于把函数添加到队列中。
  • fire:function(context, args)的形式,使用context指定this对象,args指定参数,调用队列中所有函数。fire被调用后,_Deferred会进入 isResolved状态,未来对done的调用不会再保存函数,而是直接调用函数。
  • resolve:相当于调用fire(this, arguments),一个简化的方法。
  • isResolved:用来判断_Deferred是否在isResolved状态,具体参考前面的fire函数的解释。
  • cancel:取消掉整个队列,这样不管未来是不是fire,队列中的函数都不会再被调用。

说明白了jQuery._Deferred,再来看看jQuery.Deferred。这个东西其实就是2个_Deferred组成的,第一个称为 deferred,用于保管“正常”状态下的函数;第二个称为failDeferred,用于保管“出错”状态下的函数。同时 jQuery.Deferred提供了一些新的接口:

  • then:function(done, fail)的形式,把done添加进deferred,把fail添加进failedDeferred。
  • fail:相当于failDeferred的done函数。
  • fireReject:相当于failDeferred的fire函数。
  • reject:相当于failDeferred的resolve函数。
  • isRejected:相当于failDeferred的isResolved函数。

同时jQuery.Deferred取消了cancel函数。

那么这个是啥用的呢?有“正常”和“出错”2个状态,同时又是异步的,很容易就能想到……对,给AJAX用的,在下一篇分析中再详细说明。

jQuery.ready的变化

因为有了jQuery._Deferred这个东西,jQuery.ready函数变成依赖于函数队列,具体的变化有:

原来的readyList变量已经不再是一个数组,而变成了jQuery._Deferred对象。

原本在DOMContentLoaded时,调用readList中所有函数的逻辑,现在也使用了jQuery._Deferred中,原来的代码:

while ( (fn = ready[ i++ ]) ) {
fn.call( document, jQuery );
}

变成了:

readyList.fire( document , [ jQuery ] );

jQuery.parseXML函数

新增了静态函数jQuery.parseXML,用于提供浏览器兼容的从字符串转为XML文档的功能。

该函数的逻辑网上有很多,jQuery也没有特别的地方,大致分为以下2种:

  • 对于标准浏览器,使用DOMParser对象:

    var parser = new DOMParser();
    var xml = parser.parseFromString(text, 'text/html');
  • 对于IE,使用Microsoft.XMLDOM对象:

    var parser = new ActiveXObject('Microsoft.XMLDOM');
    parser.async = 'false';
    parser.loadXML(text);
    var xml = parser.documentElement;

data部分

添加了jQuery.hasData函数,用于判断一个元素是否有jQuery附加上去的数据。

修改了jQuery.expando的实现,在原来单纯地取当前时间的基础上,添加了一个随机数:

expando = "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" );

这样保证在同一时间,引入多个jQuery副本,这几个副本之间的expando不会相互冲突,导致元素上的data变得错乱。一般来说,是不会引入多个jQuery副本的,但是使用SealJS等的时候,配置不当的话,也是很容易出现此类问题的。

DOM操作部分

原本的hasClass、addClass、removeClass函数都需要将元素的class属性分隔为数组,在1.4.4版本中,通过\n或\t进行分隔,在1.5中增加了一个\r,用于对应Windows平台下的换行符(\r\n)。

jQuery.fn.attr函数,1.4.4版本中拒绝从TextNode和CommentNode上获取属性,在1.5版本中添加了一个AttributeNode(noteType == 2)。

在1.4.4版本中,jQuery会在页面unload的时候清理掉由jQuery维护的所有DOM事件,这是为了避免IE的内存泄露问题。但是在1.5中这一段代码不见了,不知是出于什么考虑。

对于IE下使用cloneNode复制节点,会将事件也一起复制过来的问题,1.4.4中是采取复制innerHTML的方式给予解决,而在1.5中则采纳了mootools团队提供的方法,使用cloneFixAttribute函数修正该问题。

cloneFixAttribute函数们于jQuery 1.5 beta1源码文件的5388-5438行,处理IE的BUG的原理很简单,当然前端里一些看似简单的东西,都是很难发现的:

  1. IE中有个叫clearAttributes的函数,会清除到节点上的所有属性,顺便把和事件相关的onclick之类的属性也去掉了。在复制出来的节点上调用这个函数,就会把属性清得干干净净。
  2. IE中还有一个叫mergeAttributes的函数,把一个节点的属性复制到另一个节点上,但他不会把和事件相关的属性复制过去。所以再把原始节点调用mergeAttributes,把属性重新放回复制出来的节点上,这就相当于起到了去除事件相关属性的作用。

另外cloneFixAttribute函数还处理了非常多IE6-8在cloneNode上的兼容性问题,非常值得详细研究。

AJAX部分

AJAX已经完全重写了,只留下一点边边角角保留着1.4.4版本的风采,这里只抽取一部分进行简单的说明。

原来版本中$.get和$.post的实现非常相似,具体来说仅有一个method配置项不同,因此在1.5版本中被合并起来了:

$.each(['get', 'post'], function(i, method) {
$[method] = function() { ... };
});

ajaxSetup函数现在加了一行return this;,可以链式调用了。

serializeArray函数现在统一将value中的换行符替换成Windows的风格(\r\n)。

AJAX的回调函数中,作为参数的对象不再是原生的XMLHTTPRequest,而是jQuery自己封装的称为jXHR的对象,这个对象提供了XMLHTTPRequest的常用接口。

原本对于“请求成功”的浏览器状态码,除200-299以及304外,还有一个1223,来自于IE的一个BUG,会将204的状态码变成 1223。现在因为有了jXHR对象,相当于中间多了一层,因此从jXHR对象获取statusCode不会出现1223的情况,已经被变回204了。

jQuery.ajax函数的配置项中多了一个statusCode项,其结构为map,用于指定返回特定状态码时的回调函数,大致形式如下:

jQuery.ajax({
url: 'xxx',
statusCode: {
200: function() { 处理请求成功 },
404: function() { 处理页面未找到 },
503: function() { 处理Service Unavailable }
}
});

再添加了这个回调后,jQuery.ajax函数已经有非常多的回调函数,其触发过程如下:

  1. 根据返回的状态码,触发success或者error回调。
  2. 根据状态码,触发对应的statusCode回调。
  3. 触发complete回调。
  4. 触发全局ajaxComplete回调。
  5. 如果此时没有正在执行的AJAX,触发全局ajaxStop回调。

其他细节

入口函数jQuery.fn.init现在多了一个参数,值始终为rootjQuery,用于加速init函数中对rootjQuery变量的查找速度(减少了一层作用域):

//jQuery 1.5 beta1 源码23行
jQuery = function( selector, context ) {
// The jQuery object is actually just the init constructor 'enhanced'
return new jQuery.fn.init( selector, context, rootjQuery );
}

jQuery对象支持继承了,具体的修改是将几处直接调用jQuery的代码改为了对this.constructor的调用:

202行:return this.constructor( context ).find( selector );
253行:var ret = this.constructor();
334行:return this.prevObject || this.constructor(null);

同时还提供了jQuery.subclass函数用于创建一个继承自jQuery的类型,由于不是很常用jQuery,更是从来没有用到过需要继承jQuery的情况,因此也不方便说这个功能的作用有多大。

原文来自:http://www.cnblogs.com/GrayZhang/archive/2011/01/18/jquery-1-5-enhanced-detail.html

Tags: jquery

Yii ClinkPager 郁闷

开发的时候,分页用了CLinkPager,然而在某一个页面的时候,page一直在变,但是下面的分类中的当前页永远在1上,不随着页码的变化而变化。
开始的时候以为是分页程序有问题,仔细对应了一下,发现分页的数据是正确的。
排查了半个多小时,突然想起,会不会$_GET['page']被unset了?
找了一下页面,最后在模版页里居然真的发现了unset($_GET['page']),当时我就傻眼了。
顺便再上一个option的onchange切换函数。很烂,只求先解决问题。。。。

JavaScript代码
  1. function urlchange(field,value) {  
  2.     var href= location.href;  
  3.     var regex = new RegExp(field+"=[\-|0-9]{0,}");  
  4.     if(href.indexOf(field)!=-1){  
  5.         location.href = href.replace(regex,field+"="+value);  
  6.     }else{  
  7.         location.href = href + "&"+field+"="+value;  
  8.     }  
  9. }      

用法就是<select onchange="urlchange('page',this.value)"><option value='1'>第一页</option><option value='2'>第二页</option><option value='10'>第十页</option></select>

Tags: yii, clinkpager