diff --git a/README.md b/README.md
index adb9564..e1a5c69 100644
--- a/README.md
+++ b/README.md
@@ -100,6 +100,50 @@ try {
}
```
+## Usage with Laravel
+
+The SDK includes a Laravel service provider for easy integration.
+
+### Configuration
+
+Add the following to your `config/services.php`:
+
+```php
+'wati' => [
+ 'endpoint' => env('WATI_ENDPOINT'),
+ 'token' => env('WATI_TOKEN'),
+],
+```
+
+Add to your `.env` file:
+
+```env
+WATI_ENDPOINT=https://your-instance.wati.io/123456
+WATI_TOKEN=your-bearer-token
+```
+
+### Usage
+
+The service provider is auto-discovered. Simply inject or resolve `WatiClient`:
+
+```php
+use Wati\Http\WatiClient;
+use Wati\Api\GetContacts;
+
+class ContactController
+{
+ public function __construct(
+ private readonly WatiClient $wati
+ ) {}
+
+ public function index()
+ {
+ $response = $this->wati->send(new GetContacts());
+ return json_decode($response->getBody()->getContents(), true);
+ }
+}
+```
+
## API Reference
For full API documentation, visit [Wati API Docs](https://docs.wati.io/reference/introduction).
diff --git a/changelog.md b/changelog.md
index 12bbb27..39cffa2 100644
--- a/changelog.md
+++ b/changelog.md
@@ -8,3 +8,4 @@ All notable changes to `phpjuice/wati-sdk` will be documented in this file.
- Pre-built API classes for Wati API:
- `Wati\Api\GetContacts` - Get paginated list of contacts
- PHP 8.3+ support
+- Add Laravel service provider
diff --git a/composer.json b/composer.json
index 5afe3a9..cd45a80 100644
--- a/composer.json
+++ b/composer.json
@@ -23,7 +23,8 @@
"require": {
"php": "^8.3 || ^8.4",
"ext-json": "*",
- "phpjuice/wati-http-client": "^1.0"
+ "phpjuice/wati-http-client": "^1.0",
+ "illuminate/support": "^10.0|^11.0|^12.0"
},
"require-dev": {
"laravel/pint": "^1.27",
@@ -74,5 +75,12 @@
"allow-plugins": {
"pestphp/pest-plugin": true
}
+ },
+ "extra": {
+ "laravel": {
+ "providers": [
+ "Wati\\Laravel\\WatiServiceProvider"
+ ]
+ }
}
}
diff --git a/phpstan.neon b/phpstan.neon
index 12fd0aa..96296b7 100644
--- a/phpstan.neon
+++ b/phpstan.neon
@@ -5,3 +5,4 @@ parameters:
- tests
excludePaths:
- tests/*/data/*
+ - src/Laravel
diff --git a/phpunit.xml b/phpunit.xml
index 1ec04a3..6dd4f98 100644
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -14,5 +14,8 @@
src
+
+ src/Laravel
+
diff --git a/src/Api/Dto/Contact.php b/src/Api/Dto/Contact.php
index 204920f..d8130d2 100644
--- a/src/Api/Dto/Contact.php
+++ b/src/Api/Dto/Contact.php
@@ -24,15 +24,15 @@ public function __construct(
public static function fromArray(array $data): self
{
return new self(
- id: data_get($data, 'id', ''),
- phone: data_get($data, 'phone', ''),
- fullName: data_get($data, 'fullName', ''),
- wAid: is_string($v = data_get($data, 'wAid')) ? $v : null,
- firstName: is_string($v = data_get($data, 'firstName')) ? $v : null,
- email: is_string($v = data_get($data, 'email')) ? $v : null,
- contactStatus: is_string($v = data_get($data, 'contactStatus')) ? $v : null,
- created: is_string($v = data_get($data, 'created')) ? $v : null,
- lastUpdated: is_string($v = data_get($data, 'lastUpdated')) ? $v : null,
+ id: data_get_str($data, 'id', ''),
+ phone: data_get_str($data, 'phone', ''),
+ fullName: data_get_str($data, 'fullName', ''),
+ wAid: is_string($v = data_get_str($data, 'wAid')) ? $v : null,
+ firstName: is_string($v = data_get_str($data, 'firstName')) ? $v : null,
+ email: is_string($v = data_get_str($data, 'email')) ? $v : null,
+ contactStatus: is_string($v = data_get_str($data, 'contactStatus')) ? $v : null,
+ created: is_string($v = data_get_str($data, 'created')) ? $v : null,
+ lastUpdated: is_string($v = data_get_str($data, 'lastUpdated')) ? $v : null,
);
}
}
diff --git a/src/Laravel/WatiServiceProvider.php b/src/Laravel/WatiServiceProvider.php
new file mode 100644
index 0000000..7285219
--- /dev/null
+++ b/src/Laravel/WatiServiceProvider.php
@@ -0,0 +1,24 @@
+app->singleton(WatiClient::class, fn (): WatiClient => new WatiClient(
+ new WatiEnvironment(
+ endpoint: config('services.wati.endpoint'),
+ bearerToken: config('services.wati.token'),
+ )
+ ));
+ }
+}
diff --git a/src/helpers.php b/src/helpers.php
index 985fef4..2fa18ec 100644
--- a/src/helpers.php
+++ b/src/helpers.php
@@ -9,7 +9,7 @@
* @param TDefault $default
* @return string|TDefault
*/
-function data_get(array $data, string $key, mixed $default = null): mixed
+function data_get_str(array $data, string $key, mixed $default = null): mixed
{
if (! array_key_exists($key, $data)) {
return $default;
diff --git a/tests/helpersTest.php b/tests/helpersTest.php
index b03a4ca..4ee96c6 100644
--- a/tests/helpersTest.php
+++ b/tests/helpersTest.php
@@ -5,42 +5,42 @@
it('returns value when key exists', function (): void {
$data = ['name' => 'John', 'email' => 'john@example.com'];
- expect(data_get($data, 'name'))->toBe('John')
- ->and(data_get($data, 'email'))->toBe('john@example.com');
+ expect(data_get_str($data, 'name'))->toBe('John')
+ ->and(data_get_str($data, 'email'))->toBe('john@example.com');
});
it('returns default when key does not exist', function (): void {
$data = ['name' => 'John'];
- expect(data_get($data, 'email'))->toBeNull()
- ->and(data_get($data, 'email', 'default'))->toBe('default');
+ expect(data_get_str($data, 'email'))->toBeNull()
+ ->and(data_get_str($data, 'email', 'default'))->toBe('default');
});
it('returns default when value is null', function (): void {
$data = ['name' => null];
- expect(data_get($data, 'name'))->toBeNull()
- ->and(data_get($data, 'name', 'default'))->toBe('default');
+ expect(data_get_str($data, 'name'))->toBeNull()
+ ->and(data_get_str($data, 'name', 'default'))->toBe('default');
});
it('returns default when value is empty string', function (): void {
$data = ['name' => ''];
- expect(data_get($data, 'name'))->toBeNull()
- ->and(data_get($data, 'name', 'default'))->toBe('default');
+ expect(data_get_str($data, 'name'))->toBeNull()
+ ->and(data_get_str($data, 'name', 'default'))->toBe('default');
});
it('trims string values', function (): void {
$data = ['name' => ' John '];
- expect(data_get($data, 'name'))->toBe('John');
+ expect(data_get_str($data, 'name'))->toBe('John');
});
it('returns default when trimmed value is empty', function (): void {
$data = ['name' => ' '];
- expect(data_get($data, 'name'))->toBeNull()
- ->and(data_get($data, 'name', 'default'))->toBe('default');
+ expect(data_get_str($data, 'name'))->toBeNull()
+ ->and(data_get_str($data, 'name', 'default'))->toBe('default');
});
it('returns non-string values as-is', function (): void {
@@ -51,14 +51,14 @@
'price' => 19.99,
];
- expect(data_get($data, 'count'))->toBe(42)
- ->and(data_get($data, 'active'))->toBeTrue()
- ->and(data_get($data, 'items'))->toBe(['a', 'b'])
- ->and(data_get($data, 'price'))->toBe(19.99);
+ expect(data_get_str($data, 'count'))->toBe(42)
+ ->and(data_get_str($data, 'active'))->toBeTrue()
+ ->and(data_get_str($data, 'items'))->toBe(['a', 'b'])
+ ->and(data_get_str($data, 'price'))->toBe(19.99);
});
it('returns default for missing nested keys', function (): void {
$data = ['user' => ['name' => 'John']];
- expect(data_get($data, 'email', 'missing'))->toBe('missing');
+ expect(data_get_str($data, 'email', 'missing'))->toBe('missing');
});