0

我在 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>";
    }

}

?>

这些是可能相关的附加文件:

配置.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>

任何帮助将不胜感激

谢谢詹姆

4

0 回答 0