Skip to content

pobo-builder/php-sdk

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

18 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Pobo PHP SDK

Tests Latest Stable Version License

Official PHP SDK for Pobo API V2 - product content management and webhooks.

Requirements

  • PHP 8.1+
  • ext-curl
  • ext-json

Installation

composer require pobo-builder/php-sdk

Quick Start

API Client

use Pobo\Sdk\PoboClient;

$client = new PoboClient(
    apiToken: 'your-api-token',
    baseUrl: 'https://api.pobo.space', // optional
    timeout: 30 // optional, in seconds
);

Import

Import Order

1. Parameters (no dependencies)
2. Categories (no dependencies)
3. Products (depends on categories and parameters)
4. Blogs (no dependencies)

Import Parameters

use Pobo\Sdk\DTO\Parameter;
use Pobo\Sdk\DTO\ParameterValue;

$parameters = [
    new Parameter(
        id: 1,
        name: 'Color',
        values: [
            new ParameterValue(id: 1, value: 'Red'),
            new ParameterValue(id: 2, value: 'Blue'),
        ],
    ),
    new Parameter(
        id: 2,
        name: 'Size',
        values: [
            new ParameterValue(id: 3, value: 'S'),
            new ParameterValue(id: 4, value: 'M'),
        ],
    ),
];

$result = $client->importParameters($parameters);
echo sprintf('Imported: %d, Values: %d', $result->imported, $result->valuesImported);

Import Categories

use Pobo\Sdk\DTO\Category;
use Pobo\Sdk\DTO\LocalizedString;
use Pobo\Sdk\Enum\Language;

$categories = [
    new Category(
        id: 'CAT-001',
        isVisible: true,
        name: LocalizedString::create('Electronics')
            ->withTranslation(Language::CS, 'Elektronika')
            ->withTranslation(Language::SK, 'Elektronika'),
        url: LocalizedString::create('https://example.com/electronics')
            ->withTranslation(Language::CS, 'https://example.com/cs/elektronika')
            ->withTranslation(Language::SK, 'https://example.com/sk/elektronika'),
        description: LocalizedString::create('<p>All electronics</p>')
            ->withTranslation(Language::CS, '<p>Veškerá elektronika</p>')
            ->withTranslation(Language::SK, '<p>Všetka elektronika</p>'),
        images: ['https://example.com/images/electronics.jpg'],
    ),
    new Category(
        id: 'CAT-002',
        isVisible: true,
        name: LocalizedString::create('Phones')
            ->withTranslation(Language::CS, 'Telefony')
            ->withTranslation(Language::SK, 'Telefóny'),
        url: LocalizedString::create('https://example.com/phones')
            ->withTranslation(Language::CS, 'https://example.com/cs/telefony')
            ->withTranslation(Language::SK, 'https://example.com/sk/telefony'),
    ),
];

$result = $client->importCategories($categories);
echo sprintf('Imported: %d, Updated: %d', $result->imported, $result->updated);

Import Products

use Pobo\Sdk\DTO\Product;
use Pobo\Sdk\DTO\LocalizedString;
use Pobo\Sdk\Enum\Language;

$products = [
    new Product(
        id: 'PROD-001',
        isVisible: true,
        name: LocalizedString::create('iPhone 15')
            ->withTranslation(Language::CS, 'iPhone 15')
            ->withTranslation(Language::SK, 'iPhone 15'),
        url: LocalizedString::create('https://example.com/iphone-15')
            ->withTranslation(Language::CS, 'https://example.com/cs/iphone-15')
            ->withTranslation(Language::SK, 'https://example.com/sk/iphone-15'),
        shortDescription: LocalizedString::create('Latest iPhone model')
            ->withTranslation(Language::CS, 'Nejnovější model iPhone')
            ->withTranslation(Language::SK, 'Najnovší model iPhone'),
        description: LocalizedString::create('<p>The best iPhone ever.</p>')
            ->withTranslation(Language::CS, '<p>Nejlepší iPhone vůbec.</p>')
            ->withTranslation(Language::SK, '<p>Najlepší iPhone vôbec.</p>'),
        images: ['https://example.com/images/iphone-1.jpg'],
        categoriesIds: ['CAT-001', 'CAT-002'],
        parametersIds: [1, 2],
    ),
    new Product(
        id: 'PROD-002',
        isVisible: true,
        name: LocalizedString::create('Samsung Galaxy S24')
            ->withTranslation(Language::CS, 'Samsung Galaxy S24')
            ->withTranslation(Language::SK, 'Samsung Galaxy S24'),
        url: LocalizedString::create('https://example.com/samsung-s24')
            ->withTranslation(Language::CS, 'https://example.com/cs/samsung-s24')
            ->withTranslation(Language::SK, 'https://example.com/sk/samsung-s24'),
        categoriesIds: ['CAT-001'],
        parametersIds: [1, 3],
    ),
];

