laravel-webling maintained by sarfrazrizwan
Laravel Webling Wrapper Package
Laravel wrapper for the Webling REST API (usystems/webling-api-php). It features a three-layer architecture (raw pass-through, ergonomic resource models, and read-only singletons), credentials validation, automated caching, and robust API key security redacting.
Installation
You can install the package via composer:
composer require sarfrazrizwan/laravel-webling
You can publish the configuration file using:
php artisan vendor:publish --tag="webling-config"
Configuration
Set the environment variables in your .env file:
WEBLING_DOMAIN=https://your-domain.webling.ch
WEBLING_API_KEY=your-32-character-api-key
# Optional Timeouts
WEBLING_CONNECT_TIMEOUT=5
WEBLING_TIMEOUT=10
WEBLING_USER_AGENT=laravel-webling
# Optional Caching
WEBLING_CACHE_ENABLED=true
WEBLING_CACHE_DIR=/path/to/cache/directory
Usage
You can access the package using dependency injection or through the Webling facade:
use RizwanSarfraz\Webling\Facades\Webling;
// Or via container resolution:
// $webling = app(RizwanSarfraz\Webling\Webling::class);
Layer 1: Raw HTTP Pass-through (Escape Hatch)
Thin methods returning decoded arrays and throwing WeblingApiException on HTTP status codes >= 400. Useful for endpoints not modeled by the resource layer.
// Perform raw HTTP requests
$members = Webling::get('member');
$response = Webling::post('member', ['FirstName' => 'Jane']);
$response = Webling::put('member/123', ['LastName' => 'Doe']);
$response = Webling::delete('member/123');
// Access the underlying Webling\API\Client directly
$rawClient = Webling::raw();
Layer 2: Ergonomic Resource Groups
Named accessors mapping to Webling object types. Resource instances are cached in memory for the duration of the request.
// List all objects (accepts filter, order, format, page/per_page)
$objects = Webling::member()->list([
'filter' => '`Vorname` = "Hans"',
'format' => 'full'
]);
// Get a single resource
$member = Webling::member()->get(123);
// Multiget (fetches several IDs in one request comma-joined)
$multipleMembers = Webling::member()->get([536, 525, 506]);
// Create a new resource (returns new object ID)
$newId = Webling::member()->create([
'FirstName' => 'Hans',
'LastName' => 'Müller'
]);
// Update a resource
Webling::member()->update(123, ['FirstName' => 'Hansi']);
// Delete a single resource or multiple resources
Webling::member()->delete(123);
Webling::member()->delete([536, 525]);
Specialized Subclass Endpoints
member: Adds binary downloads$imageBytes = Webling::member()->image($id, 'photo.jpg', 'mini'); // size: mini|thumb|medium $fileBytes = Webling::member()->file($id, 'contract.pdf');article: Adds image download$imageBytes = Webling::article()->image($id, 'image.png', 'thumb');document: Adds document content and head checks$fileBytes = Webling::document()->content($id, 'invoice', 'pdf'); $metadata = Webling::document()->head($id);documentgroup: Adds archive ZIP download$zipBytes = Webling::documentgroup()->archive($id);apikey: Fetch last used details$lastUsed = Webling::apikey()->lastUsed($id);user: Trigger onboardingWebling::user()->sendOnboarding($id);
Note: All binary sub-resources return raw bytes (strings) rather than JSON arrays.
Layer 3: Singletons and Read-Only Direct Methods
Direct methods for singleton routes:
$config = Webling::config();
$currentUser = Webling::currentUser();
$definitions = Webling::definitions('simple'); // accepts format: simple|full|zapier
$quota = Webling::quota();
$settings = Webling::settings();
// Update settings
Webling::updateSettings(['theme' => 'dark']);
// Incremental synchronization / change tracking
$changes = Webling::changes(1719710000); // timestamp
$replication = Webling::replicate(123); // revision ID
Caching Integration
If WEBLING_CACHE_ENABLED is true, you can retrieve the cache instance wrapper:
$cache = Webling::cached(); // returns Webling\Cache\Cache
// Update the local cache state
$cache->updateCache();
// Fetch a cached object directly
$member = $cache->getObject('member', 123);
Error Handling
All failed HTTP requests (status >= 400) throw a WeblingApiException which carries detailed request metadata. For security, the API key is automatically redacted from any exception messages and printed stack traces.
use RizwanSarfraz\Webling\Exceptions\WeblingApiException;
use RizwanSarfraz\Webling\Exceptions\WeblingReadonlyException;
use RizwanSarfraz\Webling\Exceptions\WeblingConfigurationException;
try {
Webling::member()->get(999);
} catch (WeblingApiException $e) {
echo $e->getStatusCode(); // e.g. 404
echo $e->getPath(); // e.g. member/999
echo $e->getMethod(); // e.g. GET
echo $e->getResponseBody();
} catch (WeblingReadonlyException $e) {
// Thrown if write is attempted on read-only resources (e.g. letters)
} catch (WeblingConfigurationException $e) {
// Thrown if domain or API key is missing
}
Testing
Mocking requests is simple by swapping the bound Client singleton instance:
use Webling\API\Client;
use Webling\API\Response;
$mockClient = Mockery::mock(Client::class);
$mockClient->shouldReceive('get')->with('member/123')->andReturn(new Response(200, '{"id":123}'));
$this->app->instance(Client::class, $mockClient);
Run test suite:
composer test
References
License
The MIT License (MIT). Please see License File for more information.