Oliver Bayes-Shelton
Oliver Bayes-Shelton

Reputation: 6292

Dependency injection with dynamic parameter

So I have done some searching on here but I cannot find the answer...

I have the following class:

class SomeCrmService
{
    public function __construct($endpoint, $key)
    {
        $this->request = new Request($endpoint);
        $this->request->setOption(CURLOPT_USERPWD, $key);
        $this->request->setOption(CURLOPT_HTTPHEADER, array(
            "Content-type : application/json;", 'Accept : application/json'
        ));
        $this->request->setOption(CURLOPT_TIMEOUT, 120);
        $this->request->setOption(CURLOPT_SSL_VERIFYPEER, 0);
    }

The problem I have is that I wanted to inject Request so that I could change the library I was using and it would be easier to mock when testing. I needed to pass in the $endpoint var which could be (customer, contact, etc) so I thought this was the only option to do it like the above. Is there a way to make this code slightly better and inject Request and use a mutator or something to set the $endpoint var?

Thanks

Upvotes: 2

Views: 721

Answers (2)

honzalilak
honzalilak

Reputation: 376

Use the Factory design pattern:

<?php

class RequestFactory {

    public function create($endpoint) {
        return new Request($endpoint);
    }

}

class SomeCrmService
{
    public function __construct($endpoint, $key, RequestFactory $requestFactory)
    {
        // original solution
        // $this->request = new Request($endpoint);
        // better solution
        $this->request = $requestFactory->create($endpoint);

        // here comes the rest of your code
    }

}

By using the factory design pattern you don't have to extend other classes - because in fact you dont want to extend them. You are not adding new functionality, your desire is to have testable environment).

Upvotes: 2

Will
Will

Reputation: 24689

I would recommend an approach like this, where you extend the third-party Request class and allow it to accept an $endpoint along with a getter:

<?php

class EndpointRequest extends Request
{
    protected $endpoint;

    public function __construct($endpoint, $key)
    {
        $this->setOption(CURLOPT_USERPWD, $key);
        $this->setOption(CURLOPT_HTTPHEADER, array(
            "Content-type : application/json;", 'Accept : application/json'
        ));
        $this->setOption(CURLOPT_TIMEOUT, 120);
        $this->setOption(CURLOPT_SSL_VERIFYPEER, 0);
    }

    public function getEndpoint()
    {
        return $this->endpoint;
    }
}

class SomeCrmService
{
    public function __construct(EndpointRequest $request)
    {
        $this->request = $request;
    }
}

Upvotes: 2

Related Questions