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

笔记:IOS发送图片的时候,还是用的$_FILES

纯笔记:
在与IOS交互的时候,采用了POST发送数据,同事说需要发送一张图片,于是我直接用$_POST进行获取,发现该字段无值。打印整个$_POST的时候,连这个key都没有找到
于是我在想,php://input有没有值呢?试了一下也没有,其实想想也是,如果真是用Base64处理后的发给我。我也应该是可以通过 $_POST收到的。
不过,还没有尝试这种:

PHP代码
  1. preg_match('/attachment;\s+name="(.+?)";\s+filename="(.+?)"/i'$_SERVER['HTTP_CONTENT_DISPOSITION'], $info)  

这种是HTML5上传了,不过我没有试过。。。
我看了一下同事以前的代码,发现是用$_FILES的,于是很方便的套了几行代码就一切都OK了。。
看来,脑子还是不能乱。

Tags: ios

QQ互联登录应用开发逻辑思路

摘抄这篇文章不是说它的思路有多好,事实上,我们在用微博登录后,如果用getUserInfo方法获取个人信息的时候,里面已经包含了openId的信息了。所以,如果支持微博登录的话,有些信息也可以利用了。。

原文来自:http://lab.wehefei.com/posts/394

当qq登陆成功后,QQ会给我们返回一个唯一的用户标识,也就是openId。

 大小: 35.62 K
尺寸: 358 x 376
浏览: 1359 次
点击打开新窗口浏览全图

这个openId是绝对唯一确定用户的标识,你可以把它理解成QQ号。当取得openId的时候,你就需要修改原网站的user表 或 重新建立一个新表,这样做的目的是为了把openId和网站原用户进行绑定。

当qq用户登陆的时候,就需要通过openId去user表查询,如果有查询到,那么就直接修改session登陆成功;

如果没有查询到,就证明是第一次登陆,需要跳转到绑定页面,让用户绑定一个用户名(也就是说创建一个新用户),然后在修改session登陆成功。

例:
1.首先修改用户表(user)增加一个openId字段 或者重新建立一个新表

2.前面说不是用户登录后能得到openId吗?   

openId是绝对唯一确定用户的标识 ,所以我们就根据这个(openId)判断

