简体   繁体   中英

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

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;
    }
}

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).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM