PHP SDK for Swotto API

2.1.0 2025-07-28 13:24 UTC

This package is auto-updated.

Last update: 2025-07-28 14:40:08 UTC


README

Version PHP License PSR-12 PHPStan Enterprise

Enterprise-ready PHP SDK per l'integrazione con le API SW4. Fornisce un'interfaccia type-safe, smart caching, e parsing automatico delle risposte con 87.5% di riduzione del boilerplate code.

Indice

✨ Novità v2.0.0

🚀 getParsed() Methods - 87.5% Less Boilerplate

// PRIMA v1.x (8 linee di codice ripetitivo)
$response = $client->get('customers', ['query' => $query]);
$parsed = $this->parseDataResponse($response);
$data = [
    'data' => $parsed['data'],
    'paginator' => $parsed['paginator']
];

// ADESSO v2.0 (1 linea - parsing automatico!)
$data = $client->getParsed('customers', ['query' => $query]);
// Returns: ['data' => [...], 'paginator' => [...], 'success' => true]

🎯 Smart Caching Automatico

// Auto-caching per dati statici (countries, currencies, etc.)
$countries = $client->getCountryPop();     // HTTP call + cache (1h)
$countries = $client->getCountryPop();     // Cache hit! No HTTP

// Dati dinamici sempre fresh
$orders = $client->get('orders');          // Always fresh (no cache)

🏗️ Modern PHP 8.1+ Architecture

  • PSR-16 Simple Cache support per Redis, Memcached, Array cache
  • PSR-14 Event Dispatcher per monitoring e telemetry
  • 100% Backward Compatible - zero breaking changes
  • Progressive Enhancement - features solo se abilitate

Quick Start

use Swotto\Client;

// Configurazione minimal (identica a v1.x)
$client = new Client(['url' => 'https://api.swotto.it']);

// NEW v2.0: Parsing automatico delle risposte
$data = $client->getParsed('customers', ['query' => ['active' => true]]);
// Automatic parsing: data + paginator extraction!

// v1.x methods funzionano identicamente
$customers = $client->getCustomerPop();
$result = $client->get('endpoint', ['query' => ['param' => 'value']]);

Quick Start con Smart Caching

// Optional: Abilita smart caching
$cache = new \Symfony\Component\Cache\Adapter\ArrayAdapter();
$client = new Client(['url' => 'https://api.swotto.it'], null, null, $cache);

// Auto-cached per dati statici
$countries = $client->getCountryPop();  // HTTP + cache
$countries = $client->getCountryPop();  // Cache hit!

Installazione

Requisiti

  • PHP 8.1 o superiore
  • Composer
  • ext-json

Installazione via Composer

Il progetto utilizza git tags per il versioning. Installa una versione specifica:

# Versione corrente stabile
composer require agenziasmart/swotto:v2.0.0

# Range di versioni compatibili  
composer require agenziasmart/swotto:^v2.0

Configurazione composer.json

{
    "require": {
        "agenziasmart/swotto": "v2.0.0"
    }
}

Versioning e Release

Il progetto segue Semantic Versioning:

  • v2.0.0: 🚀 Enterprise-ready release con getParsed() methods + smart caching
  • v1.3.0: Test suite completa, PHPStan level 8
  • v1.2.0: Aggiunto supporto metodi HTTP PUT
  • v1.0.x: Versioni legacy

Tags disponibili: git tag --list --sort=-version:refname

🚀 Enhanced Methods - getParsed()

I nuovi metodi *Parsed() eliminano il boilerplate ripetitivo automatizzando il parsing delle risposte SW4:

Metodi Disponibili

// Tutti i metodi HTTP con parsing automatico
$data = $client->getParsed($endpoint, $options);        // GET + parsing
$data = $client->postParsed($endpoint, $options);       // POST + parsing
$data = $client->patchParsed($endpoint, $options);      // PATCH + parsing
$data = $client->putParsed($endpoint, $options);        // PUT + parsing
$data = $client->deleteParsed($endpoint, $options);     // DELETE + parsing

Struttura Response Automatica