第一步:查询用户表里是否有  openId == 用户登录的openId
if(qq登陆用户openId如果用户表里查出来有的话){
   根据openId取得用户信息 跳转到登陆后的用户。
}else if(qq登陆用户openId如果在户表里有没有的话) {
   跳转到绑定页面,也就是创建一个新的用户(具体可以参照我的网站:http://ppptuan.com)
            //创建的过程中你还可以加判断的
             if(如果注册用已经有帐号了){
                       直接绑定 跳转到登陆后的页面。
              }else if(没有帐号){
                       跳转到注册页面 然后绑定 跳转到登陆后的页面
              }
}

思路大概就是这个样子。

当然第二种方法:

可以直接在我们member表添加一个openId的字段就OK了

----------
其实我想表达的是这里面的伪代码想法不错,在开发中,有时候就需要写这样的伪代码来先整理自己的思路。所以其实这篇文章想推荐给我的团队其他同事,在开发前一定要先把思路理清。不想写流程图就写伪代码吧。

mysql_pconnect的水挺深,apache下的数据库长连接

PHP中的mysql_pconnect一直是大家所拿过来做比较的,但对于很多开发者来说,只知道一件事情,那就是mysql_pconnect是长连接,而mysql_connect是普通的连接。既然PHP没有所谓的连接池,那为什么又会有mysql_pconnect的功能呢?
本文是网上而来的,也是我难得看到一篇关于mysql_pconnect的文章。所以摘抄下来
原文来自:mysql_pconnect的水挺深,apache下的数据库长连接

  php的mysql持久化连接,美好的目标,却拥有糟糕的口碑,往往令人敬而远之。这到底是为啥么。近距离观察后发现,这家伙也不容易啊,要看apache的脸色,还得听mysql指挥。

  对于做为apache模块运行的php来说,要实现mysql持久化连接,首先得取决于apache这个web服务器是否支持Keep-Alive。

  Keep-Alive是什么东西?它是http协议的一部分,让我们复习一下没有Keep-Alive的http请求,从客户在浏览器输入一个 有效url地址开始,浏览器就会利用socket向url对应的web服务器发送一条tcp请求,这个请求成功一次就得需要来回握三次手才能确定,成功以 后,浏览器利用socket tcp连接资源向web服务器请求http协议,发送以后就等着web服务器把http返回头和body发送回来,发回来后浏览器关闭socket连接, 然后做http返回头和body的解析工作,最后呈现在浏览器上的就是漂亮的页面了。这里面有什么问题呢?tcp连接需要三次握手,也就是来回请求三次方 能确定一个tcp请求是否成功,然后tcp关闭呢?来回需要4次请求才能完成!每次http请求就3次握手,4次拜拜,这来来回回的不嫌累啊,多少时间和 资源都被浪费在socket连接关闭上了,能不能一次socket tcp连接发送多次http请求呢?于是Keep-Alive就应运而生,http/1.0里需要客户端自己在请求头加入 Connection:Keep-alive方能实现,在这里我们只考虑http1.1了,只需要设置一下apache,让它默认就是Keep- Alive持久连接模式(apache必须1.2+才能支持Keep-Alive).在httpd.conf里找到KeepAive配置项,果断设置为 On,MaxKeepAliveRequests果断为0(一个持久tcp最多允许的请求数,如果过小,很容易在tcp未过期的情况下,达到最大连接,那 下次连接就又是新的tcp连接了,这里设置0表示不限制),然后对于mysql_pconnect最重要的选项KeepAliveTimeout设置为 15(表示15秒).

  好了,重启apache,测试一下,赶紧写行东西

PHP代码
  1. <?php  
  2.     echo "Apache进程号:".getmypid();  
  3. ?>  

很简单,获取当前php执行者(apache)的进程号,用浏览器浏览这个页面,看到什么?对,有看到一串进程号数字,15秒内,连续刷新页面,看 看进程号有无变化?木有吧?现在把手拿开,交叉在胸前,度好时间,1秒,2秒,3,...15,16。好,过了15秒了,再去刷新页面,进程号有没有变 化?变了!又是一个新的apache进程了,为什么15秒后就变成新的进程了?记得我们在apache里设置的KeepAliveTimeout吗?它的 值就是15秒.现在我们应该大致清楚了,在web服务器默认打开KeepAlive的情况下,客户端第一次http成功请求后,apache不会立刻断开 socket,而是一直监听来自这一客户端的请求,监听多久?根据KeepAliveTimeout选项配置的时间决定,一旦超过这一时间,apache 就会断开socket了,那么下次同一客户端再次请求,apache就会新开一个进程来相应。所以我们之前15内不停的刷新页面,看到的进程号都是一致 的,表明是浏览器请求给了同一个apache进程。

  浏览器是怎么知道不需要tcp连接就可以直接发送http请求呢?因为http返回头里就会带上Connection:keep- alive,Keep-alive:15两行,意思就是让客户端浏览器明白,这次socket连接我这边还没关闭呢,你可以在15内继续使用这个连接,并 发送http请求,于是乎浏览器就知道应该怎么做了.

  那么,php的mysql连接资源是怎么被hold住的呢,这需要查看php的mysql_pconnect的函数代码,我看了下,大概的做法 就是mysql_pconnect根据当前apache进程号,生成hash key,找hash表内有无对应的连接资源,没有则推入hash表,有则直接使用。有些代码片段可以说明(具体可查看php5.3.8源码 ext/mysql/php_mysql.c文件690行php_mysql_do_connect函数)

C++代码
  1. #1.生成hash key  
  2.     user=php_get_current_user();//获取当前php执行者(apache)的进程唯一标识号  
  3.     hashed_details_length = spprintf(&hashed_details, 0, "mysql__%s_", user);//hashed_details就是hash key  
  4. #2.如果未找到已有资源,就推入hash表,名字叫persistent_list,如果找到就直接使用  
  5.      /* try to find if we already have this link in our persistent list */  
  6.      if (zend_hash_find(&EG(persistent_list), hashed_details, hashed_details_length+1, (void **) &le)==FAILURE) {  /* we don't */  
  7.         ...  
  8.         ...  
  9.         /* hash it up(推入hash表) */  
  10.         Z_TYPE(new_le) = le_plink;  
  11.         new_le.ptr = mysql;  
  12.         if (zend_hash_update(&EG(persistent_list), hashed_details, hashed_details_length+1, (void *) &new_le, sizeof(zend_rsrc_list_entry), NULL)==FAILURE) {  
  13.             ...  
  14.             ...             
  15.         }  
  16.    
  17.      }else{/* The link is in our list of persistent connections(连接已在hash表里)*/  
  18.         ...  
  19.         ...  
  20.         mysql = (php_mysql_conn *) le->ptr;//直接使用对应的sql连接资源  
  21.         ...  
  22.         ...  
  23.           
  24.      }  

zend_hash_find比较容易看明白,原型是zend_hash_find(hash表,key名,key长,value);如果找到,value就有值了。

  说完Keep-Alive,该到mysql家串串门了,说的是mysql_pconnect,怎么能绕开mysql的设置。

  影响mysql_pconnect最重要的两个参数就是wait_timeout和interactive_timeout,它们是什么东西?先撇一边,首先让我们把上面的代码改动一下php代码

PHP代码
  1. <?php  
  2.     $conn = mysql_pconnect("localhost","root","123456"or die("Can not connect to mysql");  
  3.     echo "Mysql线程号:".mysql_thread_id($conn)."<br/>";  
  4.     echo "Apache进程号".getmypid();  
  5. ?>  
以上的代码没啥好解释的,让我们用浏览器浏览这个页面,看到什么?看到两个显眼的数字。一个是mysql线程号,一个是apache进程号,好 了,15秒后再刷新这个页面,发现这两个id都变了,因为已经是新的apache进程了,进程id是新的,hash key就变了,php只好重新连接mysql,连接资源推入persistent list。如果15内刷新呢?apache进程肯定不变,mysql线程号会变吗?答案得问mysql了。首先这个mysql_thread_id是什么 东西?shell方式登录mysql后执行命令'show processlist;',看到了什么?

mysql> show processlist;
XML/HTML代码
  1. +-----+------+-----------+------+---------+------+-------+------------------+  
  2. | Id  | User | Host      | db   | Command | Time | State | Info             |  
  3. +-----+------+-----------+------+---------+------+-------+------------------+  
  4. | 348 | root | localhost | NULL | Query   |    0 | NULL  | show processlist |  
  5. | 349 | root | localhost | NULL | Sleep   |    2 |       | NULL             |  
  6. +-----+------+-----------+------+---------+------+-------+------------------+  

,发现了很重要的信息,这个processlist列表就是记录了正在跑的线程,忽略Info列为show processlist那行,那行是你当前shell登录mysql的线程。php连接mysql的线程就是Id为349那行,如果读者自己做测试,应该 知道这个Id=349在你的测试环境里是另外一个值,我们把这个值和网页里输出的mysql_thread_id($conn)做做比较,对!他们是一样 的。接下来最重要的是观察Command列和Time列,Command = Sleep,表明什么?表明我们mysql_pconnect连接后就一直在sleep,Time字段就告诉我们,这个线程Sleep了多久,那么 Sleep了多久这个线程才能作废呢?那就是wait_timeout或者interactive_timeout要做的工作了,他们默认的值都是8小 时,天啊,太久了,所以如果说web服务器关掉KeepAlive支持,那个这个processlist很容易就被撑爆,就爆出那个Too many connections的错误了,max_connectiosns配置得再多也没用。为了观察这两个参数,我们可以在mysql配置文件my.cnf里 设置这两个值,找到[mysqld]节点,在里面设置多两行

配置代码
  1. interactive_timeout = 60  
  2. wait_timeout        = 30
配置完后,重启mysql,shell登录mysql,这时候show processlist可以发现只有当前线程。然后运行那个带有mysql_pconnect的php页面,再回来mysql端show processlist可发现,多了一个Commond为Sleep的线程,不停的show processlist(方向键上+enter键)观察Time列的变化2,5,10..14!,突然那个Sleep线程程被kill掉了,咋回事,还没 到30秒呢,噢!忘了修改一下apache keepalive的参数了,把KeepAliveTimeOut从15改成120(只为观察,才这么改),重启apache.刷新那个页面,好,开始不 停的show processlist,2..5..10..14,15,..20...26....28,29!线程被kill,这次是因为wait_timeout 起了作用,浏览器那边停了30秒,30内如果浏览器刷新,那这个Time又会从0开始计时。这种连接不属于interactive connection(mysql shell登录那种连接就属于interactive connection),所以采用了wait_timeout的值。如果mysql_pconnect的第4个参数改改呢

 

 

 

PHP代码
  1. <?php  
  2. $conn = mysql_pconnect('localhost','root','123456',MYSQL_CLIENT_INTERACTIVE);  
  3. echo "Mysql线程号:".mysql_thread_id($conn)."<br/>";  
  4. echo "Apache进程号:".getmypid();  
  5. ?>  
刷新下页面,mysql那边开始刷show processlist,这回Time > 30也不会被kill,>60才被kill了,说明设置了MYSQL_CLIENT_INTERACTIVE,就会被mysql视为 interactive connection,那么这次php的mysql连接在60秒内未刷新的情况下,何时作废将取决于mysql的interactive_timeout 的配置值。

  总结:php的mysql_pconnect要达到功效,首先必须保证apache是支持keep alive的,其次KeepAliveTimeOut应该设置多久呢,要根据自身站点的访问情况做调整,时间太短,keep alive没啥意义,时间太长,就很可能为一个闲客户端连接牺牲很多服务器资源,毕竟hold住socket监听进程是要消耗cpu内存的.最后 apache的KeepAliveTimeOut配置得和mysql的time out配置要有个平衡点,联系以上的观察,假设mysql_pconnect未带上第4个参数,如果apache的KeepAliveTimeOut设置 的秒数比wait_timeout小,那真正对mysql_pconnect起作用的是apache而不是mysql的配置.这时如果mysql的 wait_timeout偏大,并发量大的情况下,很可能就一堆废弃的connection了,mysql这边如果不及时回收,那就很可能Too many connections了.可以如果KeepAliveTimeOut太大呢,又回到之前的问题,所以貌似Apache.KeepAliveTimeOu 比Mysql.wait_timeout 稍大,或者相等是比较好的方案,这样可以保证keep alive过期后,废弃的mysql连接可以及时被回收. 

--------------

文章不算太长,看看即可,毕竟现在大多数项目 都开始用PDO了,但这样深究的文章还是有值得学习的地方的

三步,临时解决新浪微博接口ID超长的BUG

其实,不久前就知道新浪微博的ID的长度发生了变化,所以,原来的无符号长整形的长度是肯定不够了,超出后就变成了科学计数法。这样的URL可是没有办法在浏览器中打开的。
但服务器上一直没有这个问题,运行了uname -a后发现是64位系统,但测试机是32位的,怎么解决这个问题呢?
检查了一下oauth的代码,发现问题出在了json_decode函数上,因为取回来的数据都是字符串,只是在经过json_decode后,数字才超出长度了。知道这个问题后就好办了。
搜索json_decode,在这上面加上一行:
$response = preg_replace('@"id":(\d+)@','"id":"\\1"',$response);
为ID强制加上引号,变成字符串,而不是int型,所以在经过json_decode后,就仍然是字符串了。NND,新浪真偷懒,全部搞成字符串不就结了?到现在还在那里折腾整形不整形的。。

所幸,问题解决了。

转:用XML-RPC协议读写WordPress上的文章

 这是一篇很小的例子,事实上网上这些例子是超多的,不过由于我是要模拟metaweblog或者是wordpress的一些操作,那我就必须要先了解很多相关的背景。
不过这里只是模拟一些发布和读取的接口,稍作了解即可。
原文来自:用XML-RPC协议读写WordPress上的文章我这里只简要的摘取一部分。

WordPress提供了XML-RPC接口使得第三方的博客写作软件(如windows live writer等)可以与之通信来发布和修改博客。我们也可以在网站上使用这个接口做一些工作,例如:在网站首页显示最新的博客、在博客之外的页面上发表博 客文章、把博客与其他内容管理系统结合,等等。

一、开启XML-RPC支持

XML-RPC协议默认是未开启的,需要到WordPress管理后台的“设置–>撰写”里的“远程发布”给XML-RPC打上勾。其说明文 字为:启用 WordPress,Movable Type,MetaWeblog和Blogger 的 XML-RPC发布协议。

二、获取接口的信息

我们查看博客首页的源代码,在head中可以发现类似这样的link项

XML/HTML代码
  1. <link title="RSD" rel="EditURI" type="application/rsd+xml" href="http://blog.bluesky.cn/xmlrpc.php?rsd" />  

其中的"RSD"是“Really Simple Discovery”的意思,也就是说这是一个“简单的发现博客编辑接口”的地址。我们用浏览器直接访问这个地址就可以在其返回XML中获知博客的 ID(blogID,一般这个的值是“1”)以及它所支持的接口类型和接口地址。

三、API接口选择

WordPress提供了对Blogger APImetaWeblog APIMovable Type API以及其自身的WordPress API的支持。其中WordPress API最为丰富,提供了包括操作评论文章在内的各种各样的支持。Blogger API功能较少,基本上淘汰不用了;而metaWeblog API提供了常用的接口且参数比较简洁,用得较多一些。

四、例子代码

以下是使用Incutio的XML-RPC库和Blogger API发布文章的例子,其中IXR库也是Wordpress自身所用的库,可以在“wp-includes/class-IXR.php”找到。

PHP代码
  1. <?php  
  2. $xmlrpcurl='http://blog.bluesky.cn/xmlrpc.php';  
  3. $blogid='1';  
  4. $username='admin';  
  5. $password='pass';  
  6. $postTitle='标题';  
  7. $postContent='正文内容';  
  8.    
  9. require('class-IXR.php');  // /wordpress/wp-includes/class-IXR.php  
  10. $client = new IXR_Client($xmlrpcurl);  
  11.    
  12. $params=array(  
  13.    '',  
  14.    'blog_ID'=>$blogid,  
  15.    'user_login'=>$username,  
  16.    'user_pass'=>$password,  
  17.    'post_content'=>'' . $postContent,  
  18.    'publish'=>true  
  19. );  
  20. $params=array_values($params);  
  21.    
  22. $client->query("blogger.newPost",$params);  
  23. $response=$client->getResponse();  
  24.    
  25. if ($response['faultCode']==0){  
  26.    print 'Success';  
  27. else {  
  28.    print 'Fail:' . $response['faultString'];  
  29. }  
  30. ?>  
以下是用XML-RPC for PHP库和metaWeblog接口发布文章的例子。要先下载phpxmlrpc库取出其中的xmlrpc.inc来用。
PHP代码
  1. <?php  
  2. include("xmlrpc.inc"); // 这里要改成xmlrpc.inc所在的路径  
  3. $GLOBALS['xmlrpc_internalencoding'] = 'UTF-8';  
  4.    
  5. define ('DOMAIN''blog.bluesky.cn'); // 博客的域名  
  6. define ('BLOGID', 1); // 博客ID,一般为1  
  7. define ('USER''admin'); // 博客登录的用户名  
  8. define ('PASSWORD''pass'); // 博客登录的密码  
  9.    
  10. // 创建 xml-rpc client  
  11. $cl = new xmlrpc_client ( "/xmlrpc.php", DOMAIN, 80);  
  12.    
  13. // 准备请求  
  14. $req = new xmlrpcmsg('metaWeblog.newPost');  
  15. // 逐个列出请求的参数:  
  16. $req->addParam ( new xmlrpcval ( BLOGID, 'int')); // 博客ID  
  17. $req->addParam ( new xmlrpcval ( USER, 'string' )); // 用户名  
  18. $req->addParam ( new xmlrpcval ( PASSWORD, 'string' )); // 密码  
  19. $struct = new xmlrpcval (  
  20.     array (  
  21.         "title" => new xmlrpcval ( '标题''string' ), // 标题  
  22.         "description" => new xmlrpcval ( '正文内容''string'), // 内容  
  23.     ), "struct"  
  24. );  
  25. $req->addParam ( $struct );  
  26. $req->addParam ( new xmlrpcval (1, 'int')); // 立即发布  
  27.    
  28. // 发送请求  
  29. $ans = $cl->send($req);  
  30.    
  31. var_dump ( $ans );  
  32. ?>  
注意一定要加上:$GLOBALS['xmlrpc_internalencoding'] = ‘UTF-8′;这一句,否则不能正确处理中文。 另一段也是用phpxmlrpc库和metaWeblog接口发表文章的例子代码,该代码使用了返回类型为“phpvals”,这样可以直接用返回结果 的$r->val来获取文章ID号。
PHP代码
  1. <?php  
  2.   include("xmlrpc.inc");  
  3.   $GLOBALS['xmlrpc_internalencoding'] = 'UTF-8';   
  4.    
  5.   $c = new xmlrpc_client("/xmlrpc.php""blog.bluesky.cn", 80);  
  6.   $content['title']="标题";  //标题  
  7.   $content['description']="正文内容"//内容  
  8.   $content['mt_keywords']="标签1,标签2";  //标签  
  9.   $content['wp_password']="";  //文章密码,输入后显示加密  
  10.   $content['categories'] = array("分类1","分类2"); //分类名  
  11.   $x = new xmlrpcmsg("metaWeblog.newPost",  
  12.                       array(php_xmlrpc_encode("1"), //BLOG ID  
  13.                       php_xmlrpc_encode("admin"),  //用户名  
  14.                       php_xmlrpc_encode("pass"),  //密码  
  15.                       php_xmlrpc_encode($content),  
  16.                       php_xmlrpc_encode("1")));    //立即发表  
  17.    
  18.   $c->return_type = 'phpvals';  
  19.   $r =$c->send($x);  
  20.   if ($r->errno=="0")  
  21.     echo "发表成功,文章序号为:".$r->val;  
  22.   else {  
  23.     echo "出错了";  
  24.     print_r($r);  
  25.   }  
  26. ?>  

以下是读取最新一篇文章的例子代码:

PHP代码
  1. <?php  
  2.   include("xmlrpc.inc");  
  3.   $GLOBALS['xmlrpc_internalencoding'] = 'UTF-8';  
  4.   $c = new xmlrpc_client("/xmlrpc.php""blog.bluesky.cn", 80);  
  5.    
  6.   $msg = new xmlrpcmsg('metaWeblog.getRecentPosts',  
  7.                         array(php_xmlrpc_encode("1"),  
  8.                         php_xmlrpc_encode("admin"),  
  9.                         php_xmlrpc_encode("pass"),  
  10.                         php_xmlrpc_encode("1")) );  
  11.   $res = $c->send($msg);  
  12.   $val = $res->value();  
  13.    
  14.   $val->arraymem(0)->structreset();  
  15.   while (list($key$v) = $val->arraymem(0)->structeach())  
  16.   {  
  17.     echo "Element: $key; Type: ".$v->kindOf()."; Value:".$v->scalarval()."\n";  
  18.   }  
  19. ?>  
原文地址:http://blog.bluesky.cn/archives/466/using-xml-rpc-protocol-to-read-and-write-articles-on-wordpress.html

 

 

Tags: wordpress, xml-rpc, metaweblog