senty
senty

Reputation: 12857

Class Organisation of Api Wrappers

I am trying to learn creating php wrappers for 3rd party apis. However I am confused on implementing multiple classes extended/implemented each other.

class Api {
   protected $username;
   protected $password;
   protected $wsdl = "http://example.com"

   protected $client;
   protected $account;

   public function __construct($username, $password)
   {
       $this->client = new SoapClient($this->wsdl);
       $authData = [
           "Credentials"   => [
               "Username"          => $username,
               "Password"          => $password
           ]
       ];

       $this->makeCall('AuthenticateUser', $authData);
       $this->account = $this->makeCall('GetAccountInfo', ["Authenticator" => $this->authenticator]);
   }

   protected function makeCall($method, $data) {
       $result = $this->client->$method($data);
       $this->authenticator = $result->Authenticator;
       return $result;
   }
}

Until here, it makes sense. However, at this point I don't want to add all methods in this class. Thus, I decided to create a separate class for each method. And there, here problem begins.

class AddressValidator extends Api
{
    public function validateAddress($data) {
       $response = $this->makeCall('validateAddress', $data);
       dd($response);
    }
}

Logically, how I need to call the wrapper (in my controller) is like this below, right?

$api = new Api($username, $password);
$api->validateAddress($params);   // but I can't call this line with this setup

Instead, this works:

$api = new ValidateAddress($username, $password);
$api->validateAddress($params);

Makes sense, but is this the good way of organising it?

What is the beautiful way of setting up api wrapper? By the way, maybe I am wrong with this approach completely. I'd be happy to hear what you think

Upvotes: 1

Views: 167

Answers (2)

Scamtex
Scamtex

Reputation: 181

Maybe something like

class Api {
    private $class;
       .
       .
    public function __construct($username, $password, $class_name) {
        .
        .
        $this->class = new $class_name();
    }

    public function ApiCall($func, ...$arguments) {
        $this->class->$func($arguments);
    }
}

I'm not sure if this makes things easier for you, but it works.

Upvotes: 1

Sean
Sean

Reputation: 480

Instead of extending your API class, you could use a trait to organize your methods.

    class Api {
        use ValidateAddressTrait;

        ...
    }

Trait:

    trait ValidateAddressTrait {
        public function validateAddress($data) {
            $response = $this->makeCall('validateAddress', $data);
            dd($response);
        }
    }

Use:

    $api = new Api($username, $password);
    $api->validateAddress($params);

This isn't exactly the intent of a trait but I think it can give you the result you are looking for.

Upvotes: 1

Related Questions