Search code examples
phpsoapautoloadnusoap

Registering namespaced PHP class methods with NuSoap


Is it possible to register a PHP autoloaded namespaced class method with the NuSoap library? To be clear, the PHP class is namespaced. This is not a question about XML namespacing.

For example, if I had a class defined in some file:

<?php

  namespace \My\Fancy\Namespace;

  class MyClass {
       public static function foo() { /* ... */ }
       // ...
  }

and I wanted to register it with my soap server:

    <?php

    use \My\Fancy\Namespace\MyClass; // autoloaded

    $server = new soap_server();

    // ... server configuration ...

    $server->register(
        'MyClass..foo'  // This does not work
        // ... etc. ...
    );

I've run so many searches for this with no luck, so I hope I'm not asking a bad question.


Solution

  • On nusoap_server class in invoke_method method, the code does not allow to use namespaces.

    function invoke_method() {
        // many lines of code...
    
        $class = '';
        $method = '';
        if (strlen($delim) > 0 && substr_count($this->methodname, $delim) == 1) {
            $try_class = substr($this->methodname, 0, strpos($this->methodname, $delim));
            if (class_exists($try_class)) {
                // get the class and method name
                $class = $try_class;
                $method = substr($this->methodname, strpos($this->methodname, $delim) + strlen($delim));
                $this->debug("in invoke_method, class=$class method=$method delim=$delim");
            } else {
                $this->debug("in invoke_method, class=$try_class not found");
            }
        } else {
            $try_class = '';
            $this->debug("in invoke_method, no class to try");
        }
    
        // many lines of code...
    }
    

    But thank god for open source so lets modify the code!
    This is what you could do:

    function invoke_method() {
        // many lines of code...
    
        $class = '';
        $method = '';
        if (strlen($delim) > 0 && substr_count($this->methodname, $delim) == 1) {
            $try_class = substr($this->methodname, 0, strpos($this->methodname, $delim));
            if (class_exists($try_class)) {
                // get the class and method name
                $class = $try_class;
                $method = substr($this->methodname, strpos($this->methodname, $delim) + strlen($delim));
                $this->debug("in invoke_method, class=$class method=$method delim=$delim");
            } else {
                $this->debug("in invoke_method, class=$try_class not found");
            }
        } elseif (strlen($delim) > 0 && substr_count($this->methodname, $delim) > 1) {
            $split = explode($delim, $this->methodname);
            $method = array_pop($split);
            $class = implode('\\', $split);
        } else {
            $try_class = '';
            $this->debug("in invoke_method, no class to try");
        }
    
        // many lines of code...
    }
    

    Explaining:

    // Example of namespaced class
    // $this->methodname = 'Namespace.Namespace2.Class.MethodName';
    
    // Has delimiter "." or ".." more than one time.
    if (strlen($delim) > 0 && substr_count($this->methodname, $delim) > 1) {
        // code below
    }
    
    // Transform in array
    $split = explode($delim, $this->methodname);
    // $split = array('Namespace', 'Namespace2', 'Class', 'MethodName')
    
    // Get the last item (method name) and remove from array.
    $method = array_pop($split);
    // $method = 'MethodName'
    // $split = array('Namespace', 'Namespace2', 'Class')
    
    // Transform the class name
    $class = implode('\\', $split);
    // $class = 'Namespace\Namespace2\Class'
    

    With this simple modification you can have the PHP namespace feature working.
    I know that a long time passes but I hope to help some one with this answer.