Shopify / shopify-php

MIT License
57 stars 25 forks source link

Make ShopifyClient more DI friendly #9

Closed tanigami closed 2 years ago

tanigami commented 7 years ago

Problem

if you wanna inject the dependency of ShopifyClient into some class from a DI container and you need to set $accessToken and a $shopName dynamically according to situations, you will want to set them after instantiation, but it's not easy because ShopifyClient first requires them as constructor arguments.

Approach

Stop requiring those constructor arguments and add some guard to avoid forgetting to set $accessToken and $shopName while allowing constructor arguments as it is.

<?php

use Shopify\ShopifyClient;

class SomeClass
{
    private $client;

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

    public doSomething($shop)
    {
        $this->client->setAccessToken($shop->getAccessToken());
        $this->client->setShopName($shop->getShopName())
        $products = $this->client->products->readList();
        // ...
    }
}

By the way, the class above can be tested like below for instance:

<?php

use Mockery;
use PHPUnit\Framework\TestCase;
use Shopify\ShopifyClient;
use Shopify\ShopifyProduct;

class SomeClassTest extends TestCase
{
    public function testDoSomething()
    {
        $mockProduct = Mockery::mock(ShopifyProduct::class);
        $mockProduct->shouldReceive('readList')->andReturn(/* some prepared response */);

        $mockClient = Mockery::mock(ShopifyClient::class);
        $mockClient->shouldReceive('setAccessToken');
        $mockClient->shouldReceive('setShopName');
        $mockClient->products = $mockProduct;

        $someClass = new SomeClass($mockClient);
        $someClass->doSomething($shop);

        // ...
    }
}

@rodolfobandeira @joshubrown Hope this change make sense. 😃

Lewiscowles1986 commented 6 years ago

There isn't a great cost to just instantiating a new Client though, at which point your problem is solved without DI.

You can keep connections open in a pool (which you'd create to receive ShopifyClient instances), making everything you've changed less useful.