// Tutti i metodi *Parsed() restituiscono:
[
    'data' => [...],           // Dati business estratti da response['data']
    'paginator' => [...],      // Paginator costruito da response['meta']['pagination']  
    'success' => true|false    // Flag success da response['success']
]

Esempi Pratici

Prima vs Dopo

// PRIMA v1.x - Boilerplate ripetitivo in ogni handler
$query = array_merge(array_filter($request->getQueryParams()), [
    'count' => 1,
    'include' => 'consent',
]);
$query['orderby'] ??= 'updated_at.desc';
$query['limit'] ??= $request->getAttribute('_pagination');
$response = $this->swotto->get('customers', ['query' => $query]);
$parsed = $this->parseDataResponse($response);
$data = [
    'data' => $parsed['data'],
    'paginator' => $parsed['paginator'],
];

// DOPO v2.0 - Una linea!
$query = $this->buildQuery($request, ['count' => 1, 'include' => 'consent'], 'updated_at.desc');
$data = $this->swotto->getParsed('customers', ['query' => $query]);

CRUD Operations

// CREATE with auto-parsing
$newCustomer = $client->postParsed('customers', [
    'json' => ['name' => 'New Customer', 'email' => 'test@example.com']
]);
echo $newCustomer['data']['id'];  // Auto-extracted customer ID

// READ with auto-parsing + pagination
$customers = $client->getParsed('customers', [
    'query' => ['active' => true, 'limit' => 25]
]);
echo count($customers['data']);                    // Customer data
echo $customers['paginator']['total'];             // Total count
echo $customers['paginator']['current_page'];      // Current page

// UPDATE with auto-parsing  
$updated = $client->patchParsed('customers/123', [
    'json' => ['name' => 'Updated Name']
]);
echo $updated['success'];  // true|false

// DELETE with auto-parsing
$deleted = $client->deleteParsed('customers/123');
echo $deleted['success'];  // Deletion confirmed

🔐 Dynamic Bearer Token Management

La versione 2.0.0 introduce metodi avanzati per la gestione dinamica dei Bearer token, essenziali per applicazioni enterprise che richiedono token refresh automatici e session management robusto:

Metodi di Gestione Token

// Imposta un nuovo Bearer token runtime
$client->setAccessToken('new-bearer-token-here');

// Verifica token corrente
$currentToken = $client->getAccessToken();
echo $currentToken; // "new-bearer-token-here"

// Cancella token (torna all'autenticazione base)
$client->clearAccessToken();

Pattern di Token Refresh Automatico

try {
    $result = $client->getParsed('protected-endpoint');
} catch (\Swotto\Exception\AuthenticationException $e) {
    // Token scaduto - refresh automatico
    $newToken = $this->refreshTokenFromAuthServer();
    $client->setAccessToken($newToken);
    
    // Retry con nuovo token
    $result = $client->getParsed('protected-endpoint');
}

Session Management Avanzato

// Pattern per applicazioni multi-user
class UserSessionManager {
    public function switchUser(string $userId, string $bearerToken): void {
        $this->client->setAccessToken($bearerToken);
        $this->client->setSessionId("session-{$userId}");
        
        // Verifica validità della nuova sessione
        $sessionCheck = $this->client->checkSession();
        if (!$sessionCheck) {
            throw new InvalidSessionException("Token non valido per user {$userId}");
        }
    }
    
    public function logout(): void {
        $this->client->clearAccessToken();
        $this->client->setSessionId(null);
    }
}

Token Validation Pattern

// Verifica proattiva validità token
public function ensureValidToken(): bool {
    try {
        $this->client->checkAuth();
        return true;
    } catch (\Swotto\Exception\AuthenticationException $e) {
        // Token invalido - richiedi refresh
        $this->requestTokenRefresh();
        return false;
    }
}

🎯 Smart Caching

Il smart caching automatico ottimizza le performance memorizzando automaticamente le risposte di endpoint statici:

Configurazione Cache

// Nessuna cache (default - comportamento v1.x)
$client = new Client(['url' => 'https://api.swotto.it']);

// Array cache (in-memory per request)
$cache = new \Symfony\Component\Cache\Adapter\ArrayAdapter();
$client = new Client(['url' => 'https://api.swotto.it'], null, null, $cache);

// Redis cache (persistente tra requests)
$redis = new \Redis();
$redis->connect('127.0.0.1', 6379);
$cache = new \Symfony\Component\Cache\Adapter\RedisAdapter($redis);
$client = new Client(['url' => 'https://api.swotto.it'], null, null, $cache);

// File cache (filesystem)
$cache = new \Symfony\Component\Cache\Adapter\FilesystemAdapter();
$client = new Client(['url' => 'https://api.swotto.it'], null, null, $cache);

Endpoint Auto-Cached

Gli endpoint statici vengono automaticamente memorizzati in cache:

// Questi endpoint sono auto-cached (dati che cambiano raramente)
$countries = $client->getCountryPop();        // ✅ Cached 1h
$currencies = $client->getCurrencyPop();      // ✅ Cached 1h  
$languages = $client->getSysLanguagePop();   // ✅ Cached 1h
$genders = $client->getGenderPop();          // ✅ Cached 1h

// Questi endpoint sono sempre fresh (dati che cambiano spesso)
$customers = $client->getCustomerPop();      // ❌ No cache (dynamic data)
$orders = $client->get('orders');            // ❌ No cache (dynamic data)
$inventory = $client->get('inventory');      // ❌ No cache (dynamic data)

Cache TTL Configurabile

// Default TTL: 1 ora (3600 secondi)
$client = new Client(['url' => 'https://api.swotto.it'], null, null, $cache);

// Custom TTL: 30 minuti
$client = new Client([
    'url' => 'https://api.swotto.it',
    'cache_ttl' => 1800  // 30 minutes
], null, null, $cache);

// Cache disabilitata per endpoint specifici
$countries = $client->fetchPop('open/country', ['cache' => false]);  // Force fresh

Performance Benefits

// First call: HTTP request + cache store
$countries = $client->getCountryPop();  // ~200ms (HTTP call)

// Subsequent calls: cache hit
$countries = $client->getCountryPop();  // ~1ms (cache hit)
$countries = $client->getCountryPop();  // ~1ms (cache hit)

// Automatic cache invalidation after TTL
// After 1 hour: HTTP request + cache refresh
$countries = $client->getCountryPop();  // ~200ms (cache expired, fresh call)

Configurazione Base

La configurazione minima richiede l'URL dell'API Swotto:

$client = new \Swotto\Client([
    'url' => 'https://api.swotto.it'
]);

Configurazione completa

Per un'applicazione in produzione, si consiglia una configurazione più dettagliata:

$client = new \Swotto\Client([
    'url' => 'https://api.swotto.it',  // URL dell'API (obbligatorio)
    'key' => 'YOUR_API_KEY',           // Chiave API per l'applicazione
    'access_token' => 'YOUR_TOKEN',    // Token di accesso
    'session_id' => 'SESSION_ID',      // ID sessione
    'language' => 'it',                // Lingua preferita
    'accept' => 'application/json',    // Header Accept
    'verify_ssl' => true,              // Verifica certificati SSL
]);

Configurazione con logging

Per tracciare le richieste e le risposte, aggiungi un logger compatibile con PSR-3:

// Configura un logger (esempio con Monolog)
$logger = new \Monolog\Logger('swotto');
$logger->pushHandler(new \Monolog\Handler\StreamHandler('logs/swotto.log', \Monolog\Logger::DEBUG));

// Aggiungi il logger al client
$client = new \Swotto\Client([
    'url' => 'https://api.swotto.it',
    'key' => 'YOUR_API_KEY'
], $logger);

Metodi HTTP di base

Il client fornisce metodi semplici per interagire con l'API:

GET

// Richiesta GET semplice
$result = $client->get('endpoint');

// Richiesta GET con parametri di query
$result = $client->get('endpoint', [
    'query' => [
        'param1' => 'value1',
        'param2' => 'value2'
    ]
]);

POST

// Richiesta POST con dati JSON
$result = $client->post('endpoint', [
    'json' => [
        'field1' => 'value1',
        'field2' => 'value2'
    ]
]);

