Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 130 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@
<h1>Openapi® client for PHP</h1>
<h4>The perfect starting point to integrate <a href="https://openapi.com/">Openapi®</a> within your PHP project</h4>

[![Build Status](https://github.com/openapi/openapi-php-sdk/actions/workflows/php.yml/badge.svg)](https://github.com/openapi/openapi-php-sdk/actions/workflows/php.yml)
[![Packagist Version](https://img.shields.io/packagist/v/openapi/openapi-sdk)](https://packagist.org/packages/openapi/openapi-sdk)
[![PHP Version](https://img.shields.io/packagist/php-v/openapi/openapi-sdk)](https://packagist.org/packages/openapi/openapi-sdk)
[![License](https://img.shields.io/github/license/openapi/openapi-php-sdk?v=2)](LICENSE)
[![Downloads](https://img.shields.io/packagist/dt/openapi/openapi-sdk)](https://packagist.org/packages/openapi/openapi-sdk)
<br>
[![Build Status](https://github.com/openapi/openapi-php-sdk/actions/workflows/php.yml/badge.svg)](https://github.com/openapi/openapi-php-sdk/actions/workflows/php.yml)
[![Packagist Version](https://img.shields.io/packagist/v/openapi/openapi-sdk)](https://packagist.org/packages/openapi/openapi-sdk)
[![PHP Version](https://img.shields.io/packagist/php-v/openapi/openapi-sdk)](https://packagist.org/packages/openapi/openapi-sdk)
[![License](https://img.shields.io/github/license/openapi/openapi-php-sdk?v=2)](LICENSE)
[![Downloads](https://img.shields.io/packagist/dt/openapi/openapi-sdk)](https://packagist.org/packages/openapi/openapi-sdk)
<br>
[![Linux Foundation Member](https://img.shields.io/badge/Linux%20Foundation-Silver%20Member-003778?logo=linux-foundation&logoColor=white)](https://www.linuxfoundation.org/about/members)

</div>

## Overview
Expand All @@ -27,9 +28,10 @@ Before using the Openapi PHP Client, you will need an account at [Openapi](https

- **Agnostic Design**: No API-specific classes, works with any OpenAPI service
- **Minimal Dependencies**: Only requires PHP 8.0+ and cURL
- **OAuth Support**: Built-in OAuth client for token management
- **OAuth Support**: Built-in OAuth client for token management
- **HTTP Primitives**: GET, POST, PUT, DELETE, PATCH methods
- **Clean Interface**: Similar to the Rust SDK design
- **Built-in DotEnv Support**: Lightweight environment loader with safe fallback behavior

## What you can do

Expand Down Expand Up @@ -81,7 +83,7 @@ $client = new Client($token);
$params = ['denominazione' => 'Stellantis', 'provincia' => 'TO'];
$response = $client->get('https://test.company.openapi.com/IT-advanced', $params);

// POST request
// POST request
$payload = ['limit' => 10, 'query' => ['country_code' => 'IT']];
$response = $client->post('https://test.postontarget.com/fields/country', $payload);

Expand All @@ -91,6 +93,70 @@ $response = $client->delete($url);
$response = $client->patch($url, $payload);
```

## Custom HTTP Clients (Guzzle, Laravel, etc.)

By default, the SDK uses an internal cURL-based transport.
However, you can now inject your own HTTP client, allowing full control over the request pipeline.

This is especially useful in frameworks like Laravel, where you may want to reuse an existing HTTP client with middleware such as retry, caching, logging, or tracing.

Using a custom HTTP client (e.g. Guzzle)

You can pass any PSR-18 compatible client (such as Guzzle) directly to the SDK:

```php
use OpenApi\Client;
use GuzzleHttp\Client as GuzzleClient;

$guzzle = new GuzzleClient([
'timeout' => 10,
// You can configure middleware, retry logic, caching, etc. here
]);

$client = new Client($token, $guzzle);

$response = $client->get('https://test.company.openapi.com/IT-advanced', [
'denominazione' => 'Stellantis',
]);
```

### Why this matters

When using the default transport, requests are executed via cURL and bypass any framework-level HTTP configuration.

By injecting your own client, you can:

- ✅ Reuse your existing HTTP middleware stack (e.g. Laravel retry/cache)
- ✅ Centralize logging, tracing, and observability
- ✅ Apply custom headers, timeouts, or authentication strategies
- ✅ Maintain consistency with your application's HTTP layer

### Custom Transport Interface

If needed, you can also implement your own transport by using the provided interface:

```php
use OpenApi\Interfaces\HttpTransportInterface;

class MyTransport implements HttpTransportInterface
{
public function request(
string $method,
string $url,
mixed $payload = null,
?array $params = null
): string {
// Your custom implementation
}
}
```

And inject it:

```php
$client = new Client($token, new MyTransport());
```

## Architecture

This SDK follows a minimal approach with only essential components:
Expand All @@ -100,6 +166,59 @@ This SDK follows a minimal approach with only essential components:
- `Exception`: Error handling
- `Cache\CacheInterface`: Optional caching interface

## Environment Configuration (.env support)

This SDK includes a lightweight and framework-agnostic .env loader to simplify configuration in non-framework environments.

### Automatic loading

When installed via Composer, the SDK will automatically attempt to load a .env file from the project root.

This happens only when no existing environment configuration is detected (e.g. Laravel, Symfony, CI environments).

- ✅ Does not override existing environment variables
- ✅ Works out of the box in plain PHP projects
- ✅ Compatible with Laravel, Symfony, and other frameworks
- ✅ Safe fallback mechanism

### Supported variables

The following environment variables are commonly used:

```env
OPENAPI_BASE_URL=https://example.com
OPENAPI_OAUTH_USERNAME=your_username
OPENAPI_OAUTH_APIKEY=your_api_key
OPENAPI_OAUTH_URL=https://api.com
OPENAPI_OAUTH_TEST_URL=https://api.com
```

### Framework compatibility

If you are using a framework like Laravel or Symfony:

- The SDK will not override your existing environment
- Your framework's configuration system remains the source of truth
- The internal loader acts only as a fallback

### Manual usage

If you prefer full control, you can use the DotEnv loader manually:

```php
use OpenApi\Environment\DotEnv\DotEnv;

$dotenv = new DotEnv(__DIR__ . '/.env');
$dotenv->load();

```

### Notes

- The loader is intentionally minimal and does not aim to fully replace libraries like vlucas/phpdotenv
- Designed for performance, predictability, and zero external dependencies
- Suitable for CLI tools, microservices, and lightweight integrations

## Requirements

- PHP 8.0 or higher
Expand Down Expand Up @@ -134,7 +253,6 @@ composer run test
composer run test:unit
```


## Contributing

Contributions are always welcome! Whether you want to report bugs, suggest new features, improve documentation, or contribute code, your help is appreciated.
Expand Down Expand Up @@ -165,9 +283,9 @@ Meet our partners using Openapi or contributing to this SDK:

## Our Commitments

We believe in open source and we act on that belief. We became Silver Members
of the Linux Foundation because we wanted to formally support the ecosystem
we build on every day. Open standards, open collaboration, and open governance
We believe in open source and we act on that belief. We became Silver Members
of the Linux Foundation because we wanted to formally support the ecosystem
we build on every day. Open standards, open collaboration, and open governance
are part of how we work and how we think about software.

## License
Expand All @@ -179,4 +297,3 @@ The MIT License is a permissive open-source license that allows you to freely us
In short, you are free to use this SDK in your personal, academic, or commercial projects, with minimal restrictions. The project is provided "as-is", without any warranty of any kind, either expressed or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose, and non-infringement.

For more details, see the full license text at the [MIT License page](https://choosealicense.com/licenses/mit/).

20 changes: 17 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "openapi/openapi-sdk",
"name": "seraphim/openapi-sdk",
"description": "Minimal and agnostic PHP SDK for Openapi® (https://openapi.com)",
"license": "MIT",
"authors": [
Expand All @@ -12,15 +12,29 @@
"require": {
"php": ">=8.0.0",
"ext-curl": "*",
"ext-json": "*"
"ext-json": "*",
"psr/http-client": "^1.0"
},
"require-dev": {
"symfony/dotenv": "^5.3",
"phpunit/phpunit": "^9.5"
},
"autoload": {
"psr-4": {
"OpenApi\\": "src"
"Openapi\\": "src"
},
"files": [
"src/OpenapiBootstrap.php"
]
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests"
}
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests"
Comment thread
Seraphim200001 marked this conversation as resolved.
}
},
"scripts": {
Expand Down
4 changes: 2 additions & 2 deletions examples/api_calls.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

require_once __DIR__ . '/../vendor/autoload.php';

use OpenApi\Client;
use OpenApi\OpenapiClient;

try {
$token = '<your_access_token>';
$client = new Client($token);
$client = new OpenapiClient($token);

// GET request with parameters
$params = [
Expand Down
14 changes: 7 additions & 7 deletions examples/complete_workflow.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@

require_once __DIR__ . '/../vendor/autoload.php';

use OpenApi\OauthClient;
use OpenApi\Client;
use OpenApi\Exception;
use OpenApi\OpenapiOauthClient;
use OpenApi\OpenapiClient;
use OpenApi\OpenapiException;

try {
echo "=== OpenAPI PHP SDK Complete Workflow Example ===" . PHP_EOL . PHP_EOL;

// Step 1: Create OAuth client
echo "Step 1: Creating OAuth client..." . PHP_EOL;
$oauthClient = new OauthClient('<your_username>', '<your_apikey>', true);
$oauthClient = new OpenapiOauthClient('<your_username>', '<your_apikey>', true);
echo "✓ OAuth client created" . PHP_EOL . PHP_EOL;

// Step 2: Generate token
Expand All @@ -25,15 +25,15 @@
$tokenData = json_decode($tokenResult, true);

if (!isset($tokenData['token'])) {
throw new Exception('Failed to generate token: ' . $tokenResult);
throw new OpenapiException('Failed to generate token: ' . $tokenResult);
}

$token = $tokenData['token'];
echo "✓ Token generated: " . substr($token, 0, 20) . "..." . PHP_EOL . PHP_EOL;

// Step 3: Create API client
echo "Step 3: Creating API client..." . PHP_EOL;
$apiClient = new Client($token);
$apiClient = new OpenapiClient($token);
echo "✓ API client created" . PHP_EOL . PHP_EOL;

// Step 4: Make API calls
Expand Down Expand Up @@ -62,7 +62,7 @@

echo "=== Workflow completed successfully! ===" . PHP_EOL;

} catch (Exception $e) {
} catch (OpenapiException $e) {
echo "✗ Error: " . $e->getMessage() . PHP_EOL;

if ($e->getHttpCode()) {
Expand Down
4 changes: 2 additions & 2 deletions examples/token_generation.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

require_once __DIR__ . '/../vendor/autoload.php';

use OpenApi\OauthClient;
use OpenApi\OpenapiOauthClient;

try {
$oauthClient = new OauthClient('<your_username>', '<your_apikey>', true);
$oauthClient = new OpenapiOauthClient('<your_username>', '<your_apikey>', true);

$scopes = [
'GET:test.imprese.openapi.it/advance',
Expand Down
20 changes: 20 additions & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/12.5/phpunit.xsd"
bootstrap="vendor/autoload.php"
colors="true">

<testsuites>
<testsuite name="unit">
<directory>tests</directory>
</testsuite>
</testsuites>

<php>
<env name="OPENAPI_BASE_URL" value="https://example.com"/>
<env name="OPENAPI_USERNAME" value="test_user"/>
<env name="OPENAPI_SANDBOX_KEY" value="test_key"/>
<env name="OPENAPI_OAUTH_SANDBOX_URL" value="https://api.com"/>
<env name="OPENAPI_OAUTH_URL" value="https://api.com"/>
</php>
</phpunit>
4 changes: 2 additions & 2 deletions src/Cache/ArrayCache.php → src/Cache/OpenapiArrayCache.php
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<?php

namespace OpenApi\Cache;
namespace Openapi\Cache;

/**
* In-memory cache implementation
* Data is stored in PHP arrays and cleared at end of script execution
*/
class ArrayCache implements CacheInterface
class OpenapiArrayCache implements OpenapiCacheInterface
{
private array $cache = [];
private array $expiry = [];
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<?php

namespace OpenApi\Cache;
namespace Openapi\Cache;

/**
* Cache interface for SDK implementations
*/
interface CacheInterface
interface OpenapiCacheInterface
{
/**
* Retrieve value from cache
Expand Down
Loading