测试工具:wsCaller.jar (此文是给java程序调用的webservice)
提示:要运行wsCaller.jar 要选安装jdk 如果没有安装jdk 则wsCaller.jar 会以压缩包的形式显示
1 写webservice 要用到的接口
<?php
class service
{
function add($a,$b){
$c=$a+$b;
return $c;
}
function str($string){
return $string;
}
}
//require('cls_mysql.php');
//$db = new cls_mysql('localhost', 'root', 'root', test_db');
//$db = new cls_mysql('211.103.156.227:3306', 'root', 'txtx', test_db');
//'testwsdl.wsd需要在后面采用Zend Studio生成。
$server=new SoapServer('testwsdl.wsdl',array('uri' => 'http://webserver.com/','encoding'=>'utf-8','soap_version' => SOAP_1_2 ));
$server->setClass("service");
$server->handle();
?>
2.生成wsdl文件
菜单中
File--àExport---àphp 选中 “wsdl file” 然后下一步 (图1)
File name 是wsdl 文件所在的位置
Exported files 下面的文件是你上面刚刚创建的php文件(接口文件)
Classes 下面的service 前面的勾要打上
URL 中填写接口文件的访问地址 (如:http://webserver.com/rpcservice.php)
点击global settings 出现下图(图3)
选择RPC – Oriented
然后点击 “ok” 在点击 “Finish”
出现下图(图4)
最后一步就是给 每个参数一个合理的类型(下图)
然后保存
到此 wsdl文件已经生成
访问路径 http://webserver.com/testwsdl.wsdl (会出现下面内容)
如果不出现 则要配置apache 使其支持xml
注: 不要用chrome 打开wsdl文件 ,可能会显示不正常 (可以用ie firfox)
测试是否可以成功调用
测试工具
wsCaller.jar
注:必需安装JDK 才能运行wsCaller.jar 请不要解压wsCaller.jar
如果不能正确返回信息 可直接访问你的php 看看会不会报错
(本例http://webserver.com/rpcservice.php)
Php 要支持 soap
如果php 版本是5.X 则 编辑 php.ini
extension=php_soap.dll (添加 如果存在则去掉注释)
重启一下apache
apache 要注意这个文件 mime.types
函数添加新参数
找到message name=”函数名” 中直接复制一下并把参数改一下参数名
WSDL文件
<!--[endif]-->
Php接口文件
注:$e 就是wsdl文件中的 c 参数
添加新的函数
WSDL复制代码就行; PHP写出对应的函数 (看一下选中的部分 其实就是复制了一下add 这个函数 并且直接粘贴在它下面就可以) 下面以 添加add_bak 函数为例
WSDL
1.复制message 标签
2.复制 portType 中的标签
3.复制binding 标签内容
PHP
function add_bak($a,$b,$e){
$c=$a+$b-$e;
return $c;
}
测试结果
add_bak 函数
add 函数
其它函数就不一一测试了截图了
如果有不对的地方,请指出 谢谢
<!--[if !supportLists]-->一、<!--[endif]-->安装篇(XDebug 和PHPUnit)
A:安装XDebug:
Xdebug网下载xdebug dll文件,存放到php加载的ext目录下(可以选择重命名,比如php_xdebug.dll,然后打开php.ini文件,添加配置
[xdebug]
zend_extension_ts = php_xdebug.dll
xdebug.profiler_enable = on
xdebug.trace_output_dir = D:\PHPAPP\XDebug
xdebug.profiler_output_dir=D:\PHPAPP\XDebug
xdebug需要采用zend引擎加载的方式加载,所以用zend_extension_ts或是zend_extension, ts是thread_safety, 目前5.3以上才支持zend_extension加载,<5.3的用zend_extension_ts加载(或者你可以查看phpinfo是否启用了zts),然后重启apache,查看phpinfo,就发现XDebug选项了。
可以看到xdebug.profiler_enable,xdebug.profiler_output_dir,xdebug.trace_output_dir这三个是我们刚刚配置的项,可以安装自己的需要配置剩余项,xdebug.profiler_enable:开启性能分析,
开启这个之后会在xdebug.profiler_output_dir这个目录下生成cachegrind.out.XXX的分析文件,如果指定了xdebug.profiler_output_name这个,则输出来的文件就会是指定的名字.xxx的格式(此方法不适合分析,原因稍后说明),
xdebug.trace_options:这个是开启跟踪项,
开启该项之后,会在xdebug.trace_output_dir下生产跟踪文件,注意该项会影响运行速度,因为他需要记录跟踪过程中的一系列事件。
关于XDebug还有一点需要注意的:XDebug是调试的,也就是说配置了XDebug那程序运行的就是一个Debug状态,所以这时候zend_optimizer就不能用了,总不能让程序即调试状态又处于优化状态哈。
更多关于XDebug的,大家去网上发掘吧~~然后一起探讨哈
友情提醒:对于使用集成环境的同学,比如Wamp,它拥有两个PHP.ini配置文件,一个在Apache下,一个在PHP下,Apache下是影响web的,而PHP下是影响命令行的,所以····(感谢俊哥的提醒)
B:安装PHPUnit:
关于PHPUnit的安装过程,网上也已经很多了,之前自己为了终于安装成功之后也小写了篇安装篇(http://user.qzone.qq.com/414073277/blog/1292122868),所以这里就不再赘述了,网上的一些安装教程大都能完成安装。就简单说下过程:
PHPUnit安装用的是pear的安装方式,所以如果机子没有安装过pear包需要先安装下,一般在php安装的时候在其安装目录下都有一个go-pear.bat文件,直接执行即可完成安装,【这里安装需要注意扩展exif,这个扩展会用到mbstring扩展中的方法,所以mbstring的加载顺序需要再exif之上。】完成pear的安装之后就可以执行pear,查看pear的命令参数,
然后依次执行:
pear channel-discover pear.phpunit.de
pear install –alldeps phpunit/PHPUnit
需要注意的是现在最新版的phpunit是3.5的··但是这个只有pear的版本是1.6以上及PHP5.2.X才会安装得到最新版·否则是安装的是第一次的版本(不过不影响使用)。
安装好后就可以执行phpunit查看相关信息:
可以看到有—coverage-html –coverage-clover –coverage-source这三个选项·就是因为在XDebug安装成功之后才能用,这三个对于导出覆盖率文件可是很重要的选项。
<!--[if !supportLists]-->二、<!--[endif]-->PHPUnit 单元测试覆盖率分析
单元测试,最重要的指标之一就是覆盖率。这点虽然Zend Studio上可以很清晰的看出来,可是要导出成一分文档就不太好使了,所以这时候XDebug就又可以帮上忙了,使用的时候也挺简单,调用命令即可:
phpunit –coverage-html D:\PHPAPP\XDebug\ YouTest
这样就会将生成的覆盖文件(html格式的)放在D:\PHPAPP\XDebug\目录下了,
然后就可以在放置的目录下找到一堆的html文件,运行下index.html
就可以看到这样的图了,英文字母很简单··意思也明了就不解释了,说明一点:
测试结果说明:一共有5种,上图的例子出现了两种。
. :代表正确
F :代表断言错误
E :代表PHP程序错误或是异常
I : 代表没有实现的方法
S : 代表是跳过的方法
生产的覆盖文件说明:
Classes: 只有一个类中的所有方法都被覆盖的时候,这个类才算是被测试完的
Functions/Methods :只有一个方法或是函数的所有有效的语句代码都被执行到了才算这个方法或是函数是被测试完的
Lines: 总行数将会不饱行注释,空行,<?php ?> 标签, 及类及方法的声明。
使用phpunit –coverage-clover D:\PHPAPP\XDebug\first.xml YouTest
生产的将会是一个xml格式的文件,这个格式的文件效果不明显,没有html格式的好,这边的效果被我删掉了所以么有效果图可看,第三个覆盖文件的参数我没测试过,大家有兴趣可以试试。
<!--[if !supportLists]-->三、<!--[endif]-->程序执行性能分析
XDebug除了有效的帮助分析单元测试覆盖率之外,还可以帮组分析程序执行的瓶颈所在,开启分析的功能:
xdebug.profiler_enable = on
xdebug.profiler_output_dir=D:\PHPAPP\XDebug
设置上面两项,然后执行你要分析的程序,就会在上面的目录下看到cachegrind.out.XXX的文件,这个文件直接打开就是一些记录,需要借助第三方的cachegrind查看工具才行,一个好用的工具是winCacheGrind,查看起来很方便。
可以看到执行的总时间,及每个函数执行的时间。
因为这个工具在打开文件的时候,只能打开cachegrind.out.*的文件,所以待分析的文件必须是这个名字的,所以为了省去重命名,这也就是为啥我说不建议修改xdebug.profiler_output_name这个选项的原因。
<!--[if !supportLists]-->四、<!--[endif]-->XDebug库函数
XDebug除了上述方式外,还有自己的一些函数库提供,可以在你程序的代码段任何地方执行,具体的请看http://xdebug.org/docs/all_functions
XDebug的功能,还不止这些,因为他的选项·好大的一页,所以还是去http://xdebug.org/docs/这里看看官方的说明。靠谱!
<?php
/**
* 事件异常
*
* @author lonely
* @create 2010-10-21
* @version 0.1
* @lastupdate lonely
* @package Event
*/
class Exception_Event extends Exception {}
/**
* 事件对象
*
* @author lonely
* @create 2010-10-21
* @version 0.1
* @lastupdate lonely
* @package Event
*/
class Event extends stdClass{
public $target=null;
public $type=null;
/**
* 创建事件
* @param string $type
*/
public function __construct($type){
$this->type=trim($type);
}
/**
* 得到事件字符串
*/
public function __toString(){
return $this->type;
}
}
/**
* 事件派发
*
* @author lonely
* @create 2010-10-21
* @version 0.1
* @lastupdate lonely
* @package Event
*/
class EventDispatcher{
private $_callback_method;
/**
* 添加事件
* @param Event $event
* @param string $method
* @param string||object $class
* @return boolean true
*/
public function attach(Event $event,$method,$|object $class
* @return void
*/
public function dispatch(Event $event){
$eventstr=$this->_create_event_str($event);
if($this->_check_callback($eventstr)){
foreach ($this->_callback_method[$eventstr] as $v){
if($v['object']){
if(is_object($v['class'])){
$v['class']->$v['method']($event);
}else{
call_user_func(array($v['class'], $v['method']),$event);
}
}else{
$v['function']($event);
}
}
}
}
/**
* 删除事件
* @param Event $event
* @param string $method
* @param string $class
* @return boolean true
*/
public function detact(Event $event,$method,$class'])){
$v_class']);
}else{
$v_class'];
}
if(is_object($class)){
$s_class"=>$v_class,
"method"=>$method,
);
$temp_s=array(
"class"=>$s_class,
"method"=>$method,
);
if($temp_v==$temp_s){
return true;
}
}
}
}else{
$this->_check_function($method);
if($this->_check_callback($eventstr)){
foreach($this->_callback_method[$eventstr] as $v){
if($method==$v['function']){
return true;
}
}
}
}
return false;
}
/**
* 检测指定类是否存在指定方法
* @param string $class
* @param string $method
* @exception Exception_Event
* @return void
*/
private function _check_method($class,$method){
if(!method_exists($class,$method)){
throw new Exception_Event(get_class($class)." not exist ".$method." method",1);
}
}
/**
* 检测指定函数是否存在
* @param string $function
* @return void
*/
private function _check_function($function){
if(!function_exists($function)){
throw new Exception_Event($function." function not exist ",2);
}
}
/**
* 检测指定事件是否存在监听函数
* @param string $eventstr
* @return boolean
*/
private function _check_callback($eventstr){
if(isset($this->_callback_method[$eventstr])
&&is_array($this->_callback_method[$eventstr])
){
return true;
}
return false;
}
/**
* 创建监听函数数组
* @param string $eventstr
* @param string $function
* @return array
*/
private function _create_listener_fn($eventstr,$function){
return array(
"object"=>false,
"function"=>$function,
);
}
/**
* 创建监听类数组
* @param string $eventstr
* @param string $class
* @param string $method
* @return array
*/
private function _create_listener_method($eventstr,$class,$method){
return array(
"object"=>true,
"class"=>$class,
"method"=>$method,
);
}
/**
* 创建事件字符串
* @param Event $event
* @return string
*/
private function _create_event_str(Event $event){
$classstr=strtolower(get_class($event));
$eventstr=(string)$event;
return $classstr.$eventstr;
}
}
class test extends EventDispatcher{
}
function t($e){
print_r($e->a);
}
$v=new test();
$e=new Event("test");
$v->attach($e,"t");
$v->detact($e,"t");
echo $v->has($e,"t");
$e->a="dd";
$v->dispatch($e);