老王的技术手册
百度空间 | 百度首页 
 
文章列表
 
2009年10月31日 星期六 下午 08:01
作者:老王

PHP里有$_GET,$_POST,但是没有$_PUT,所以如果需要使用它的话,则你不得不自己模拟一下:

1 $_PUT = array();
2 if ('PUT' == $_SERVER['REQUEST_METHOD']) {
3     parse_str(file_get_contents('php://input'), $_PUT);
4 }


通过php://input得到的数据是raw data,所以需要用parse_str解析一下。

不过需要说明的是,当表单是enctype="multipart/form-data"类型的时候(就是上传文件那种类型),这种方法是无效的(此时php://input为空),一旦PHP发现请求的Content-Type是multipart/form-data,就会无条件的代你处理表单数据,然后保存到$_FILES里,此时无法得到raw data,只能用一些偏门方法,以apache为例,修改httpd.conf(为了使用RequestHeader语法,请先激活header模块):

1 <Location "/demo.php">
2     RequestHeader set Content-Type foobar
3 </Location>


通过重置Content-Type请求头为foobar(只要不是multipart/form-data即可),此时php://input就有数据了,不过原本应有的$_FILES数据却不存在了,所以基本上只有演示上的意义,如果想得到raw data,只能自己根据数据生成,在PEAR里有类似的实现:HTTP_Request2_MultipartBody

浏览器一般只允许使用GET/POST方法,虽然可以通过JS来发送PUT方法,但是还得编写代码,相对而言,使用命令行下的CURL命令则显得方便很多,在开发测试时很有用,所以学习一下还是必要的:

curl -X PUT http://www.domain.com/demo.php -d "id=1" -d "title=a"

这样就会通过PUT方法发送id, title数据,测试时demo.php的代码就类似上面的php://input,不细说了。
 
2009年10月24日 星期六 下午 08:08
作者:老王

说点题外话,单就框架而言,对我而言使用CakePHP要比使用Zend Framework顺手得多,不过最近CakePHP陷入了多事之秋,Phpnut,Gwoo,Nate彻底闹僵,Gwoo和Nate选择离开,据坊间传闻他们已经开始另立门户,稍后会释出一个CakePHP的衍生框架:Lithium。虽然CakePHP官方已经表态会一如既往的继续前进,但毫无疑问在众多开发者眼中,CakePHP的前景已经不再明朗,其是否能继续保证PHP框架领头羊的地位也越发充满疑问。

之所以说了这么多题外话,就是为了说明一点,对于广大PHPer而言,过多局限于一种框架之上本身就是一种强耦合,未来是不可预期的。所以我打算在继续使用CakePHP的同时,适当向Zend Framework倾斜,如果Lithium不错的话,也会在我未来学习计划之中占有一席之地。

言归正传,新版的Zend Framework引入了Zend_Application,把Bootstrap进行的规范化的封装,一个典型的Application的Bootstrap文件大致如下:

01 class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
02 {
03     protected function _initAutoloader()
04     {
05         $autoloader = new Zend_Application_Module_Autoloader(array(
06             'namespace' => 'Application',
07             'basePath' => APPLICATION_PATH,
08         ));
09
10         return $autoloader;
11     }
12 }


在Bootstrap中,所有以_init开头的方法被当做资源方法自动运行,如果方法有返回值的话,还会被作为资源保存。资源方法不是唯一配置资源的方式,为了避免重复编码,框架包含了若干现成的资源插件,可以在配置文件里通过简单设置就可以达到相应的功能,一个典型的配置文件如下所示:

01 return array(
02     'bootstrap' => array(
03         'path' => APPLICATION_PATH . '/Bootstrap.php',
04     ),
05     'resources' => array(
06         'modules' => array(),
07         'frontController' => array(
08             'controllerDirectory' => APPLICATION_PATH . '/controllers',
09             'moduledirectory' => APPLICATION_PATH . '/modules',
10         ),
11     ),
12 );


resources部分的modules和frontController就是资源插件。其中modules资源开启了系统的模块功能。比如说你有一个admin模块的话,那么对应的也可以有一个它自己的Bootstrap类:

01 class Admin_Bootstrap extends Zend_Application_Module_Bootstrap
02 {
03 }


需要说明的一点是Modules的Bootstrap里一般不再需要类似前面的_initAutoloader资源方法,这是因为从父类Zend_Application_Module_Bootstrap里已经通过继承自动执行了以模块名为命名空间的Autoloader操作。

在使用Modules的Bootstrap时,有一点需要注意的是系统会把所有模块的所有资源方法统统初始化一遍,打个比方来说,如果你有一个Blog模块,还有一个Forum模块,每个模块使用各自独立的数据库配置,都有一个自己的_initDb方法,那么即便是我们单独访问Blog或者Forum中一个模块,系统还是会把两个数据库都连接一遍,这无疑是低效的。但也不能就此认为这是Zend Framework的设计错误,问题的根源在于我们划分模块的粒度大小,如上所示,Blog和Forum不应该以Module的形式存在,而应该以Application的形式存在。如此一来仅需要在Application层次的Bootstrap中执行一次数据库连接即可。

Zend Framework的文档虽然看似详细,但很多细节都没有说明,比如说View助手缺省就会加载,这一点可以在Zend_Controller_Front中看到对Zend_Controller_Action_Helper_ViewRenderer的调用,所以最好在使用时自己扎到源代码里查阅。
 
2009年10月19日 星期一 下午 09:24
作者:老王

每天工作内容都免不了使用putty之类的工具多次登陆Linux服务器,执行若干命令,每次进行这些无趣的操作时,我都免不了下个决心:下次装上screen命令就方便多了。可是下次还是老样子,人的惰性总是难以打破,今天终于受不了了,装好了screen,好久不用了,用法都忘光了,这里再复习一下:

screen回车后就创建了一个新的会话,按ctrl+a+d就把会保存这个会话。

screen -ls会列出现在已有的会话,比如:

123.tty1.server        (Detached)
321.tty2.server        (Detached)

如果想恢复第一个会话,使用:screen -r 123或者screen -r tty1,只要能让screen区别出你要选择哪个即可。

直接使用screen创建会话有一个问题,就是会话的名字无实际的语义,不容易记忆,此时可以使用-S参数:

screen -S foobar

然后按ctrl+a+d保存会话,接着使用命令screen -ls查询,你就能看到名为foobar的会话了,再恢复它:

screen -r foobar

完活!具体参考文档或者linux 技巧:使用 screen 管理你的远程会话。学而时习之,不亦悦乎。
 
2009年10月13日 星期二 下午 04:22
作者:老王

Blueprint为代表的CSS框架一直为人诟病的缺点之一就是其生成的标签都是一些诸如span-24之类的名字,缺乏实际的语义,不过现在这种情况已经改变了,只需要简单的配置,Blueprint就可以帮你自动生成语义化标签。

使用本功能前需要先安装好ruby的运行环境,最好再熟悉一下yml的文件格式。把blueprint\lib目录下的配置文件settings.example.yml改名为settings.yml,并修改project2,把path改成已存在的某个目录,里面的semantic_classes部分就是我们需要的语义化标签的配置:

"#footer, #header": ".span-24, div.span-24"
"#content": ".span-17, div.span-17, div.colborder"
"#extra-content": ".span-6, div.span-6"
"div#navigation": "div.span_24, .span-24"
"div.section, div.entry, .feeds": ".span-6 div.span-6"

然后在命令行下运行:

ruby compress.rb -p project2

如此一来,就会在我们预先设置的path路径下生成自定义的css文件,查看screen.css文件的最下面:

/* semantic class names */
#content {float:left;margin-right:10px;width:670px;padding-right:24px;margin-right:25px;border-right:1px solid #eee;}
#footer, #header {float:left;margin-right:10px;width:950px;margin-right:0;}
#extra-content {float:left;margin-right:10px;width:230px;}
div.section, div.entry, .feeds {float:left;margin-right:10px;width:230px;}
div#navigation {width:950px;margin-right:0;}

名字看上去好了很多,可以安心使用CSS框架了。如果不清楚yml配置文件中各项的含义,可以参考compress.rb文件中的注释部分,里面做了详细的介绍,还可以参考此文:Blueprint’s compress.rb: A Walkthrough,或者CSS Frameworks and Semantic Class Names

顺手记录一个网址:csscaffold
 
2009年10月13日 星期二 下午 01:04
作者:老王

SOAP已经是属于OUT范畴的技术了,不过因为历史原因,时不时还是会用到它,以前都是用NuSOAP,现在准备试试PHP内置的SOAP扩展。由于文本只打算说说客户端的用法,所以得先找一些能直接用的服务端,Xmethods提供了一些有趣的选择,这里选择其中的Map IP Address to Country服务,功能很简单,就是提供一个IP地址,然后返回国家名称。

先创建一个client实例:

$client = new SoapClient('http://www.ecubicle.net/iptocountry.asmx?wsdl', array('trace' => true));

通过设置trace为true,我们可以在稍后使用__getLastRequest,__getLastRequestHeaders,__getLastResponse,__getLastResponseHeaders等方法得到一些信息,在程序调试阶段,这些信息很有用,程序投入使用时,则不必使用此参数。除了trace参数,还可以设定login和password参数以实现HTTP认证的功能,此外还有很多参数,可以参考官方文档

创建了前面的$client实例后,我们可以先看看服务都提供了哪些方法:

print_r($client->__getFunctions());

服务方法的信息细节可以从wsdl里自己查阅,下面看看怎么调用一个实际的方法,$ip='64.156.132.140':

$result = $client->__soapCall('FindCountryAsString', array('FindCountryAsString' => array('V4IPAddress' => $ip)));
print_r($result->FindCountryAsStringResult);

还可以这样调用:

$result = $client->FindCountryAsString(array('V4IPAddress' => $ip));
print_r($result->FindCountryAsStringResult);

还可以这样调用:

$params = new SoapParam(array('V4IPAddress' => $ip), 'FindCountryAsStringSoapIn');
$result = $client->__soapCall('FindCountryAsString', array($params));
print_r($result->FindCountryAsStringResult);

还可以这样调用:

$params = new SoapParam(array('V4IPAddress' => $ip), 'FindCountryAsStringSoapIn');
$result = $client->FindCountryAsString($params);
print_r($result->FindCountryAsStringResult);

在使用SOAP时,参数如何传递有点不好说明,这需要研读wsdl描述文档,不过看wsdl实在是一件无趣的事情,所以我觉得你可以先大概看一下wsdl,然后凭感觉去尝试传递参数,其中配合trace调试,一般来说,试几次就能找到正确的传递方式,如果还不行,再通过__getLastRequest,__getLastRequestHeaders等方法提供的信息配合wsdl描述文档仔细研究。

附一个很不错的SOAP测试工具:SOAPUI
 
     
 
 
文章分类
 
 
Os(33)
 
 
 
Php(61)
 
 
 
 
 
 
     
 
关注工具
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
     
 
在线资料
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
     
 
订阅我的空间
 
已有人次访问本空间
 
订阅RSS  什么是RSS?

您也想拥有这样的空间?请点此申请。
     


©2009 Baidu