Fundamentals 9 min read

Adapter Design Pattern for Integrating Multiple E‑Commerce APIs in PHP

This article explains the Adapter design pattern, illustrates the challenges of aggregating product data from diverse e‑commerce APIs, and provides a complete PHP implementation—including interface definitions, adaptor classes for Shopify, BigCommerce, and WooCommerce, and a ProductFeed aggregator—to achieve a maintainable, extensible solution.

php中文网 Courses
php中文网 Courses
php中文网 Courses
Adapter Design Pattern for Integrating Multiple E‑Commerce APIs in PHP

Design patterns are essential tools in object‑oriented programming, offering reusable solutions to common software design problems; structural design patterns focus on the relationships between classes and objects. This article discusses one such pattern, the Adapter.

The Adapter pattern allows the interface of an existing class to be converted into another interface, enabling incompatible interfaces to work together through an intermediate class.

Consider a product‑feed application that pulls product data from various e‑commerce APIs (Shopify, BigCommerce, WooCommerce, Prestashop) into a unified table for further processing and distribution. The challenges are that each API has different methods, parameters, and return formats, and adding a new source (e.g., Magento) would require changes throughout the application.

The Adapter pattern resolves these issues with four components:

Client (Target) : the class that uses the Target interface and wants to connect to multiple sources; in this example it is the ProductFeed class containing existing business logic.

Target : the interface defining the contract the client expects, here FeedAdapterInterface .

Adapter : a class implementing the Target interface, holding an instance of an Adaptee and translating calls from Target to the Adaptee . Examples are ShopifyApiAdapter , BigCommerceApiAdapter , and WooCommerceApiAdapter .

Adaptee : the existing classes with incompatible interfaces, such as ShopifyApi , BigCommerceApi , and WooCommerceApi .

First, define the client interface that specifies the required functionality:

<code>interface FeedAdapterInterface {
    /**
     * @return array<int, array<string, string>>
     */
    public function getFeed(): array;
}</code>

Next, define the adaptee (service) classes with their native methods:

<code>// Adaptee Classes aka Service classes

class ShopifyApi {
    public function fetchItems(): array {
        // Returns an `array` of products with `title`, `date`, `image`, `url`.
    }
}

class BigCommerceApi {
    public function getProducts(): array {
        // returns an array of products that have 'name', 'published_at', 'picture_url', 'url'
    }
}

class WooCommerceApi {
    public function getList(): array {
        // returns an array of products that have 'name', 'published_date', 'cover', 'link'
    }
}
</code>

Now create adapter classes that implement FeedAdapterInterface and translate the data into a uniform format:

<code>class ShopifyApiAdapter implements FeedAdapterInterface {
    public function __construct(public ShopifyApi $api) {}

    public function getFeed(): array {
        $products = $this->api->fetchItems();
        return array_map(function ($item) {
            return [
                'title' => $item['title'],
                'date'  => DateTime::createFromFormat('H:i:s Y-m-d', $item['date'])->format('Y-m-d H:i:s'),
                'img'   => $item['image'],
                'url'   => $item['url'],
            ];
        }, $products);
    }
}
</code>
<code>class BigCommerceApiAdapter implements FeedAdapterInterface {
    public function __construct(public BigCommerceApi $api) {}

    public function getFeed(): array {
        $products = $this->api->getProducts();
        return array_map(function ($item) {
            return [
                'title' => $item['name'],
                'date'  => DateTime::createFromFormat('H:i:s Y-m-d', $item['published_at'])->format('Y-m-d H:i:s'),
                'img'   => $item['picture_url'],
                'url'   => $item['url'],
            ];
        }, $products);
    }
}
</code>
<code>class WooCommerceApiAdapter implements FeedAdapterInterface {
    public function __construct(public WooCommerceApi $api) {}

    public function getFeed(): array {
        $products = $this->api->getList();
        return array_map(function ($item) {
            return [
                'title' => $item['name'],
                'date'  => DateTime::createFromFormat('H:i:s Y-m-d', $item['published_date'])->format('Y-m-d H:i:s'),
                'img'   => $item['cover'],
                'url'   => $item['link'],
            ];
        }, $products);
    }
}
</code>

The ProductFeed class aggregates multiple adapters and merges their product arrays:

<code>class ProductFeed implements FeedAdapterInterface {
    public function __construct(private array $adapters) {}

    public function getFeed(): array {
        $adapters = is_array($this->adapters) ? $this->adapters : func_get_args();
        $products = [];
        foreach ($adapters as $adapter) {
            $products = array_merge($products, $adapter->getFeed());
        }
        return $products;
    }
}
</code>

Usage example:

<code>// Create adapters
$shopify = new ShopifyApiAdapter();
$wooCommerce = new WooCommerceApiAdapter();
$bigCommerce = new BigCommerceApiAdapter();

// Create ProductFeed instance
$productFeed = new ProductFeed([
    $shopify,
    $wooCommerce,
    $bigCommerce,
]);

// Retrieve product data
$products = $productFeed->getAllProducts();

// Print product data
foreach ($products as $product) {
    var_dump($product);
}
</code>

Advantages of this approach include separating conversion logic from core business code, improving maintainability and extensibility, decoupling the client from specific adapters, and adhering to SOLID principles such as Single Responsibility, Open/Closed, and Dependency Inversion.

Other typical uses of the Adapter pattern include aggregating data from social media APIs, sending notifications through different channels (SMS, Slack, push), switching cache drivers (Redis, Memcached), abstracting file storage (local, S3, Google Cloud), logging mechanisms, and connecting to various databases (MySQL, PostgreSQL, MongoDB).

design patternsBackend IntegrationPHPAdapter PatternSOLIDE‑Commerce APIs
php中文网 Courses
Written by

php中文网 Courses

php中文网's platform for the latest courses and technical articles, helping PHP learners advance quickly.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.