// Richiesta POST con form data
$result = $client->post('endpoint', [
    'form_params' => [
        'field1' => 'value1',
        'field2' => 'value2'
    ]
]);

PUT

// Aggiornamento di una risorsa specifica
$result = $client->put('endpoint/123', [
    'json' => [
        'field1' => 'new_value'
    ]
]);

DELETE

// Eliminazione di una risorsa
$result = $client->delete('endpoint/123');

Gestione degli Errori

Il client lancia eccezioni specifiche per ogni tipo di errore:

try {
    $result = $client->get('endpoint');
} catch (\Swotto\Exception\ValidationException $e) {
    // Errore 400: Bad Request
    $errors = $e->getErrorData();
    echo "Errori di validazione: " . json_encode($errors);
} catch (\Swotto\Exception\AuthenticationException $e) {
    // Errore 401: Unauthorized
    echo "Autenticazione richiesta";
} catch (\Swotto\Exception\ForbiddenException $e) {
    // Errore 403: Forbidden
    echo "Accesso negato";
} catch (\Swotto\Exception\NotFoundException $e) {
    // Errore 404: Not Found
    echo "Risorsa non trovata";
} catch (\Swotto\Exception\RateLimitException $e) {
    // Errore 429: Too Many Requests
    $retryAfter = $e->getRetryAfter();
    echo "Troppe richieste. Riprova tra {$retryAfter} secondi";
} catch (\Swotto\Exception\ConnectionException $e) {
    // Errore di connessione
    echo "Impossibile connettersi a: " . $e->getUrl();
} catch (\Swotto\Exception\NetworkException $e) {
    // Errore di rete
    echo "Errore di rete: " . $e->getMessage();
} catch (\Swotto\Exception\ApiException $e) {
    // Altri errori API
    echo "Errore API: " . $e->getMessage();
    echo "Codice: " . $e->getStatusCode();
    echo "Dati: " . json_encode($e->getErrorData());
} catch (\Exception $e) {
    // Altri errori
    echo "Errore generico: " . $e->getMessage();
}

Utilizzo dei Metodi POP

I metodi POP sono shortcut per recuperare dati comuni:

// Recupera clienti
$customers = $client->getCustomerPop([
    'account' => 'true',
    'orderby' => 'name'
]);

// Recupera paesi
$countries = $client->getCountryPop();

// Recupera valute
$currencies = $client->getCurrencyPop();

// Recupera zone di un magazzino specifico
$warehouseId = 123;
$zones = $client->getWarehouseZonePop($warehouseId);

Test di Connettività

Verifica se il servizio API è raggiungibile:

if ($client->checkConnection()) {
    echo "Connessione all'API funzionante";
} else {
    echo "Impossibile connettersi all'API";
}

Verifica Autenticazione

Verifica se le credenziali sono valide:

try {
    $authStatus = $client->checkAuth();
    echo "Autenticazione valida";
} catch (\Swotto\Exception\AuthenticationException $e) {
    echo "Credenziali non valide";
}

Verifica Sessione

Verifica se la sessione è valida:

try {
    $sessionStatus = $client->checkSession();
    echo "Sessione valida: " . $sessionStatus['session_id'];
} catch (\Swotto\Exception\SwottoException $e) {
    echo "Sessione non valida";
}

Cambio Configurazione Runtime

Puoi modificare alcune impostazioni durante l'esecuzione:

// Cambia ID sessione
$client->setSessionId('nuovo-session-id');

// Cambia lingua
$client->setLanguage('en');

// Cambia header Accept
$client->setAccept('application/xml');

Test e Verifica

Il SDK include metodi per verificare connettività e stato:

Test di Connettività

if ($client->checkConnection()) {
    echo "API raggiungibile";
}

Verifica Autenticazione

try {
    $client->checkAuth();
    echo "Credenziali valide";
} catch (\Swotto\Exception\AuthenticationException $e) {
    echo "Autenticazione fallita";
}

Architettura

PSR Standards Implementati

  • PSR-3: Logging interface per tracciamento richieste/risposte
  • PSR-4: Autoloading standard per namespace Swotto\
  • PSR-12: Code style con PHP CS Fixer per consistenza
  • PSR-18: HTTP Client interface per dependency injection

