I have developed a WebService in Symfony2 framework. It works perfectly in DEV environment in either my local PC and in my hosting server (both have PHP version 5.3.8), but in PROD environment only works in my local PC, not in my hosting.
This is the WebService controller:
<?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 is the WebService. The testingAction is an action to make some calls to it.
The class that discovers the WSDL is:
<?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\" ?>
";
$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/\">
";
$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>
";
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 = "
<!-- Ports -->
" . '<portType name="' . $this->service_name . 'Port">';
$bindingWSDL = "
<!-- SOAP Bindings -->
" . '<binding name="' . $this->service_name . 'Binding" type="tns:' . $this->service_name . "Port\">
<soap:binding style=\"rpc\" transport=\"http://schemas.xmlsoap.org/soap/http\" />
";
$serviceWSDL = "
<!-- Service (location) -->
" . '<service name="' . $this->service_name . "\">
<documentation />
<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() . "\" />
</port>
</service>
";
$messageWSDL = "
<!-- Messages -->
";
$complexType = '';
foreach ($methods as $method) {
if ($method->isPublic() && !$method->isConstructor()) {
$portTypeWSDL.= '<operation name="' . $method->getName() . "\">
" . '<input message="tns:' . $method->getName() . "Request\" />
<output message=\"tns:" . $method->getName() . "Response\" />
</operation>
";
$bindingWSDL.= '<operation name="' . $method->getName() . "\">
" . '<soap:operation soapAction="urn:' . $this->service_name . '#' . $this->class_name . '#' . $method->getName() . "\" />
<input><soap:body use=\"encoded\" namespace=\"urn:$this->service_name\" encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\" />
</input>
<output>
<soap:body use=\"encoded\" namespace=\"urn:$this->service_name\" encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\" />
</output>
</operation>
";
$messageWSDL.= "<!-- Input parameters for method {$method->getName()} -->
" . '<message name="' . $method->getName() . "Request\">
";
$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}\" />
";
}
$messageWSDL.= "</message>
";
$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 . '">' . "
" . '<xsd:sequence>' . "
";
foreach ($properties as $property)
$complexType .= '<xsd:element minOccurs="0" maxOccurs="1" name="' . $property->getName() . '" type="xsd:string"/>' . "
";
$complexType .= "</xsd:sequence>
</xsd:complexType>
";
}
}
if ($is_array) {
$complexType .= '<xsd:complexType name="ArrayOf' . ucfirst($return) . '">' . "
" . '<xsd:sequence>' . "
";
$complexType .= '<xsd:element minOccurs="0" maxOccurs="unbounded" name="' . $return . '" nillable="true" type="tns:' . $return . '" />' . "
";
$complexType .= "</xsd:sequence>
</xsd:complexType>
";
$return = 'ArrayOf' . ucfirst($return);
}
}
} else {
$return = 'string';
}
$messageWSDL.= "<!-- Output for method {$method->getName()} -->
" . '<message name="' . $method->getName() . "Response\">
";
$messageWSDL.= '<part name="' . $method->getName() . "\" type=\"{$typePrefix}:{$return}\" />
";
$messageWSDL.= "</message>
";
}
}
$headerWSDL = str_replace('{{complexTypes}}', $complexType, $headerWSDL);
$portTypeWSDL.= "</portType>
";
$bindingWSDL.= "</binding>
";
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\" ?>
<disco:discovery xmlns:disco=\"http://schemas.xmlsoap.org/disco/\" xmlns:scl=\"http://schemas.xmlsoap.org/disco/scl/\">
<scl:contractRef ref=\"http://" . $this->request->getHttpHost() . $this->request->getScriptName() . $this->request->getPathInfo() . "?wsdl\" />
</disco:discovery>";
}
}
?>
These are the addional files that maybe are relevant:
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
routing.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>
Any help will be greatly appreciated
Thanks Jaime