Skip to content
ZILLEALI edited this page Jun 16, 2026 · 1 revision

v1.5.0 — Input Validation & Silent Failure Fixes

Released: 2026-06-16
Tag: v1.5.0
Install: composer require zilleali/mikrotik-laravel:^1.5.0


Overview

Reliability release — adds input validation across all 18 service managers and eliminates silent failures on write operations. Invalid data is now rejected before touching the router, and missing resources throw typed exceptions instead of returning silently.


What's New

1. Input Validation (HasValidation trait)

All 18 service managers now validate input before sending any command to the router. Passing bad data throws ValidationException immediately — no wasted API round-trips.

Validators available:

Method Validates
validateNotEmpty($value, $field) String is not empty or whitespace
validateIp($ip, $field) Valid IPv4 address
validateCidr($cidr, $field) Valid IPv4/prefix (e.g. 192.168.1.0/24)
validateMac($mac, $field) Valid MAC address (XX:XX:XX:XX:XX:XX)
validatePort($port, $field) Integer between 1 and 65535
validateRequiredKeys($data, $keys, $context) Array contains all required non-empty keys

Example — ValidationException:

use ZillEAli\MikrotikLaravel\Exceptions\ValidationException;

try {
    MikroTik::pppoe()->createSecret(['name' => 'ali']); // missing 'password'
} catch (ValidationException $e) {
    $e->getMessage();
    // "Required field 'password' is missing or empty in pppoe-secret."
}

try {
    MikroTik::arp()->addStaticArp('not-an-ip', 'AA:BB:CC:DD:EE:FF', 'ether1');
} catch (ValidationException $e) {
    $e->getMessage();
    // "Field 'address' must be a valid IPv4 address, got 'not-an-ip'."
}

What is validated per manager:

Manager Validated Fields
PppoeManager name, password on create; name on all write ops
HotspotManager name, password on create; name on all write ops
QueueManager name, target on create; name on write ops
ScriptManager name, source on addScript; name, on-event on addScheduler
ArpManager address (IPv4), mac-address, interface on add; address on remove
DnsManager name, address (IPv4) on addStaticEntry; name on update/remove
IpAddressManager address, interface on add; CIDR format on update/remove/enable/disable
RouteManager CIDR on dst-address; IPv4 on gateway; CIDR on update/remove/enable/disable
FirewallManager list name on addToAddressList/removeFromAddressList
IpPoolManager name, ranges on createPool
DhcpManager MAC format on makeLeaseStatic/deleteLease
InterfaceManager name on enableInterface/disableInterface
WirelessManager MAC format on addToAccessList/removeFromAccessList
VpnManager interface, public-key, allowed-address on addWireGuardPeer
BridgeManager name on addBridge; bridge, interface on addBridgePort; name on remove ops
RouterUserManager name, password, group on addUser; name on all write ops
SyslogManager name, IPv4 remote-ip, port on addRemoteTarget; topics, action on addRule
RadiusManager address, secret on addServer; address on update/remove/enable/disable

2. Silent Failure Fixes (ResourceNotFoundException)

Previously, write operations on non-existent resources (update, delete, enable, disable) would return silently with no error. They now throw ResourceNotFoundException.

use ZillEAli\MikrotikLaravel\Exceptions\ResourceNotFoundException;

try {
    MikroTik::pppoe()->deleteSecret('unknown-user');
} catch (ResourceNotFoundException $e) {
    $e->getMessage();
    // "pppoe-secret 'unknown-user' not found on the router."

    $e->getResourceType(); // 'pppoe-secret'
    $e->getIdentifier();   // 'unknown-user'
}

All 18 managers are covered. The exception is thrown for: update, delete, enable, disable, kick, and any operation that looks up by name/IP/MAC first.


3. InvalidRouterResponseException

RouterOS API responses that are missing the required .id field now throw InvalidRouterResponseException instead of returning null.

use ZillEAli\MikrotikLaravel\Exceptions\InvalidRouterResponseException;

try {
    MikroTik::pppoe()->deleteSecret('ali');
} catch (InvalidRouterResponseException $e) {
    $e->getMessage();
    // "RouterOS returned a 'pppoe-secret' resource without the required
    //  '.id' field. Check that the API user has sufficient read permissions."
}

This typically indicates that the API user account lacks read permissions.


Breaking Changes

ResourceNotFoundException instead of silent return

If your code previously relied on write operations silently doing nothing when a resource was not found, it will now receive an exception.

Before (v1.4.0):

MikroTik::pppoe()->deleteSecret('unknown'); // no error, no effect

After (v1.5.0):

MikroTik::pppoe()->deleteSecret('unknown'); // throws ResourceNotFoundException

Fix: Wrap in a try/catch or check existence first:

// Option A — catch it
try {
    MikroTik::pppoe()->deleteSecret($name);
} catch (ResourceNotFoundException $e) {
    // handle or ignore
}

// Option B — check first
if (MikroTik::pppoe()->getSecret($name)) {
    MikroTik::pppoe()->deleteSecret($name);
}

ValidationException on invalid input

Passing an empty string or invalid format where a valid value was expected now throws ValidationException instead of sending a malformed command to the router.


Exception Hierarchy

\InvalidArgumentException
  └── ValidationException          ← invalid input format

\RuntimeException
  ├── ResourceNotFoundException    ← resource not found on router
  └── InvalidRouterResponseException ← router returned unexpected data

Test Coverage

Suite Tests Assertions
v1.4.0 350 546
v1.5.0 433 631

New test files: HasValidationTest (35 tests), DnsManagerTest (15 tests). Validation tests added to all 18 manager test files.


Upgrade

composer require zilleali/mikrotik-laravel:^1.5.0

No config changes needed.


v1.4.0 | Managers Reference →


📝 Found an error or missing info?
Edit this page or open an issue to suggest improvements.

Clone this wiki locally