dbp/campusonline-api
PHP client for CAMPUSonline web services. Supports legacy REST endpoints, generic exports API, and legacy XML web services. Configure base URL and credentials/token, then access resources like UCard, exports, and organization units.
## Getting Started
### Minimal Setup
1. **Installation**:
```bash
composer require dbp/campusonline-api
Ensure your Laravel project meets the package's PHP version requirements (8.2+).
First API Call:
use Dbp\CampusonlineApi\Rest\Api;
$api = new Api(
env('CAMPUSONLINE_BASE_URL', 'https://qline.example.at/online/'),
env('CAMPUSONLINE_CLIENT_ID'),
env('CAMPUSONLINE_CLIENT_SECRET')
);
Store credentials in .env:
CAMPUSONLINE_BASE_URL=https://your-instance.at/online/
CAMPUSONLINE_CLIENT_ID=your_client_id
CAMPUSONLINE_CLIENT_SECRET=your_client_secret
First Use Case: Fetch a student's UCard data (e.g., for authentication):
$ucard = $api->UCard();
$cardData = $ucard->getCardsForIdentIdObfuscated('1234567890');
Authentication Flow:
Api constructor with OAuth2 credentials.api_token instead of client credentials.Resource Fetching:
$users = $api->User()->getUsers(['filter' => ['status' => 'active']]);
$export = $api->GenericApi('loc_apiMyExport');
$data = $export->getResource('ID', '42', ['language' => 'en']);
$org = $api->OrganizationUnit();
$unit = $org->getOrganizationUnitById('1234');
Pagination:
offset/limit for REST APIs:
$users = $api->User()->getUsers(['offset' => 0, 'limit' => 100]);
$courses = $api->Course()->getCourses(['cursor' => 'initial']);
do {
$courses = $api->Course()->getCourses(['cursor' => $courses->getNextCursor()]);
} while ($courses->hasNext());
Filtering:
FilterBuilder for complex queries:
use Dbp\CampusonlineApi\FilterBuilder;
$filter = (new FilterBuilder())
->equals('status', 'active')
->contains('name', 'Smith');
$users = $api->User()->getUsers(['filter' => $filter->build()]);
$validSubstrings = FilterBuilder::extractValidFilterSubstrings(
$userInput,
['name', 'email']
);
Caching:
$api = new Api(
$baseUrl,
$clientId,
$clientSecret,
[
'cache' => [
'enabled' => true,
'middleware' => new \kevinrob\GuzzleCacheMiddleware\CacheMiddleware(
new \kevinrob\GuzzleCacheMiddleware\Storage\Psr6CacheStorage(
new \Symfony\Component\Cache\Adapter\FilesystemAdapter()
)
),
],
]
);
$data = $api->User()->getUsers(['force_cache_miss' => true]);
Error Handling:
try {
$data = $api->User()->getUserByPersonUid('12345');
} catch (\Dbp\CampusonlineApi\ApiException $e) {
Log::error('Campusonline API error: ' . $e->getMessage());
return response()->json(['error' => 'Service unavailable'], 503);
}
Laravel Service Providers: Bind the API client to the container for dependency injection:
// app/Providers/AppServiceProvider.php
public function register()
{
$this->app->singleton(Api::class, function ($app) {
return new Api(
config('campusonline.base_url'),
config('campusonline.client_id'),
config('campusonline.client_secret')
);
});
}
Configure in config/campusonline.php:
return [
'base_url' => env('CAMPUSONLINE_BASE_URL'),
'client_id' => env('CAMPUSONLINE_CLIENT_ID'),
'client_secret' => env('CAMPUSONLINE_CLIENT_SECRET'),
'cache' => [
'enabled' => env('CAMPUSONLINE_CACHE_ENABLED', false),
],
];
Queued Jobs: Offload heavy API calls to queues (e.g., fetching large datasets):
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
class SyncCampusonlineData implements ShouldQueue
{
use Queueable;
public function handle(Api $api)
{
$data = $api->GenericApi('loc_apiLargeExport')->getResource('ID', '123');
// Process data...
}
}
API Rate Limiting: Implement middleware to throttle requests:
// app/Http/Middleware/ThrottleCampusonline.php
public function handle($request, Closure $next)
{
return $next($request)->throttle([
'campusonline' => ['max' => 60, 'perMinute'],
]);
}
Authentication Issues:
401 Unauthorized or invalid_grant.client_id/client_secret are correct (check .env).checkConnection() to validate the API instance:
if (!$api->User()->checkConnection()) {
throw new \RuntimeException('Campusonline API unavailable');
}
$api->PublicRest()->refreshToken();
Pagination Edge Cases:
hasNext() check or malformed cursors.if (!$courses->hasNext()) break;
Filtering Quirks:
500 Internal Server Error with complex filters.FilterBuilder for safe construction.equals).Legacy XML APIs:
libxml_use_internal_errors(true) if needed.getOrganizationUnitsById() for batch fetching (more efficient than looping).Caching Gotchas:
force_cache_miss for critical updates.$cacheMiddleware->setCacheTTL(300); // 5 minutes
POST vs. GET:
$data = $api->GenericApi('loc_apiLargeExport')->getResource(
'ID', '123',
['method' => 'POST']
);
Enable Guzzle Debugging: Add a debug handler to Guzzle for verbose logging:
$api = new Api($baseUrl, $clientId, $clientSecret, [
'handler' => \GuzzleHttp\HandlerStack::create(new \GuzzleHttp\Handler\CurlHandler()),
'debug' => true,
]);
Inspect Raw Responses:
Use getLastResponse() to debug API calls:
try {
$data = $api->
How can I help you explore Laravel packages today?