darsyn/ip
Laravel package for working with IP addresses: parse and validate IPv4/IPv6, compare and normalize formats, check ranges and subnet/CIDR matches, and convert between representations. Useful for request filtering, geo/security rules, and logging.
Installation
composer require darsyn/ip
For Laravel, no additional setup is required—just autoloading.
First Use Case: Parsing an IP
use Darsyn\Ip\Ip;
$ip = Ip::fromString('192.168.1.1'); // IPv4
$ip6 = Ip::fromString('2001:0db8:85a3::8a2e:0370:7334'); // IPv6
Ip::fromString() validates and normalizes input.Ip::tryFromString() to avoid exceptions for invalid IPs.Where to Look First
Darsyn\Ip\Ip (base value object), Darsyn\Ip\Ipv4, Darsyn\Ip\Ipv6.Darsyn\Ip\Cidr for range checks (e.g., Cidr::fromString('192.168.1.0/24')).Darsyn\Ip\Laravel\IpServiceProvider (auto-registered) and ip() helper (if published).Workflow: Extract and validate client IPs from Laravel requests.
use Darsyn\Ip\Ip;
$ip = Ip::fromString(request()->ip());
// Normalize to canonical form (e.g., "192.168.1.1" → "192.168.1.1")
$normalized = $ip->toString();
// Check if IP is in a trusted range (e.g., office subnet)
$officeRange = Cidr::fromString('10.0.0.0/8');
if ($officeRange->contains($ip)) {
// Grant access or log as internal
}
Pattern: Store IPs as normalized strings or objects in logs/databases.
// Store in database (use ->toString() for consistency)
$user->last_ip = $ip->toString();
$user->save();
// Log with structured data
\Log::info('User accessed from', [
'ip' => $ip->toString(),
'is_private' => $ip->isPrivate(),
'is_loopback' => $ip->isLoopback(),
]);
Use Case: Block/allow traffic by subnet.
$blockedRanges = [
Cidr::fromString('1.2.3.0/24'),
Cidr::fromString('2001:db8::/32'),
];
$clientIp = Ip::fromString(request()->ip());
$isBlocked = collect($blockedRanges)->contains(fn ($range) => $range->contains($clientIp));
if ($isBlocked) {
abort(403, 'Access denied');
}
Pattern: Write IPv6-agnostic code by leveraging the base Ip class.
function logIpVisit(Ip $ip) {
\Log::info('Visit from ' . $ip->toString());
// Works for both IPv4 and IPv6
}
Pattern: Use factory methods to create test IPs.
$ip = Ip::fromString('192.168.1.1');
$this->assertTrue($ip->isPrivate());
$this->assertFalse(Ip::fromString('8.8.8.8')->isPrivate());
Invalid Input Handling
Ip::fromString() throws \InvalidArgumentException for malformed IPs.Ip::tryFromString() or wrap in a try-catch:
$ip = Ip::tryFromString($userInput) ?? Ip::fromString('0.0.0.0'); // Fallback
CIDR Parsing Quirks
Cidr::fromString() rejects invalid CIDR notations (e.g., 192.168.1.1/33).try {
$range = Cidr::fromString($input);
} catch (\InvalidArgumentException $e) {
// Handle invalid CIDR
}
IPv6 Normalization
2001:0db8::1).$ip1 = Ip::fromString('2001:0DB8::1'); // Normalized to lowercase
$ip2 = Ip::fromString('2001:0db8::1');
$ip1->equals($ip2); // true (uses normalized form)
Laravel Helper Conflicts
ip() helper (if published) may conflict with global functions.use function Darsyn\Ip\Laravel\Facades\Ip as IpHelper;
$ip = IpHelper::fromString(request()->ip());
Inspect IP Properties
$ip = Ip::fromString('192.168.1.1');
dump([
'string' => $ip->toString(),
'is_v4' => $ip->isIpv4(),
'is_private' => $ip->isPrivate(),
'binary' => $ip->toBinary(), // Raw binary representation
]);
CIDR Debugging
$range = Cidr::fromString('192.168.1.0/24');
dump([
'network' => $range->networkAddress()->toString(),
'broadcast' => $range->broadcastAddress()->toString(),
'contains' => $range->contains(Ip::fromString('192.168.1.100')),
]);
Custom IP Logic
Extend the Ip class for domain-specific rules:
class CustomIp extends Ip {
public function isInDmz(): bool {
return $this->equals(Ip::fromString('172.16.0.1'));
}
}
Laravel Service Provider
Bind custom implementations in AppServiceProvider:
$this->app->bind(Ip::class, function () {
return new CustomIp(Ip::fromString(request()->ip()));
});
Database Storage
Use toString() for storage and Ip::fromString() on retrieval to ensure consistency:
// Store
$user->ip = $ip->toString();
// Retrieve
$ip = Ip::fromString($user->ip); // Re-parses for validation
Ip::fromString() is lightweight but avoid parsing the same IP repeatedly (cache results if needed).$range->contains($ip)) are optimized but test performance in bulk operations (e.g., blocking lists).
How can I help you explore Laravel packages today?