1

I'm creating a client to a third-party soap web service in my application. Here is the way I'm thinking of doing it:

  • Create a ClientFactory that makes a client based on the wsdl file, and sets needed options on it, then returns it.
  • Have several Request objects, preferably implementing the Request interface, that take the Client as their constructor argument, and then make requests to the web service through that client.

Here is a short example to illustrate my point.

class ClientFactory
{

    public function create()
    {
        return new \SoapClient('http://www.example.com/example.wsdl', [
            'trace' => true
        ]);
    }

}

class LockSeatRequest implements RequestInterface
{

    public function __construct(Client $client)
    {
        $this->client = $client;
    }

    public function execute($id, $count, $date)
    {
        $result = $this->client->lockSeat($id, $count, $date);

        // Make some changes to $result here...

        return $result;
    }

}

interface Request
{

    // what should I put in here?

}

Client code example:

$client = $clientFactory->create();
$lockSeatRequest = new lockSeatRequest($client);
$lockSeatRequest->execute(1, 5, '2015-04-04');

My problem here is that the number of arguments, and the type of arguments, are different from request to request, and this makes it impossible to define an interface. The way I have seen it done in other PHP libraries is to accept an array of parameters, but my issue with that approach is that it makes the user have to look up the parameters for each function call instead of making it explicit. Also, I would then have to add cruft such as checking whether the right keys are defined in the array, to each Request, instead of having the language ensure each parameter with the right type is passed to the function.

How can I have multiple methods, each of them requiring a different number of arguments, but still have them implement a particular interface?

Or, am I seeing this totally wrong?

6
  • 2
    Can you give a short example for how the different requests are made "through that client"? Who is calling whom here? And which parameters control which request arguments are the correct ones?
    – Doc Brown
    Dec 28, 2015 at 10:47
  • Why dont you have methods on the client for the various operations? Iwle client.DoThing(argument1, argument2...)
    – Ewan
    Dec 28, 2015 at 11:08
  • I added a code example. Dec 28, 2015 at 12:02
  • @Ewan, the Client class will get too big, since those functions do transformations on the data they receive from the third-party web service to make it consumable by higher-level classes. Dec 28, 2015 at 12:03
  • Why not use a code generator to convert the service's WSDL to code, then use that generated code (possibly with a custom wrapper)? Code generators will automatically create the relevant argument structure.
    – Brian
    Dec 28, 2015 at 16:07

1 Answer 1

1

I would consider moving the params to the __construct() so each request will do only one thing.

I would also consider decoule the params out using valueobject.

Something like this:

class LockSeatRequest implements RequestInterface
{

    public function __construct(Client $client, LockSeatRequestValueObject $params)
    {
        $this->client = $client;
        $this->params = $params;
    }

    public function execute()
    {
        $result = $this->client->lockSeat($this->params->getId(), $this->params->getCount(), $this->params->getDate());

        // Make some changes to $result here...

        return $result;
    }

}

interface Request
{

    public function execute();
}

class LockSeatRequestValueObject
{
    private $id;
    ....

    public function __construct ($id, $count, $date)
    // or in php7
    // public function __construct (int $id, int $count, \DateTime $date)
    {
        $this->id = $id;
        $this->validate(); // Might be redundant in php7
    }

    public function getId()
    {
        return $this->id;
    }
    ......
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.