Installation
composer require woohoolabs/yang
Add to composer.json if using a monorepo or custom package management.
First Request
use Woohoolabs\Yang\Client;
$client = new Client('https://api.example.com');
$response = $client->get('/posts/1');
$data = $response->getData();
Key Files to Review
src/Client.php – Core client logic.src/Response.php – Response handling (data, meta, links).src/Exceptions/ – Custom exceptions for error handling.$client = new Client('https://api.example.com');
$response = $client->get('/posts', [
'include' => 'comments,author',
'filter[published]' => 'true'
]);
// Access data
$posts = $response->getData(); // Array of posts
$meta = $response->getMeta(); // Pagination, etc.
Resource Fetching with Includes
$response = $client->get('/posts/1', [
'include' => 'comments,author',
'fields[posts]' => 'title,body,created_at'
]);
$post = $response->getData();
$comments = $post->getRelationship('comments')->getData();
Pagination Handling
$page = 1;
do {
$response = $client->get('/posts', [
'page[number]' => $page,
'page[size]' => 20
]);
$posts = $response->getData();
// Process posts...
$page++;
} while ($response->getMeta()->get('links')->has('next'));
Sparse Fieldsets
$response = $client->get('/posts', [
'fields[posts]' => 'id,title,slug'
]);
Laravel HTTP Client Wrapper
Extend Laravel’s Http facade for seamless integration:
use Woohoolabs\Yang\Client;
use Illuminate\Support\Facades\Http;
Http::macro('jsonApi', function ($uri, $options = []) {
$client = new Client(config('services.jsonapi.base_uri'));
return $client->request($options['method'] ?? 'get', $uri, $options);
});
Usage:
$response = Http::jsonApi('/posts')->getData();
Caching Responses Cache responses with Laravel’s cache system:
$cacheKey = 'posts:1';
$response = Cache::remember($cacheKey, now()->addHours(1), function () use ($client) {
return $client->get('/posts/1');
});
Error Handling Use custom exceptions for API-specific errors:
try {
$response = $client->get('/posts/999');
} catch (\Woohoolabs\Yang\Exceptions\NotFoundException $e) {
abort(404);
}
Case Sensitivity in Headers
JSON:API headers (e.g., Accept: application/vnd.api+json) must be exact. Use:
$client->withHeaders([
'Accept' => 'application/vnd.api+json',
'Content-Type' => 'application/vnd.api+json'
]);
Relationship Loading Quirks
include is used, relationships are nested under data.attributes.relationships. Access them via:
$author = $post->getRelationship('author')->getData();
include.Pagination Meta Data
The meta field for pagination is nested under links. Access it via:
$links = $response->getMeta()->get('links');
$nextUrl = $links->get('next');
Custom Error Responses
JSON:API errors are in errors array, not meta. Handle them like:
if ($response->hasErrors()) {
$errors = $response->getErrors();
// Log or throw
}
Enable Debug Mode
$client = new Client('https://api.example.com', [
'debug' => true
]);
Logs requests/responses to storage/logs/yang.log.
Inspect Raw Response
$rawResponse = $response->getRawResponse();
// Useful for debugging unexpected JSON:API structures.
Custom Response Transformers Override default response handling:
$client = new Client('https://api.example.com', [
'response_factory' => function ($response) {
return new CustomYangResponse($response);
}
]);
Middleware for Requests Add middleware to modify requests:
$client = new Client('https://api.example.com');
$client->pushMiddleware(function ($request) {
$request->withHeader('X-Custom-Header', 'value');
});
Mocking for Testing
Use Laravel’s Http facade to mock responses:
Http::fake([
'api.example.com/posts/*' => Http::response([
'data' => ['id' => '1', 'type' => 'posts', 'attributes' => [...]]
], 200, ['Content-Type' => 'application/vnd.api+json'])
]);
How can I help you explore Laravel packages today?