Dependency Injection

use Swotto\Client;
use Swotto\Http\GuzzleHttpClient;
use Monolog\Logger;

// Custom HTTP client implementation
$httpClient = new GuzzleHttpClient($config, $logger);
$client = new Client($config, $logger, $httpClient);

Pattern Utilizzati

  • Strategy Pattern: HttpClientInterface per swappable HTTP implementations
  • Trait Composition: PopTrait per metodi SW4-specific
  • Factory Method: Configuration validation e object creation

Configurazione Completa

Tutte le opzioni supportate da Configuration.php:

$client = new Client([
    'url' => 'https://api.swotto.it',        // Required: API endpoint
    'key' => 'your-api-key',                 // API authentication key
    'access_token' => 'bearer-token',        // OAuth/Bearer token
    'session_id' => 'session-identifier',   // Session tracking
    'language' => 'it',                      // Response language (it|en)
    'accept' => 'application/json',          // Accept header
    'verify_ssl' => true,                    // SSL certificate verification
    'headers' => [                           // Custom headers
        'X-Custom-Header' => 'value'
    ],
    'client_user_agent' => 'MyApp/1.0',     // Custom User-Agent
    'client_ip' => '192.168.1.1'            // Client IP forwarding
]);

Sviluppo

Qualità del Codice

Il progetto utilizza diversi strumenti per garantire la qualità del codice:

PHP CS Fixer

Formatazione automatica del codice secondo lo standard PSR-12:

# Esegui la formattazione
composer cs-fix

# Controlla la formattazione (dry run)
composer cs-dry

PHPStan

Analisi statica del codice per identificare errori potenziali:

# Esegui l'analisi
composer phpstan

Test Suite

Suite completa con 57 test e 148 asserzioni:

# Esegui tutti i test
composer test

# Test specifici per componente
vendor/bin/phpunit tests/ClientTest.php
vendor/bin/phpunit tests/ConfigurationTest.php
vendor/bin/phpunit tests/PopTraitTest.php
vendor/bin/phpunit tests/GuzzleHttpClientTest.php
vendor/bin/phpunit tests/ExceptionTest.php

# Test con coverage dettagliata
composer test-coverage

Copertura test per modulo:

  • ClientTest: HTTP methods, authentication, configuration
  • ConfigurationTest: Validation, headers, IP/UserAgent detection
  • PopTraitTest: Tutti i metodi POP specifici SW4
  • GuzzleHttpClientTest: HTTP client con scenari completi
  • ExceptionTest: Tutte le classi exception custom

Configurazione VSCode

Per un'esperienza di sviluppo ottimale, il progetto include configurazioni per VSCode:

  • Formattazione automatica al salvataggio
  • Integrazione con PHP CS Fixer
  • Configurazione PHPStan
  • Esclusione di file non necessari

Hooks di Sviluppo

Il progetto è configurato per eseguire automaticamente:

  • Formattazione del codice al salvataggio (VSCode)
  • Analisi statica con PHPStan
  • Test unitari prima del commit (se configurati)

Performance

Ottimizzazioni HTTP Client

// Pool di connessioni per high-throughput
$client = new Client([
    'url' => 'https://api.swotto.it',
    'headers' => [
        'Connection' => 'keep-alive',
        'Keep-Alive' => 'timeout=5, max=1000'
    ]
]);

Rate Limiting Management

try {
    $result = $client->get('endpoint');
} catch (\Swotto\Exception\RateLimitException $e) {
    $retryAfter = $e->getRetryAfter();
    sleep($retryAfter);
    // Retry logic implementation
}

Connection Pooling Best Practices

  • Riutilizza istanze Client per múltiple richieste
  • Configura timeout appropriati per environment di produzione
  • Implementa retry logic exponential backoff per resilienza

Troubleshooting

Debug Logging

use Monolog\Logger;
use Monolog\Handler\StreamHandler;

$logger = new Logger('swotto-debug');
$logger->pushHandler(new StreamHandler('debug.log', Logger::DEBUG));

$client = new Client($config, $logger);

Problemi Comuni

SSL Certificate Verification Error