$result = $client->importProducts($products);

if ($result->hasErrors() === true) {
    foreach ($result->errors as $error) {
        echo sprintf('Error: %s', implode(', ', $error['errors']));
    }
}

Import Blogs

use Pobo\Sdk\DTO\Blog;
use Pobo\Sdk\DTO\LocalizedString;
use Pobo\Sdk\Enum\Language;

$blogs = [
    new Blog(
        id: 'BLOG-001',
        isVisible: true,
        name: LocalizedString::create('New Product Launch')
            ->withTranslation(Language::CS, 'Uvedení nového produktu')
            ->withTranslation(Language::SK, 'Uvedenie nového produktu'),
        url: LocalizedString::create('https://example.com/blog/new-product')
            ->withTranslation(Language::CS, 'https://example.com/cs/blog/novy-produkt')
            ->withTranslation(Language::SK, 'https://example.com/sk/blog/novy-produkt'),
        category: 'news',
        description: LocalizedString::create('<p>We are excited to announce...</p>')
            ->withTranslation(Language::CS, '<p>S radostí oznamujeme...</p>')
            ->withTranslation(Language::SK, '<p>S radosťou oznamujeme...</p>'),
        images: ['https://example.com/images/blog-1.jpg'],
    ),
    new Blog(
        id: 'BLOG-002',
        isVisible: true,
        name: LocalizedString::create('How to Choose')
            ->withTranslation(Language::CS, 'Jak vybrat')
            ->withTranslation(Language::SK, 'Ako vybrať'),
        url: LocalizedString::create('https://example.com/blog/how-to-choose')
            ->withTranslation(Language::CS, 'https://example.com/cs/blog/jak-vybrat')
            ->withTranslation(Language::SK, 'https://example.com/sk/blog/ako-vybrat'),
        category: 'tips',
    ),
];

$result = $client->importBlogs($blogs);
echo sprintf('Imported: %d, Updated: %d', $result->imported, $result->updated);

Delete

Delete Products

$result = $client->deleteProducts(['PROD-001', 'PROD-002', 'PROD-003']);

echo sprintf('Deleted: %d, Skipped: %d', $result->deleted, $result->skipped);

if ($result->hasErrors() === true) {
    foreach ($result->errors as $error) {
        echo sprintf('ID %s: %s', $error['id'], implode(', ', $error['errors']));
    }
}

Delete Categories

$result = $client->deleteCategories(['CAT-001', 'CAT-002']);
echo sprintf('Deleted: %d', $result->deleted);

Delete Blogs

$result = $client->deleteBlogs(['BLOG-001', 'BLOG-002']);
echo sprintf('Deleted: %d', $result->deleted);

Note: Delete performs a soft-delete.

Export

Export Products

$response = $client->getProducts(page: 1, perPage: 50);

foreach ($response->data as $product) {
    echo sprintf("%s: %s\n", $product->id, $product->name->getDefault());
}

echo sprintf('Page %d of %d', $response->currentPage, $response->getTotalPages());

// Iterate through all products (handles pagination automatically)
foreach ($client->iterateProducts() as $product) {
    echo sprintf("%s: %s\n", $product->id, $product->name->getDefault());
}

// Filter by last update time
$since = new DateTime('2024-01-01 00:00:00');
$response = $client->getProducts(lastUpdateFrom: $since);

// Filter only edited products
$response = $client->getProducts(isEdited: true);

Export Categories

$response = $client->getCategories();

foreach ($response->data as $category) {
    echo sprintf("%s: %s\n", $category->id, $category->name->getDefault());
}

// Iterate through all categories
foreach ($client->iterateCategories() as $category) {
    processCategory($category);
}

Export Blogs

$response = $client->getBlogs();

foreach ($response->data as $blog) {
    echo sprintf("%s: %s\n", $blog->id, $blog->name->getDefault());
}

// Iterate through all blogs
foreach ($client->iterateBlogs() as $blog) {
    processBlog($blog);
}

Content (HTML/Marketplace)

Products, categories, and blogs include a content field with generated HTML content for web and marketplace:

use Pobo\Sdk\Enum\Language;

