Part of the EllisLab Network

Bug Report

XML-RPC Server: Mapping incoming requests to the external classes

Date: 03/18/2008 Severity: Minor
Status: Resolved Reporter: phildawson
Version: 1.6.1
Keywords: Libraries, XML-RPC Class

Description

The user guide explains how to set up an array with mapping instructions so that incoming requests can be sent to the appropriate class and method for processing.

A debug message is generated from line 268 in Xmlrpcs.php when the code checks to see if the method is callable and fails if the external class has not been loaded.

if ($objectCall &&
!is_callable(array($method_parts[‘0’],$method_parts[‘1’])))


To solve this issue any classes helping requests could be turned into library helpers using get_instance() and loaded using $this->load->library();

This will then pass the check, but we come to the next problem of making the call on line 324 futher down..

$CI =& get_instance();
return $CI->$method_parts[‘1’]($m);
//$class = new $method_parts[‘0’];
//return $class->$method_parts[‘1’]($m);
//return call_user_func(array(&$method_parts[‘0’],$method_parts[‘1’]), $m);


This is just calling the method on the CI object which wont work unless $method_parts[‘0’] was the name of the XML-RPC server class.

You could uncomment and use these two lines again which will work as long as we loaded the libraries.

$class = new $method_parts[‘0’];
return $class->$method_parts[‘1’]($m);

But then won’t work for the request methods inside the Server Controller unless you change the call depending on $method_parts[‘0’]
We also would lose calling Controller methods…

Code Sample

$config['functions']['new_post']  = array('function' => 'My_blog.new_entry');

Expected Result

The new_entry method will be called in the My_blog class to process the new_post request.

Actual Result

This is not a known method for this XML-RPC Server

Comment on Bug Report

Page 1 of 1 pages
Posted by: barbazul on 31 March 2008 8:21am
barbazul's avatar

It is not clear what is exactly the problem here.

Is it that you have tried the example code and got an error?
If that is so, I’ve tried the examples myself and got no error at all.

Could you please provide some example code of what you were trying to do (controller code I mean).
Also, is there any forum thread related to this bug?

Posted by: Kiall on 7 April 2008 11:44am
no avatar

Hiya, I think i understand what the original poster was trying to say.
The short version:

xmlrpc methods can only be mapped to php functions in the same class as the xmlrpc server and not to php functions in other classes.

The long version:

I think what they mean is if you have a controller “Xmlrpc_server” and in it you copy and paste the index function from example server code, but change the line:

$config[‘functions’][‘Greetings’] = array(‘function’ => ‘Xmlrpc_server.process’);

to:

$config[‘functions’][‘Greetings’] = array(‘function’ => ‘Other_class.process’);

and then have a new controller, Other_class - and copy and paste the process function (and of course, load xmlrpc/xmlrpcs etc)

It does not work…

Posted by: kylehase on 18 April 2008 11:11pm
kylehase's avatar

I have also confirmed this bug.  See thread
http://codeigniter.com/forums/viewthread/76801/

Posted by: Derek Jones on 8 May 2008 1:42pm
Derek Jones's avatar

Took a bit of a different approach, but should still solve the problem.

Posted by: Elliot Haughin on 17 May 2008 8:51am
Elliot Haughin's avatar

I don’t think this problem is solved. I’m still having it:

class Api extends Controller {
    
        
function Api()
        
{
            parent
::Controller();
            
            
log_message('debug', 'Api received method');
        
}
        
        
function index()
        
{
            $this
->load->library('xmlrpc');
            
$this->load->library('xmlrpcs');
            
$this->load->library('server');

            
$config['functions']['Posts.getLatest']     = array('function' => 'Posts.getLatest');
            
$config['functions']['Posts.getSingle']     = array('function' => 'Posts.getSingle');
            
            
$config['object'] = $this;
            
            
$this->xmlrpcs->initialize($config);
            
            
$this->xmlrpcs->serve();
        
}
    }

Then have a posts.php controller with:

<?php
    
    
class Posts extends Controller {

        
function Posts()
        
{
            parent
::Controller();
            
            
$this->load->library('xmlrpc');
            
$this->load->library('xmlrpcs');
            
$this->load->library('server');
        
}
        
        
function getLatest($request)
        
{
            $params
= $this->server->prep_request($request);
            
            if    (!empty(
$params[0]))
            
{
                $limit
= $params[0];
            
}
            
else
            
{
                $limit
= 'none';
            
}
            
            $response
= array('you want posts! limit '.$limit, 'string');
            
            return
$this->server->send_response($response);
        
}
    }

?>

But, alas, my code fails with method not found too.

Posted by: Derek Jones on 17 May 2008 9:02am
Derek Jones's avatar

The object that you feed to $config[‘object’] needs to be an instantiated class object that is callable via $OBJ->method_name(), so if you are feeding it $this, it would have to be a method within that class, in this case, the Api class.  Make sense?

Posted by: Jamie Rumbelow on 14 June 2008 9:08pm
Jamie Rumbelow's avatar

Derek, any chance for a real life example? I can’t actually seem to work out WHAT object to feed to the [‘object’]

I think I understand it, but if I wanted to load like, 5 different classes, that’s not gonna work.

Posted by: Derek Jones on 15 June 2008 8:44pm
Derek Jones's avatar

The object you feed object must be a class object containing the methods that are going to be called by the XML RPC server.  If the methods are in the controller handling the request, then you would send $this, otherwise, you would instantiate a class object or assign it to a variable and use that instead.  You are correct, you cannot have five different classes handling calls made to the same controller, at least, not without some pre-mapping in your controller making the determination of which object to send.

Posted by: blitux on 5 September 2008 7:53pm
blitux's avatar

It seems that this bug is not fixed at all in v1.7.0 (svn).

I have compared two files: Xmlrpcs.php on v1.6.3 and the same file on v1.7.0 (svn). There were no changes. I really think this IS NOT a minor issue.

This is an extract from documentation (v1.6.3)

In other words, if an XML-RPC Client sends a request for the new_post method, your server will load the My_blog class and call the new_entry function. If the request is for the update_post method, your server will load the My_blog class and call the update_entry function.

This workaround are somehow like a Q&D solution and do not reflects the way this should be working as exposed in documentation.

This bug is not resolved at all.

Posted by: Derek Jones on 5 September 2008 8:11pm
Derek Jones's avatar

The files from 1.6.3 to 1.7.0 haven’t changed here, blitux, as this was committed on may 08.  We’re using this ourselves, and I’ve done so on a side application as well.  Are you passing the class object?  You’re free to make a feature request in the forums if you have suggestions on improvements, but your comment here doesn’t demonstrate any bug.

Posted by: blitux on 5 September 2008 9:06pm
blitux's avatar

Well, I guess at least documentation must be changed to reflect this as it may be confusing for some people (it was for me). I can pass the class object, but what if I have a lot of classes/controllers?

I was thinking about this, and maybe I can have a unique controller, where I can map all the functions that are currently in separate libraries, and feed it to [‘object’]. There are a lot of solutions for this issue.

But I think that is not the way to go with MVC. I mean.. if you have a lot of controllers to logically separate your app for the sake of modularity (even if you’re building a web app or a web service) you will have some troubles with this. Nobody wants (i guess) to have a “superclass” or “supercontroller” with a lot of functions and loading a lot of models inside a single controller.

I’ll make a Feature Request, but I’m still thinking that this should be fixed in the code, or in the docs.

Thanks for the quick response smile

Name:

Email:

Location:

URL:

Remember my personal information

Notify me of follow-up comments?