// Temporary fix per development (NON usare in production)
$client = new Client(['url' => 'https://api.swotto.it', 'verify_ssl' => false]);

Connection Timeout

// Aumenta timeout per API lente
$client = new Client([
    'url' => 'https://api.swotto.it',
    'headers' => ['timeout' => 30]
]);

Memory Issues con Large Datasets

// Usa pagination per dataset grandi
$customers = $client->getCustomerPop([
    'limit' => 100,
    'offset' => 0
]);

Changelog

Vedi CHANGELOG.md per la storia completa delle release.

Migration Guide

Da v1.x a v2.0.0

✅ Zero Breaking Changes: Il codice v1.x funziona identicamente in v2.0.0.

Upgrade Immediate

# Update version in composer.json
composer require agenziasmart/swotto:v2.0.0

Gradual Adoption - Level 1: getParsed() Methods

// Replace manual parsing with getParsed()
// BEFORE
$response = $client->get('customers', ['query' => $query]);
$parsed = $this->parseDataResponse($response);
$data = ['data' => $parsed['data'], 'paginator' => $parsed['paginator']];

// AFTER  
$data = $client->getParsed('customers', ['query' => $query]);

Gradual Adoption - Level 2: Smart Caching

// Add optional caching
$cache = new \Symfony\Component\Cache\Adapter\ArrayAdapter();
$client = new Client(['url' => $url, 'key' => $key], null, null, $cache);

// All POP functions now auto-cached
$countries = $client->getCountryPop();  // HTTP + cache
$countries = $client->getCountryPop();  // Cache hit!

Gradual Adoption - Level 3: Full Enterprise (Future)

// Future v2.1 features (non-breaking additions)
$client = new Client([
    'url' => $url,
    'key' => $key,
    'retry' => ['max_attempts' => 3],        // Smart retry
    'circuit_breaker' => true                // Circuit breaker
], null, null, $cache, $events);

Deprecated Features

Nessuna: v2.0.0 non depreca alcuna feature esistente.

Performance Improvements

  • 87.5% less boilerplate con getParsed() methods
  • Smart caching automatic per dati statici
  • Zero overhead se cache/events non iniettati
  • Same performance per codice v1.x esistente

Changelog

Vedi CHANGELOG.md per la storia completa delle release.

v2.0.0 - 🚀 Enterprise-Ready Release

🚀 New Features

  • getParsed() Methods: Auto-parsing per tutti i metodi HTTP (GET, POST, PATCH, PUT, DELETE)
  • Smart Caching: Auto-caching endpoint statici con PSR-16 compatibility
  • Modern PHP 8.1+: PSR standards + typed properties + progressive enhancement
  • Enterprise Foundation: Architecture ready per Circuit Breaker, Smart Retry, Rate Limiting

Enhancements

  • 87.5% Boilerplate Reduction: Da 8 linee a 1 linea per response parsing
  • Progressive Enhancement: Features enterprise solo se iniettate (null = no overhead)
  • PSR-16 Simple Cache: Support per Redis, Memcached, Array, File cache
  • PSR-14 Event Dispatcher: Foundation per monitoring e telemetry

🛡️ Backward Compatibility

  • 100% Compatible: Zero breaking changes, codice v1.x funziona identicamente
  • Constructor Enhancement: Parametri addizionali optional, signature esistente unchanged
  • Method Preservation: Tutti i metodi esistenti funzionano senza modifiche

📊 Quality Assurance

  • 64 tests, 181 assertions: Full test coverage per nuove features
  • PSR12 Compliance: Code style standards maintained
  • Static Analysis: PHPStan level 8 compatibility
  • Enterprise Architecture: Foundation solida per future features

v1.3.0 - Highlights

  • PHP CS Fixer: Implementato per mantenere uno stile di codice coerente
  • PHPStan: Analisi statica livello 8 per maggiore sicurezza del codice
  • Test Suite: Copertura completa con 57 test e 148 asserzioni
  • Configurazione VSCode: Setup ottimizzato per lo sviluppo
  • Gestione Eccezioni: Migliorata la gestione delle eccezioni con costruttori standardizzati