get($key); if ($value !== null && $value !== '') { $ip = trim(explode(',', $value)[0]); if (self::isValid($ip)) { return new self($ip); } } } return null; } public static function localhost(): self { return new self('127.0.0.1'); } // Validation public static function isValid(string $ip): bool { return filter_var($ip, FILTER_VALIDATE_IP) !== false; } // Basic checks public function isPrivate(): bool { return ! filter_var($this->value, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE); } public function isPublic(): bool { return ! $this->isPrivate() && ! $this->isReserved(); } public function isReserved(): bool { return filter_var($this->value, FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE) === false; } public function isLoopback(): bool { if ($this->isV4()) { return str_starts_with($this->value, '127.'); } return $this->value === '::1'; } /** * Check if IP is considered local (private or loopback) */ public function isLocal(): bool { return $this->isPrivate() || $this->isLoopback(); } public function isV4(): bool { return filter_var($this->value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== false; } public function isV6(): bool { return filter_var($this->value, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false; } // Comparison public function equals(IpAddress $other): bool { return $this->value === $other->value; } public function __toString(): string { return $this->value; } }