bytes-commerce / zabbix-api
A PHP library for interacting with the Zabbix API using JSON-RPC 2.0
Package info
github.com/bytes-commerce/zabbix-api
Type:symfony-bundle
pkg:composer/bytes-commerce/zabbix-api
Requires
- php: >=8.3
- psr/log: >=3
- symfony/cache: ^7|^8
- symfony/config: ^7|^8
- symfony/dependency-injection: ^7|^8
- symfony/http-client: ^7|^8
- symfony/http-kernel: ^7|^8
- webmozart/assert: >=1.11
Requires (Dev)
- doctrine/doctrine-bundle: ^2.18
- doctrine/orm: ^3.6
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^9.6.22
- rector/rector: ^2.0
- symfony/messenger: ^7.4
- symfony/security-bundle: ^7.4
- symfony/string: ^7.4
- symfony/uid: ^7.4
- symfony/yaml: ^7|^8
This package is auto-updated.
Last update: 2026-03-28 02:10:22 UTC
README
Modern Symfony bundle for Zabbix API integration with persistent authentication, type-safe actions, and history data retrieval.
Features
✨ Persistent Session Management - Automatic token caching with retry-on-failure 🏭 Factory Pattern - Type-safe action instantiation 📊 History Data Retrieval - Query monitoring data with type-specific methods 🔒 Self-Contained Actions - No globals, clean architecture 🎯 PHP 8.3+ Ready - Full strict typing, readonly properties, enums ⚡ Zero Configuration - Works out of the box with environment variables 📦 Complete API Coverage - Host, HostGroup, Item, History, Graph, Trigger, and more 🚀 Asynchronous Monitoring - Push metrics and events via Symfony Messenger 🛠️ Automatic Setup - Auto-provisioning of hosts, items, and dashboards
composer require bytes-commerce/zabbix-api
Bundle auto-registers via Symfony Flex.
Quick Start
1. Configure
Create .env.local:
ZABBIX_API_BASE_URI=https://zabbix.example.com/api_jsonrpc.php ZABBIX_USERNAME=monitoring_user ZABBIX_PASSWORD=secure_password ZABBIX_AUTH_TTL=3600 # Optional: cache TTL in seconds APP_NAME=MyApplication # Used for host identification
2. Use Actions (Recommended)
use BytesCommerce\ZabbixApi\ZabbixServiceInterface; use BytesCommerce\ZabbixApi\Actions\History; use BytesCommerce\ZabbixApi\Actions\HostGroup; use BytesCommerce\ZabbixApi\Actions\Dto\GetHostGroupDto; use BytesCommerce\ZabbixApi\Enums\HistoryTypeEnum; class MonitoringController { public function __construct( private readonly ZabbixServiceInterface $zabbix ) {} public function cpuMetrics(): array { // Factory pattern - type-safe instantiation $history = $this->zabbix->action(History::class); // Get last 24 hours of CPU data (float values) return $history->getLast24Hours( itemIds: ['12345'], historyType: HistoryTypeEnum::NUMERIC_FLOAT, limit: 100 ); } public function getHostGroups(): array { // Get all host groups $hostGroup = $this->zabbix->action(HostGroup::class); $dto = new GetHostGroupDto( groupids: null, hostids: null, filter: null, output: 'extend', selectHosts: true, selectTemplates: null, sortfield: null, sortorder: null, limit: null, preservekeys: null, ); return $hostGroup->get($dto)->hostGroups; } }
Core Concepts
Actions (Self-Contained API Modules)
Each action represents a Zabbix API namespace:
| Action Class | API Prefix | Methods Example |
|---|---|---|
History |
history |
get(), getLast24Hours(), getLatest() |
Host |
host |
get(), create(), update(), delete() |
HostGroup |
hostgroup |
get(), create(), update(), delete(), exists(), getObjects(), isReadable(), isWritable(), massAdd(), massRemove(), massUpdate() |
Dashboard |
dashboard |
get(), create(), update(), delete() |
Item |
item |
get(), create(), update(), delete() |
User |
user |
login() |
Factory Pattern
// Instantiate actions via factory $hostAction = $zabbix->action(Host::class); $hosts = $hostAction->get(['output' => 'extend']); // Type-safe - IDE autocomplete works $history = $zabbix->action(History::class); $data = $history->getLast24Hours(['itemId']);
Persistent Authentication
Authentication is automatic - no manual login needed:
- First request checks cache (
zabbix_bearer_token) - If missing: auto-login via
user.login, store token with TTL - If expired during request: invalidate → re-login → retry once
- Token sent as
Authorization: Bearer <token>header
// No manual auth - handled transparently $history = $zabbix->action(History::class); $data = $history->getLatest(['12345']); // Auto-authenticates if needed
Usage Examples
History Data Retrieval
use BytesCommerce\ZabbixApi\Actions\History; use BytesCommerce\ZabbixApi\Enums\HistoryTypeEnum; $history = $zabbix->action(History::class); // Latest values (default: last 10) $latest = $history->getLatest( itemIds: ['10084', '10085'], historyType: HistoryTypeEnum::NUMERIC_FLOAT ); // Custom time range $data = $history->get( itemIds: ['10084'], historyType: HistoryTypeEnum::NUMERIC_UNSIGNED, timeFrom: strtotime('-7 days'), timeTill: time(), limit: 500 ); // Last 24 hours (convenience method) $recent = $history->getLast24Hours( itemIds: ['10084'], historyType: HistoryTypeEnum::LOG );
History Data Types
| Enum | Value | Use Case |
|---|---|---|
NUMERIC_FLOAT |
0 | CPU load, temperature, percentages |
CHARACTER |
1 | Short strings |
LOG |
2 | Log file entries |
NUMERIC_UNSIGNED |
3 | Disk space, counts (default) |
TEXT |
4 | Long text values |
BINARY |
5 | Base64-encoded binary (Zabbix 6.0+) |
Host Management
use BytesCommerce\ZabbixApi\Actions\Host; $host = $zabbix->action(Host::class); // Get hosts with filters $hosts = $host->get([ 'output' => ['hostid', 'name', 'status'], 'filter' => ['status' => 0], // Active hosts only 'limit' => 50 ]); // Create host $result = $host->create([[ 'host' => 'New Server', 'groups' => [['groupid' => '2']], 'interfaces' => [[ 'type' => 1, 'main' => 1, 'useip' => 1, 'ip' => '192.168.1.100', 'dns' => '', 'port' => '10050' ]] ]]); // Update host $host->update([[ 'hostid' => '10084', 'status' => 0 ]]); // Delete hosts $host->delete(['10084', '10085']);
HostGroup Management
use BytesCommerce\ZabbixApi\Actions\HostGroup; use BytesCommerce\ZabbixApi\Actions\Dto\GetHostGroupDto; $hostGroup = $zabbix->action(HostGroup::class); // Get host groups with DTO $dto = new GetHostGroupDto( groupids: ['15'], hostids: null, filter: null, output: 'extend', selectHosts: true, selectTemplates: null, sortfield: null, sortorder: null, limit: null, preservekeys: null, ); $groups = $hostGroup->get($dto)->hostGroups; // Create host group $createDto = new CreateHostGroupDto([ ['name' => 'Linux Servers'], ['name' => 'Windows Servers'], ]); $result = $hostGroup->create($createDto); echo "Created group IDs: " . implode(', ', $result->groupids); // Update host group $updateDto = new UpdateHostGroupDto([ [ 'groupid' => '15', 'name' => 'Linux Production Servers', ], ]); $result = $hostGroup->update($updateDto); // Delete host groups $deleteDto = new DeleteHostGroupDto(['15', '16']); $hostGroup->delete($deleteDto); // Check if host group exists $existsDto = new ExistsHostGroupDto( groupids: ['15'], hostids: null, filter: null, name: null, ); $exists = $hostGroup->exists($existsDto)->exists; // Get host groups by filters $getObjectsDto = new GetObjectsHostGroupDto( groupids: null, hostids: null, filter: ['name' => 'Linux'], name: null, ); $groups = $hostGroup->getObjects($getObjectsDto)->hostGroups; // Check if host groups are readable $isReadableDto = new IsReadableHostGroupDto( groupids: ['15'], hostids: null, ); $isReadable = $hostGroup->isReadable($isReadableDto)->isReadable; // Check if host groups are writable $isWritableDto = new IsWritableHostGroupDto( groupids: ['15'], hostids: null, ); $isWritable = $hostGroup->isWritable($isWritableDto)->isWritable; // Mass add hosts to host groups $massAddDto = new MassAddHostGroupDto( groups: ['15'], hosts: ['10084', '10085'], templates: null, ); $result = $hostGroup->massAdd($massAddDto); // Mass remove hosts from host groups $massRemoveDto = new MassRemoveHostGroupDto( groupids: ['15'], hostids: ['10084'], templateids: null, ); $result = $hostGroup->massRemove($massRemoveDto); // Mass update host groups $massUpdateDto = new MassUpdateHostGroupDto( groups: ['15'], hosts: ['10084', '10085'], templates: null, ); $result = $hostGroup->massUpdate($massUpdateDto);
Dashboard Management
use BytesCommerce\ZabbixApi\Actions\Dashboard; use BytesCommerce\ZabbixApi\Actions\Dto\GetDashboardDto; $dashboard = $zabbix->action(Dashboard::class); // Get dashboards with DTO $dto = new GetDashboardDto( dashboardids: ['15'], filter: null, output: 'extend', selectPages: true, selectUsers: true, selectUserGroups: null, sortfield: null, sortorder: null, limit: null, preservekeys: null, ); $dashboards = $dashboard->get($dto)->dashboards; // Create dashboard $createDto = new CreateDashboardDto([ [ 'name' => 'Production Dashboard', 'pages' => [ [ 'name' => 'Overview', 'widgets' => [], ], ], ], ]); $result = $dashboard->create($createDto); echo "Created dashboard IDs: " . implode(', ', $result->dashboardids); // Update dashboard $updateDto = new UpdateDashboardDto([ [ 'dashboardid' => '15', 'name' => 'Updated Dashboard', ], ]); $result = $dashboard->update($updateDto); // Delete dashboards $deleteDto = new DeleteDashboardDto(['15', '16']); $dashboard->delete($deleteDto);
Item Operations
use BytesCommerce\ZabbixApi\Actions\Item; use BytesCommerce\ZabbixApi\Actions\Dto\GetItemDto; $item = $zabbix->action(Item::class); // Get items with DTO $dto = new GetItemDto(); $dto->hostids = ['10084']; $dto->output = 'extend'; $items = $item->get($dto)->items; // Create item $createDto = new CreateItemDto(); $createDto->items = [ new CreateSingleItemDto( name: 'CPU Load', key_: 'system.cpu.load', hostid: '10084', type: ItemTypeEnum::ZABBIX_AGENT, value_type: ValueTypeEnum::NUMERIC_FLOAT, delay: '60s' ) ]; $item->create($createDto);
Manual AuthenticationUser Action
While automatic, you can manually trigger login if needed:
use BytesCommerce\ZabbixApi\Actions\User; $user = $zabbix->action(User::class); $token = $user->login('username', 'password'); // Token is now cached automatically
Asynchronous Operations (Messenger)
The bundle integrates with Symfony Messenger to push metrics and events without blocking the main request.
1. Push Metrics
Send numeric values to Zabbix items:
use BytesCommerce\ZabbixApi\Message\PushMetricMessage; use Symfony\Component\Messenger\MessageBusInterface; public function trackLogin(MessageBusInterface $bus): void { $bus->dispatch(new PushMetricMessage( key: 'app.user.login', value: 1, tags: ['env' => 'prod'] )); }
2. Push Events
Send complex event data:
use BytesCommerce\ZabbixApi\Message\PushEventMessage; use Symfony\Component\Messenger\MessageBusInterface; public function trackError(MessageBusInterface $bus, \Exception $e): void { $bus->dispatch(new PushEventMessage( key: 'app.error', payload: [ 'message' => $e->getMessage(), 'file' => $e->getFile(), 'line' => $e->getLine() ] )); }
3. Transport Configuration
By default, messages are routed to the async transport. You can change this in your configuration:
zabbix_api: messenger_transport: async # Use 'sync' for immediate execution or 'false' to disable auto-routing
Automatic Setup
The bundle can automatically ensure that the necessary Zabbix infrastructure (Hosts, Items, Dashboards) exists.
Configuration
zabbix_api: setup_enabled: true app_name: 'My Application' host_group: 'Application Servers' dashboard_config_path: '%kernel.project_dir%/config/zabbix/dashboards'
Usage
When setup_enabled is true, the bundle will automatically dispatch an EnsureZabbixSetupMessage to verify and create the required resources in Zabbix.
Advanced Usage
ActionService (Backward Compatible)
For dynamic method calls:
use BytesCommerce\ZabbixApi\ActionServiceInterface; use BytesCommerce\ZabbixApi\Actions\History; public function __construct( private readonly ActionServiceInterface $actionService ) {} public function dynamicCall(): mixed { return $this->actionService->call(History::class, [ 'method' => 'get', 'params' => [ 'itemids' => ['10084'], 'history' => 3, 'limit' => 100 ] ]); }
Direct Low-Level Client
For raw API calls:
use BytesCommerce\ZabbixApi\ZabbixClientInterface; use BytesCommerce\ZabbixApi\Enums\ZabbixAction; public function __construct( private readonly ZabbixClientInterface $client ) {} public function rawCall(): mixed { return $this->client->call( ZabbixAction::HISTORY_GET, ['itemids' => ['10084'], 'history' => 0, 'limit' => 10] ); }
Error Handling
All errors throw ZabbixApiException with context:
use BytesCommerce\ZabbixApi\ZabbixApiException; try { $result = $history->get(['10084']); } catch (ZabbixApiException $e) { echo "Error: {$e->getMessage()}\n"; echo "Code: {$e->getErrorCode()}\n"; if ($data = $e->getErrorData()) { echo "Data: {$data}\n"; } }
Auto-Retry on Auth Failure
Authentication errors (-32602, "Session terminated") trigger automatic recovery:
- Cache invalidated
- Fresh login performed
- Original request retried once
- If still fails: exception thrown
Configuration Reference
YAML (Optional)
config/packages/zabbix_api.yaml:
zabbix_api: # API Connection base_uri: '%env(ZABBIX_API_BASE_URI)%' api_token: '%env(ZABBIX_API_TOKEN)%' # Alternative to username/password username: '%env(ZABBIX_USERNAME)%' password: '%env(ZABBIX_PASSWORD)%' auth_ttl: 3600 # seconds, default: 3600 # Monitoring Configuration app_name: '%env(APP_NAME)%' # Application name for monitoring host_group: 'Application Servers' # Default Zabbix host group # Messenger Integration messenger_transport: async # Messenger transport for Zabbix messages (e.g. async, sync, or false to disable auto-routing) # Automatic Setup setup_enabled: false # Enable Zabbix setup commands dashboard_config_path: '%kernel.project_dir%/config/zabbix/dashboards' # Path to dashboard configuration files
Environment Variables
# Required (either API Token or Username/Password) ZABBIX_API_BASE_URI=https://zabbix.example.com/api_jsonrpc.php ZABBIX_API_TOKEN=your_api_token # OR ZABBIX_USERNAME=monitoring_user ZABBIX_PASSWORD=secure_password # Optional ZABBIX_AUTH_TTL=3600 # Token cache TTL in seconds APP_NAME=MyApplication # Used for host identification
Creating Custom Actions
Extend AbstractAction and implement getActionPrefix():
namespace App\Zabbix\Actions; use BytesCommerce\ZabbixApi\Actions\AbstractAction; use BytesCommerce\ZabbixApi\Enums\ZabbixAction; final class CustomAction extends AbstractAction { public static function getActionPrefix(): string { return 'custom'; // API prefix: custom.method } public function myMethod(array $params): array { $result = $this->client->call( ZabbixAction::from('custom.myMethod'), $params ); return is_array($result) ? $result : []; } } // Usage $custom = $zabbix->action(CustomAction::class); $result = $custom->myMethod(['param' => 'value']);
Testing
# Run tests inside Docker docker compose exec php bash -c "vendor/bin/phpunit" # With coverage docker compose exec php bash -c "XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-text" # Static analysis docker compose exec php bash -c "vendor/bin/phpstan analyse --level=max src"
Architecture
- ZabbixService: Factory for action instantiation
- ZabbixClient: Low-level HTTP client with auth management
- Actions: Self-contained API modules (Host, HostGroup, Dashboard, Item, History, Graph, Trigger, etc.)
- Enums: Type-safe constants (HistoryTypeEnum, ZabbixAction, etc.)
- DTOs: Structured request/response objects
Requirements
- PHP 8.3+
- Symfony 7.4+
- Zabbix API 7+ (tested with 8.0)
License
MIT
Support
For issues and feature requests, please use the GitHub issue tracker.