Symfony2 フレームワークで WebService を開発しました。ローカル PC とホスティング サーバー (どちらも PHP バージョン 5.3.8 を使用) の DEV 環境では完全に動作しますが、PROD 環境ではローカル PC でのみ動作し、ホスティングでは動作しません。
これは WebService コントローラーです。
<?php
namespace Desytec\ServiciosBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\HttpFoundation\Response;
use Desytec\ServiciosBundle\Services\SoapDiscovery;
class FeriadosController extends Controller {
/**
* @Route("/feriados")
*/
public function indexAction() {
$response = new Response();
$response->headers->set('Content-Type', 'text/xml; charset=UTF-8');
$request = $this->getRequest();
if (strcasecmp($request->getQueryString(), 'wsdl') == 0) {
// Crea el servidor de descubrimiento
$disco = new SoapDiscovery($request, 'Desytec\ServiciosBundle\Services\FeriadosService', 'Desytec_Feriados');
$response->setContent($disco->getWSDL());
} else {
$server = new \SoapServer('http://' . $request->getHttpHost() . $request->getScriptName() . $request->getPathInfo() . '?wsdl');
$server->setObject($this->get('feriados_service'));
ob_start();
$server->handle();
if (ob_get_length() > 0) {
$response->setContent(ob_get_clean());
}
}
return $response;
}
/**
* @Route("/testing")
* @Template()
*/
public function testingAction() {
//date_default_timezone_set('America/Santiago');
//$fecha = new \DateTime();
//echo sha1(sha1('761463993'.$fecha->format('YmdHisu'))).'<br />';
$client = new \SoapClient('http://' . $this->getRequest()->getHttpHost() . '/feriados?wsdl');
var_dump($client->__getFunctions()); $client = new \SoapClient('http://' . $this->getRequest()->getHttpHost() . $this->getRequest()->getScriptName() . '/feriados?wsdl');
$result = $client->IsHoliday('8cd4c502f69b5606a8bef291deaac1ba83bb7727', 'cl', 2013, 6, 29);
if ($result)
echo 'Es feriado';
else
echo 'No es feriado';
$feriados = $client->GetHolidays('8cd4c502f69b5606a8bef291deaac1ba83bb7727', 'cl', 2013, 6);
var_dump($feriados);
$numero_dias = $client->GetDateDifference('8cd4c502f69b5606a8bef291deaac1ba83bb7727', 'cl', '2013-08-01', '2013-08-31');
echo $numero_dias;
$diferencias = $client->GetDatesDifference('8cd4c502f69b5606a8bef291deaac1ba83bb7727', 'cl', '2013-08-01;2013-09-01', '2013-08-31;2013-09-30');
var_dump($diferencias);
return array();
}
}
indexAction は Web サービスです。testingAction は、それを呼び出すためのアクションです。
WSDL を検出するクラスは次のとおりです。
<?php
/**
* Copyright (c) 2005, Braulio José Solano Rojas
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
* Neither the name of the Solsoft de Costa Rica S.A. nor the names of its contributors may
* be used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
* @version $Id$
* @copyright 2005
*/
namespace Desytec\ServiciosBundle\Services;
/**
* SoapDiscovery Class that provides Web Service Definition Language (WSDL).
*
* @package SoapDiscovery
* @author Braulio Jos� Solano Rojas
* @copyright Copyright (c) 2005 Braulio José Solano Rojas
* @version $Id$
* @access public
* */
class SoapDiscovery {
private $class_name = '';
private $service_name = '';
private $request;
/**
* SoapDiscovery::__construct() SoapDiscovery class Constructor.
*
* @param string $class_name
* @param string $service_name
* */
public function __construct($request, $class_name = '', $service_name = '') {
$this->request = $request;
$this->class_name = $class_name;
$this->service_name = $service_name;
}
/**
* SoapDiscovery::getWSDL() Returns the WSDL of a class if the class is instantiable.
*
* @return string
* */
public function getWSDL() {
if (empty($this->service_name)) {
throw new Exception('No service name.');
}
$headerWSDL = "<?xml version=\"1.0\" ?>\n";
$headerWSDL .= "<definitions xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"
xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\"
xmlns:tns=\"urn:$this->service_name\"
xmlns:soap=\"http://schemas.xmlsoap.org/wsdl/soap/\"
xmlns:wsdl=\"http://schemas.xmlsoap.org/wsdl/\"
xmlns=\"http://schemas.xmlsoap.org/wsdl/\"
targetNamespace=\"urn:$this->service_name\">";
//$headerWSDL.= "<definitions name=\"$this->service_name\" targetNamespace=\"urn:$this->service_name\" xmlns:wsdl=\"http://schemas.xmlsoap.org/wsdl/\" xmlns:soap=\"http://schemas.xmlsoap.org/wsdl/soap/\" xmlns:tns=\"urn:$this->service_name\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\" xmlns=\"http://schemas.xmlsoap.org/wsdl/\">\n";
$headerWSDL.= "<types>
<xsd:schema targetNamespace=\"urn:$this->service_name\">
<xsd:import namespace=\"http://schemas.xmlsoap.org/soap/encoding/\" />
<xsd:import namespace=\"http://schemas.xmlsoap.org/wsdl/\" />
</xsd:schema>
{{complexTypes}}
</types>\n";
if (empty($this->class_name)) {
throw new Exception('No class name.');
}
$class = new \ReflectionClass($this->class_name);
if (!$class->isInstantiable()) {
throw new Exception('Class is not instantiable.');
}
$methods = $class->getMethods();
$portTypeWSDL = "\n<!-- Ports -->\n" . '<portType name="' . $this->service_name . 'Port">';
$bindingWSDL = "\n<!-- SOAP Bindings -->\n" . '<binding name="' . $this->service_name . 'Binding" type="tns:' . $this->service_name . "Port\">\n<soap:binding style=\"rpc\" transport=\"http://schemas.xmlsoap.org/soap/http\" />\n";
$serviceWSDL = "\n<!-- Service (location) -->\n" . '<service name="' . $this->service_name . "\">\n<documentation />\n<port name=\"" . $this->service_name . 'Port" binding="tns:' . $this->service_name . "Binding\"><soap:address location=\"http://" . $this->request->getHttpHost() . $this->request->getScriptName() . $this->request->getPathInfo() . "\" />\n</port>\n</service>\n";
$messageWSDL = "\n<!-- Messages -->\n";
$complexType = '';
foreach ($methods as $method) {
if ($method->isPublic() && !$method->isConstructor()) {
$portTypeWSDL.= '<operation name="' . $method->getName() . "\">\n" . '<input message="tns:' . $method->getName() . "Request\" />\n<output message=\"tns:" . $method->getName() . "Response\" />\n</operation>\n";
$bindingWSDL.= '<operation name="' . $method->getName() . "\">\n" . '<soap:operation soapAction="urn:' . $this->service_name . '#' . $this->class_name . '#' . $method->getName() . "\" />\n<input><soap:body use=\"encoded\" namespace=\"urn:$this->service_name\" encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\" />\n</input>\n<output>\n<soap:body use=\"encoded\" namespace=\"urn:$this->service_name\" encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\" />\n</output>\n</operation>\n";
$messageWSDL.= "<!-- Input parameters for method {$method->getName()} -->\n" . '<message name="' . $method->getName() . "Request\">\n";
$parameters = $method->getParameters();
foreach ($parameters as $parameter) {
if ($method->getDocComment()) {
$pattern = '/@param\s+(string|boolean|int|integer|float|double)/i';
preg_match($pattern, $method->getDocComment(), $matches);
$type = $matches[1];
} else {
$type = 'string';
}
$messageWSDL.= '<part name="' . $parameter->getName() . "\" type=\"xsd:{$type}\" />\n";
}
$messageWSDL.= "</message>\n";
$typePrefix = 'xsd';
if ($method->getDocComment()) {
$pattern = '/@return\s+(string|boolean|int|integer|float|double)/i';
preg_match($pattern, $method->getDocComment(), $matches);
if (count($matches) > 0)
$return = $matches[1];
else {
$typePrefix = 'tns';
$pattern = '/@return\s+\w+(\[.*])?/i';
preg_match($pattern, $method->getDocComment(), $matches);
$matches = explode(' ', $matches[0]);
$return = trim($matches[1]);
$is_array = substr($return, 0, 6) == 'array[';
if ($is_array) {
$return = substr($return, 6, strlen($return) - 7);
}
if (strstr($complexType, 'name="' . $return . '"') === FALSE) {
$pattern = '/(string|boolean|int|integer|float|double)/i';
preg_match($pattern, $return, $matches);
if (count($matches) == 0) {
if ($return[0] == '\\')
$refClass = $return;
else
$refClass = $class->getNamespaceName() . '\\' . $return;
$type = new \ReflectionClass($refClass);
$properties = $type->getProperties();
$complexType .= '<xsd:complexType name="' . $return . '">' . "\n" . '<xsd:sequence>' . "\n";
foreach ($properties as $property)
$complexType .= '<xsd:element minOccurs="0" maxOccurs="1" name="' . $property->getName() . '" type="xsd:string"/>' . "\n";
$complexType .= "</xsd:sequence>\n</xsd:complexType>\n";
}
}
if ($is_array) {
$complexType .= '<xsd:complexType name="ArrayOf' . ucfirst($return) . '">' . "\n" . '<xsd:sequence>' . "\n";
$complexType .= '<xsd:element minOccurs="0" maxOccurs="unbounded" name="' . $return . '" nillable="true" type="tns:' . $return . '" />' . "\n";
$complexType .= "</xsd:sequence>\n</xsd:complexType>\n";
$return = 'ArrayOf' . ucfirst($return);
}
}
} else {
$return = 'string';
}
$messageWSDL.= "<!-- Output for method {$method->getName()} -->\n" . '<message name="' . $method->getName() . "Response\">\n";
$messageWSDL.= '<part name="' . $method->getName() . "\" type=\"{$typePrefix}:{$return}\" />\n";
$messageWSDL.= "</message>\n";
}
}
$headerWSDL = str_replace('{{complexTypes}}', $complexType, $headerWSDL);
$portTypeWSDL.= "</portType>\n";
$bindingWSDL.= "</binding>\n";
return sprintf('%s%s%s%s%s%s', $headerWSDL, $messageWSDL, $portTypeWSDL, $bindingWSDL, $serviceWSDL, '</definitions>');
}
/**
* SoapDiscovery::getDiscovery() Returns discovery of WSDL.
*
* @return string
* */
public function getDiscovery() {
return "<?xml version=\"1.0\" ?>\n<disco:discovery xmlns:disco=\"http://schemas.xmlsoap.org/disco/\" xmlns:scl=\"http://schemas.xmlsoap.org/disco/scl/\">\n<scl:contractRef ref=\"http://" . $this->request->getHttpHost() . $this->request->getScriptName() . $this->request->getPathInfo() . "?wsdl\" />\n</disco:discovery>";
}
}
?>
関連する可能性のある追加のファイルは次のとおりです。
config.yml:
imports:
- { resource: parameters.yml }
- { resource: security.yml }
framework:
#esi: ~
#translator: { fallback: %locale% }
secret: %secret%
router:
resource: "%kernel.root_dir%/config/routing.yml"
strict_requirements: ~
form: ~
csrf_protection: ~
validation: { enable_annotations: true }
templating:
engines: ['twig']
#assets_version: SomeVersionScheme
default_locale: "%locale%"
trusted_proxies: ~
session: ~
fragments: ~
http_method_override: true
# Twig Configuration
twig:
debug: %kernel.debug%
strict_variables: %kernel.debug%
# Assetic Configuration
assetic:
debug: %kernel.debug%
use_controller: false
bundles: [ ]
#java: /usr/bin/java
filters:
cssrewrite: ~
#closure:
# jar: %kernel.root_dir%/Resources/java/compiler.jar
#yui_css:
# jar: %kernel.root_dir%/Resources/java/yuicompressor-2.4.7.jar
# Doctrine Configuration
doctrine:
dbal:
driver: %database_driver%
host: %database_host%
port: %database_port%
dbname: %database_name%
user: %database_user%
password: %database_password%
charset: UTF8
# if using pdo_sqlite as your database driver, add the path in parameters.yml
# e.g. database_path: %kernel.root_dir%/data/data.db3
# path: %database_path%
orm:
auto_generate_proxy_classes: %kernel.debug%
auto_mapping: true
# Swiftmailer Configuration
swiftmailer:
transport: %mailer_transport%
host: %mailer_host%
username: %mailer_user%
password: %mailer_password%
spool: { type: memory }
services:
feriados_service:
class: Desytec\ServiciosBundle\Services\FeriadosService
arguments: ["@database_connection"]
config_dev.yml
imports:
- { resource: config.yml }
framework:
router:
resource: "%kernel.root_dir%/config/routing_dev.yml"
strict_requirements: true
profiler: { only_exceptions: false }
web_profiler:
toolbar: true
intercept_redirects: false
monolog:
handlers:
main:
type: stream
path: %kernel.logs_dir%/%kernel.environment%.log
level: debug
firephp:
type: firephp
level: info
chromephp:
type: chromephp
level: info
assetic:
use_controller: true
#swiftmailer:
# delivery_address: me@example.com
config_prod.yml
imports:
- { resource: config.yml }
#framework:
# validation:
# cache: apc
#doctrine:
# orm:
# metadata_cache_driver: apc
# result_cache_driver: apc
# query_cache_driver: apc
monolog:
handlers:
main:
type: fingers_crossed
action_level: error
handler: nested
nested:
type: stream
path: %kernel.logs_dir%/%kernel.environment%.log
level: debug
ルーティング.yml
_desytec:
resource: "@DesytecServiciosBundle/Resources/config/routing.yml"
routing_dev.yml
_wdt:
resource: "@WebProfilerBundle/Resources/config/routing/wdt.xml"
prefix: /_wdt
_profiler:
resource: "@WebProfilerBundle/Resources/config/routing/profiler.xml"
prefix: /_profiler
_configurator:
resource: "@SensioDistributionBundle/Resources/config/routing/webconfigurator.xml"
prefix: /_configurator
_main:
resource: routing.yml
@DesytecServiciosBundle/Resources/config/routing.yml
desytec_servicios:
resource: "@DesytecServiciosBundle/Controller/"
type: annotation
prefix: /
.htaccess
# Use the front controller as index file. It serves as a fallback solution when
# every other rewrite/redirect fails (e.g. in an aliased environment without
# mod_rewrite). Additionally, this reduces the matching process for the
# start page (path "/") because otherwise Apache will apply the rewriting rules
# to each configured DirectoryIndex file (e.g. index.php, index.html, index.pl).
DirectoryIndex app.php
<IfModule mod_rewrite.c>
RewriteEngine On
# Determine the RewriteBase automatically and set it as environment variable.
# If you are using Apache aliases to do mass virtual hosting or installed the
# project in a subdirectory, the base path will be prepended to allow proper
# resolution of the app.php file and to redirect to the correct URI. It will
# work in environments without path prefix as well, providing a safe, one-size
# fits all solution. But as you do not need it in this case, you can comment
# the following 2 lines to eliminate the overhead.
RewriteCond %{REQUEST_URI}::$1 ^(/.+)/(.*)::\2$
RewriteRule ^(.*) - [E=BASE:%1]
# Redirect to URI without front controller to prevent duplicate content
# (with and without `/app.php`). Only do this redirect on the initial
# rewrite by Apache and not on subsequent cycles. Otherwise we would get an
# endless redirect loop (request -> rewrite to front controller ->
# redirect -> request -> ...).
# So in case you get a "too many redirects" error or you always get redirected
# to the start page because your Apache does not expose the REDIRECT_STATUS
# environment variable, you have 2 choices:
# - disable this feature by commenting the following 2 lines or
# - use Apache >= 2.3.9 and replace all L flags by END flags and remove the
# following RewriteCond (best solution)
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^app\.php(/(.*)|$) %{ENV:BASE}/$2 [R=301,L]
# If the requested filename exists, simply serve it.
# We only want to let Apache serve files and not directories.
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule .? - [L]
# Rewrite all other queries to the front controller.
RewriteRule .? %{ENV:BASE}/app.php [L]
</IfModule>
<IfModule !mod_rewrite.c>
<IfModule mod_alias.c>
# When mod_rewrite is not available, we instruct a temporary redirect of
# the start page to the front controller explicitly so that the website
# and the generated links can still be used.
RedirectMatch 302 ^/$ /app.php/
# RedirectTemp cannot be used instead
</IfModule>
</IfModule>
どんな助けでも大歓迎です
ありがとうハイメ