例子是网上看到的,具体地址找不到了,先记录一下,日后有用。 services_controller.php <?php class ExecutionDTO { public $id; public $testcase_id; public $details; public $report; public $size; public $complete_units; public $attempted_units; public $failed_units; public $blocked_units; public $configuration_id; public $iteration_id; public $created; public $updated; public $pdfs; public function __construct() { $this->id = NULL; $this->testcase_id = NULL; $this->details = NULL; $this->report = NULL; $this->size = NULL; $this->complete_units = NULL; $this->attempted_units = NULL; $this->failed_units = NULL; $this->blocked_units = NULL; $this->configuration_id = NULL; $this->iteration_id = NULL; $this->created = NULL; $this->updated = NULL; $this->pdfs = NULL; } } class PdfDTO { public $name; public $type; public $text_value; public $date_value; public $num_value; public $bool_value; } class FindResponseDTO { public $out; public function __construct() { $this->out = new ExecutionDTO(); } } class UpdateResponseDTO { public static $SUCCESS = 0; public static $PERMISSION_FAILED = 1; public static $NO_SUCH_EXECUTION = 2; public static $BAD_DATA = 4; public static $NOT_ACTIVE = 256; public $out; public function __construct($code = 0) { $this->out = $code; } } /** * This class exists to facilitate remote web services */ class ServicesController extends AppController { public $helpers = array(); public $components = array(); protected $level = "execution"; public $layout = "ajax"; /** * All web services should come through this method and then PHP * will farm it out to the other methods. */ public function remote() { $this->log("-> remote()", LOG_DEBUG); $server = new SoapServer("../webroot/wsdl/smarts.wsdl", array( 'soap_version' => SOAP_1_2, array('classmap' => array( 'Execution' => "ExecutionDTO", 'pdf' => "PdfDTO", 'findByTestcaseNameResponse' => 'FindResponseDTO', 'findByTestcaseIdResponse' => 'FindResponseDTO', 'findByNamesResponse' => 'FindResponseDTO', 'findByIdsResponse' => 'FindResponseDTO', 'updateResponse' => 'UpdateResponseDTO' ) ) ) ); $server->setObject($this); $f = implode(" ", file("php://input")); $this->log($f, LOG_DEBUG); try { $server->handle($f); } catch (Exception $e) { $this->log(var_export($e, true)); } $this->log("<- remote()", LOG_DEBUG); // This is necessary to avoid rendering anything extra from Cake exit; } /* * This is a web service called method */ public function update($parameters) { if (LOG_LEVEL <= LOG_DEBUG) $this->log(" -> update(" . var_export($parameters, true) . ")", LOG_DEBUG); if ($parameters->execution != NULL && $parameters->execution->id != NULL) { $this->execution = $this->Execution->find( "first", array( "conditions" => array( "Execution.id" => $parameters->execution->id ), "fields" => $this->Execution->getControlFields(0), "recursive" => 0 ) ); if ($this->execution) { /** * Implementation Details */ } else { return new UpdateResponseDTO(UpdateResponseDTO::$NO_SUCH_EXECUTION); } } else { return new UpdateResponseDTO(UpdateResponseDTO::$NO_SUCH_EXECUTION); } return new UpdateResponseDTO(UpdateResponseDTO::$SUCCESS); } /* * This is a web service called method */ public function findByIds($parameters) { if (LOG_LEVEL <= LOG_DEBUG) $this->log("-> findByIds(" . var_export($parameters, true) . ")", LOG_DEBUG); $testcase_id = $parameters->testcase_id; $configuration_id = $parameters->configuration_id; $iteration_id = $parameters->iteration_id; $toReturn = NULL; /** * Implementation Details */ if (LOG_LEVEL <= LOG_DEBUG) $this->log("<- findByIds(): " . var_export($toReturn, true), LOG_DEBUG); return $toReturn; } /* * This is a web service called method */ public function findByTestcaseId($parameters) { if (LOG_LEVEL <= LOG_DEBUG) $this->log("-> findByTestcaseId(" . var_export($parameters, true) . ")", LOG_DEBUG); /** * Implementation Details */ // Re-using existing functionality. return $this->findByIds($parameters); } /* * This is a web service called method */ public function findByTestcaseName($parameters) { if (LOG_LEVEL <= LOG_DEBUG) $this->log("-> findByTestcaseName(" . var_export($parameters, true) . ")", LOG_DEBUG); $release_id = $parameters->release_id; $testcase_name = $parameters->testcase_name; /** * Implementation Details */ if (LOG_LEVEL <= LOG_DEBUG) $this->log("<- findByTestcaseName(): " . var_export($toReturn, true), LOG_DEBUG); return $toReturn; } /* * This is a web service called method */ public function findByNames($parameters) { if (LOG_LEVEL <= LOG_DEBUG) $this->log("-> findByNames(" . var_export($parameters, true) . ")", LOG_DEBUG); /** * Implementation Details */ // Re-using existing functionality. return $this->findByTestcaseName($parameters); } } ?> 生成的WSDL大致应该是:smarts.wsdl <?xml version="1.0"?> <wsdl:definitions targetNamespace="http://ws.smarts.com" xmlns:soapenc12="http://www.w3.org/2003/05/soap-encoding" xmlns:tns="http://ws.smarts.com" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap11="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soapenc11="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope"> <wsdl:types> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://ws.smarts.com"> <xsd:complexType name="Execution"> <xsd:sequence> <xsd:element name="pdfs" type="tns:pdf" maxOccurs="unbounded" minOccurs="0"></xsd:element> </xsd:sequence> <xsd:attribute name="id" type="xsd:long"></xsd:attribute> <xsd:attribute name="testcase_id" type="xsd:long"></xsd:attribute> <xsd:attribute name="size" type="xsd:int"></xsd:attribute> <xsd:attribute name="complete_units" type="xsd:int"></xsd:attribute> <xsd:attribute name="attempted_units" type="xsd:int"></xsd:attribute> <xsd:attribute name="blocked_units" type="xsd:int"></xsd:attribute> <xsd:attribute name="failed_units" type="xsd:int"></xsd:attribute> <xsd:attribute name="configuration_id" type="xsd:long"></xsd:attribute> <xsd:attribute name="iteration_id" type="xsd:long"></xsd:attribute> <xsd:attribute name="report" type="xsd:boolean"></xsd:attribute> <xsd:attribute name="created" type="xsd:dateTime"></xsd:attribute> <xsd:attribute name="updated" type="xsd:dateTime"></xsd:attribute> <xsd:attribute name="details" type="xsd:string"></xsd:attribute> </xsd:complexType> <xsd:element name="update"> <xsd:complexType> <xsd:sequence> <xsd:element maxOccurs="1" minOccurs="1" name="execution" nillable="false" type="tns:Execution"/> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:element name="updateResponse"> <xsd:complexType> <xsd:sequence> <xsd:element maxOccurs="1" minOccurs="1" name="out" type="xsd:int"/> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:element name="findByTestcaseName"> <xsd:complexType> <xsd:sequence> <xsd:element maxOccurs="1" minOccurs="1" name="release_id" nillable="false" type="xsd:long"/> <xsd:element maxOccurs="1" minOccurs="1" name="testcase_name" nillable="false" type="xsd:string"/> <xsd:element maxOccurs="1" minOccurs="1" name="configuration_id" nillable="true" type="xsd:long"/> <xsd:element maxOccurs="1" minOccurs="1" name="iteration_id" nillable="true" type="xsd:long"/> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:element name="findByTestcaseNameResponse"> <xsd:complexType> <xsd:sequence> <xsd:element maxOccurs="1" minOccurs="1" name="out" nillable="true" type="tns:Execution"/> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:element name="findByTestcaseId"> <xsd:complexType> <xsd:sequence> <xsd:element maxOccurs="1" minOccurs="1" name="release_id" nillable="true" type="xsd:long"/> <xsd:element maxOccurs="1" minOccurs="1" name="testcase_id" nillable="false" type="xsd:long"/> <xsd:element maxOccurs="1" minOccurs="1" name="configuration_name" nillable="true" type="xsd:string"/> <xsd:element maxOccurs="1" minOccurs="1" name="iteration_name" nillable="true" type="xsd:string"/> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:element name="findByTestcaseIdResponse"> <xsd:complexType> <xsd:sequence> <xsd:element maxOccurs="1" minOccurs="1" name="out" nillable="true" type="tns:Execution"/> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:element name="findByIds"> <xsd:complexType> <xsd:sequence> <xsd:element maxOccurs="1" minOccurs="1" name="release_id" nillable="true" type="xsd:long"/> <xsd:element maxOccurs="1" minOccurs="1" name="testcase_id" nillable="false" type="xsd:long"/> <xsd:element maxOccurs="1" minOccurs="1" name="configuration_id" nillable="true" type="xsd:long"/> <xsd:element maxOccurs="1" minOccurs="1" name="iteration_id" nillable="true" type="xsd:long"/> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:element name="findByIdsResponse"> <xsd:complexType> <xsd:sequence> <xsd:element maxOccurs="1" minOccurs="1" name="out" nillable="true" type="tns:Execution"/> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:element name="findByNames"> <xsd:complexType> <xsd:sequence> <xsd:element maxOccurs="1" minOccurs="1" name="release_id" nillable="false" type="xsd:long"/> <xsd:element maxOccurs="1" minOccurs="1" name="testcase_name" nillable="false" type="xsd:string"/> <xsd:element maxOccurs="1" minOccurs="1" name="configuration_name" nillable="true" type="xsd:string"/> <xsd:element maxOccurs="1" minOccurs="1" name="iteration_name" nillable="true" type="xsd:string"/> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:element name="findByNamesResponse"> <xsd:complexType> <xsd:sequence> <xsd:element maxOccurs="1" minOccurs="1" name="out" nillable="true" type="tns:Execution"/> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:complexType name="pdf"> <xsd:attribute name="name" type="xsd:string" use="required"></xsd:attribute> <xsd:attribute name="type" type="xsd:string" use="required"></xsd:attribute> <xsd:attribute name="text_value" type="xsd:string" use="optional"></xsd:attribute> <xsd:attribute name="date_value" type="xsd:dateTime" use="optional"></xsd:attribute> <xsd:attribute name="num_value" type="xsd:float" use="optional"></xsd:attribute> <xsd:attribute name="bool_value" type="xsd:boolean" use="optional"></xsd:attribute> </xsd:complexType> </xsd:schema> </wsdl:types> <wsdl:message name="findByTestcaseIdRequest"> <wsdl:part name="parameters" element="tns:findByTestcaseId"> </wsdl:part> </wsdl:message> <wsdl:message name="findByTestcaseNameResponse"> <wsdl:part name="parameters" element="tns:findByTestcaseNameResponse"> </wsdl:part> </wsdl:message> <wsdl:message name="findByIdsRequest"> <wsdl:part name="parameters" element="tns:findByIds"> </wsdl:part> </wsdl:message> <wsdl:message name="updateRequest"> <wsdl:part name="parameters" element="tns:update"> </wsdl:part> </wsdl:message> <wsdl:message name="findByNamesRequest"> <wsdl:part name="parameters" element="tns:findByNames"> </wsdl:part> </wsdl:message> <wsdl:message name="findByTestcaseIdResponse"> <wsdl:part name="parameters" element="tns:findByTestcaseIdResponse"> </wsdl:part> </wsdl:message> <wsdl:message name="findByNamesResponse"> <wsdl:part name="parameters" element="tns:findByNamesResponse"> </wsdl:part> </wsdl:message> <wsdl:message name="findByIdsResponse"> <wsdl:part name="parameters" element="tns:findByIdsResponse"> </wsdl:part> </wsdl:message> <wsdl:message name="findByTestcaseNameRequest"> <wsdl:part name="parameters" element="tns:findByTestcaseName"> </wsdl:part> </wsdl:message> <wsdl:message name="updateResponse"> <wsdl:part name="parameters" element="tns:updateResponse"> </wsdl:part> </wsdl:message> <wsdl:portType name="RemotePortType"> <wsdl:operation name="update"> <wsdl:input name="updateRequest" message="tns:updateRequest"> </wsdl:input> <wsdl:output name="updateResponse" message="tns:updateResponse"> </wsdl:output> </wsdl:operation> <wsdl:operation name="findByTestcaseName"> <wsdl:input name="findByTestcaseNameRequest" message="tns:findByTestcaseNameRequest"> </wsdl:input> <wsdl:output name="findByTestcaseNameResponse" message="tns:findByTestcaseNameResponse"> </wsdl:output> </wsdl:operation> <wsdl:operation name="findByTestcaseId"> <wsdl:input name="findByTestcaseIdRequest" message="tns:findByTestcaseIdRequest"> </wsdl:input> <wsdl:output name="findByTestcaseIdResponse" message="tns:findByTestcaseIdResponse"> </wsdl:output> </wsdl:operation> <wsdl:operation name="findByIds"> <wsdl:input name="findByIdsRequest" message="tns:findByIdsRequest"> </wsdl:input> <wsdl:output name="findByIdsResponse" message="tns:findByIdsResponse"> </wsdl:output> </wsdl:operation> <wsdl:operation name="findByNames"> <wsdl:input name="findByNamesRequest" message="tns:findByNamesRequest"> </wsdl:input> <wsdl:output name="findByNamesResponse" message="tns:findByNamesResponse"> </wsdl:output> </wsdl:operation> </wsdl:portType> <wsdl:binding name="RemoteHttpBinding" type="tns:RemotePortType"> <wsdlsoap:binding style="document" mce_style="document" transport="http://schemas.xmlsoap.org/soap/http"/> <wsdl:operation name="update"> <wsdlsoap:operation soapAction=""/> <wsdl:input name="updateRequest"> <wsdlsoap:body use="literal"/> </wsdl:input> <wsdl:output name="updateResponse"> <wsdlsoap:body use="literal"/> </wsdl:output> </wsdl:operation> <wsdl:operation name="findByTestcaseName"> <wsdlsoap:operation soapAction=""/> <wsdl:input name="findByTestcaseNameRequest"> <wsdlsoap:body use="literal"/> </wsdl:input> <wsdl:output name="findByTestcaseNameResponse"> <wsdlsoap:body use="literal"/> </wsdl:output> </wsdl:operation> <wsdl:operation name="findByTestcaseId"> <wsdlsoap:operation soapAction=""/> <wsdl:input name="findByTestcaseIdRequest"> <wsdlsoap:body use="literal"/> </wsdl:input> <wsdl:output name="findByTestcaseIdResponse"> <wsdlsoap:body use="literal"/> </wsdl:output> </wsdl:operation> <wsdl:operation name="findByIds"> <wsdlsoap:operation soapAction=""/> <wsdl:input name="findByIdsRequest"> <wsdlsoap:body use="literal"/> </wsdl:input> <wsdl:output name="findByIdsResponse"> <wsdlsoap:body use="literal"/> </wsdl:output> </wsdl:operation> <wsdl:operation name="findByNames"> <wsdlsoap:operation soapAction=""/> <wsdl:input name="findByNamesRequest"> <wsdlsoap:body use="literal"/> </wsdl:input> <wsdl:output name="findByNamesResponse"> <wsdlsoap:body use="literal"/> </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:service name="Remote"> <wsdl:port name="RemoteHttpPort" binding="tns:RemoteHttpBinding"> <wsdlsoap:address location="http://localhost/services/remote"/> </wsdl:port> </wsdl:service> </wsdl:definitions>