foreach ($client->iterateProducts() as $product) {
    if ($product->content !== null) {
        // Get HTML content for web
        $htmlCs = $product->content->getHtml(Language::CS);
        $htmlSk = $product->content->getHtml(Language::SK);
        $htmlEn = $product->content->getHtml(Language::EN);

        // Get content for marketplace
        $marketplaceCs = $product->content->getMarketplace(Language::CS);
        $marketplaceSk = $product->content->getMarketplace(Language::SK);

        // Get default content
        $htmlDefault = $product->content->getHtmlDefault();
        $marketplaceDefault = $product->content->getMarketplaceDefault();
    }
}

// Same for categories
foreach ($client->iterateCategories() as $category) {
    if ($category->content !== null) {
        echo $category->content->getHtml(Language::CS);
    }
}

// Same for blogs
foreach ($client->iterateBlogs() as $blog) {
    if ($blog->content !== null) {
        echo $blog->content->getHtml(Language::CS);
    }
}

Webhook Handler

Basic Usage

use Pobo\Sdk\WebhookHandler;
use Pobo\Sdk\Enum\WebhookEvent;
use Pobo\Sdk\Exception\WebhookException;

$handler = new WebhookHandler(webhookSecret: 'your-webhook-secret');

try {
    $payload = $handler->handleFromGlobals();

    match ($payload->event) {
        WebhookEvent::PRODUCTS_UPDATE => syncProducts($client),
        WebhookEvent::CATEGORIES_UPDATE => syncCategories($client),
        WebhookEvent::BLOGS_UPDATE => syncBlogs($client),
    };

    http_response_code(200);
    echo json_encode(['status' => 'ok']);

} catch (WebhookException $e) {
    http_response_code(401);
    echo json_encode(['error' => $e->getMessage()]);
}

Manual Handling

$payload = $handler->handle(
    payload: file_get_contents('php://input'),
    signature: $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? ''
);

Webhook Payload

$payload->event;     // WebhookEvent enum
$payload->timestamp; // DateTimeInterface
$payload->eshopId;   // int

Error Handling

use Pobo\Sdk\Exception\ApiException;
use Pobo\Sdk\Exception\ValidationException;
use Pobo\Sdk\Exception\WebhookException;

try {
    $result = $client->importProducts($products);
} catch (ValidationException $e) {
    echo sprintf('Validation error: %s', $e->getMessage());
    print_r($e->errors);
} catch (ApiException $e) {
    echo sprintf('API error (%d): %s', $e->httpCode, $e->getMessage());
    print_r($e->responseBody);
}

Localized Strings

use Pobo\Sdk\DTO\LocalizedString;
use Pobo\Sdk\Enum\Language;

// Create with default value
$name = LocalizedString::create('Default Name');

// Add translations using fluent interface
$name = $name
    ->withTranslation(Language::CS, 'Czech Name')
    ->withTranslation(Language::SK, 'Slovak Name')
    ->withTranslation(Language::EN, 'English Name');

// Get values
$name->getDefault();         // 'Default Name'
$name->get(Language::CS);    // 'Czech Name'
$name->toArray();            // ['default' => '...', 'cs' => '...', ...]

Supported Languages

Code Language
default Default (required)
cs Czech
sk Slovak
en English
de German
pl Polish
hu Hungarian

API Methods

Method Description
importProducts(array $products) Bulk import products (max 100)
importCategories(array $categories) Bulk import categories (max 100)
importParameters(array $parameters) Bulk import parameters (max 100)
importBlogs(array $blogs) Bulk import blogs (max 100)
deleteProducts(array $ids) Bulk delete products (max 100)
deleteCategories(array $ids) Bulk delete categories (max 100)
deleteBlogs(array $ids) Bulk delete blogs (max 100)
getProducts(?int $page, ?int $perPage, ?DateTime $lastUpdateFrom, ?bool $isEdited) Get products page
getCategories(?int $page, ?int $perPage, ?DateTime $lastUpdateFrom, ?bool $isEdited) Get categories page
getBlogs(?int $page, ?int $perPage, ?DateTime $lastUpdateFrom, ?bool $isEdited) Get blogs page
iterateProducts(?DateTime $lastUpdateFrom, ?bool $isEdited) Iterate all products
iterateCategories(?DateTime $lastUpdateFrom, ?bool $isEdited) Iterate all categories
iterateBlogs(?DateTime $lastUpdateFrom, ?bool $isEdited) Iterate all blogs

Limits

Limit Value
Max items per import request 100
Max items per delete request 100
Max items per export page 100
Product/Category ID length 255 chars
Name length 250 chars
URL length 255 chars
Image URL length 650 chars
Description length 65,000 chars
SEO description length 500 chars

License

MIT License