Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Ip Tools Laravel Package

longman/ip-tools

Longman IP Tools is a PHP/Laravel package for IPv4 and IPv6 address handling. It validates IPs, parses CIDR blocks, checks ranges and subnet membership, and helps build reliable IP-based validation and filtering logic.

View on GitHub
Deep Wiki
Context7

Getting Started

Install via Composer — the package is longman/ip-tools and exposes the IpTools\ namespace:

composer require longman/ip-tools

There are only two classes you need to learn on day one; everything else is a detail:

  • IpTools\IP (with IPv4/IPv6 subclasses) — single address parsing, version detection, numeric conversion, and classification (private/public/reserved).
  • IpTools\Range — CIDR, dash-range, and single-IP containment checks plus iteration.

A good first read is src/IP.php, src/Range.php, then src/IPv4.php / src/IPv6.php to see how big-integer math is handled. Start with the use case that motivates most installs: deciding whether an incoming request IP is inside a known network.

use IpTools\IP;
use IpTools\Range;

$ip = new IP('192.168.1.25');

$ip->getVersion();   // 4
$ip->getLong();      // numeric form, handy for storage/sorting
$ip->isPrivate();    // true

$range = Range::parse('192.168.1.0/24');
$range->contains($ip);          // true
$range->getFirstIP();           // IP object for 192.168.1.0
$range->getLastIP();            // IP object for 192.168.1.255

Range::parse() accepts a CIDR (10.0.0.0/8), a dash range (10.0.0.1-10.0.0.50), or a bare address (10.0.0.1), which makes it a single choke point for any "is this IP in this network" check.

Implementation Patterns

Trusted-proxy / allow-list middleware. The most common day-to-day pattern is a small middleware that rejects or tags requests from IPs outside configured networks:

use IpTools\Range;

public function handle($request, Closure $next)
{
    $trusted = config('services.trusted_ranges', []); // ['10.0.0.0/8', '192.168.0.0/16']
    $client  = $request->ip();

    foreach ($trusted as $cidr) {
        if (Range::parse($cidr)->contains($client)) {
            return $next($request);
        }
    }

    abort(403);
}

Because contains() accepts the raw string, you avoid constructing IP objects on the hot path yourself.

Config-driven network registry. Keep CIDRs in config/*.php rather than hard-coding them. That lets ops change the allow-list without a deploy, and lets you unit-test the same list through Range::parse() in isolation. If you need a reusable service, wrap it — e.g. App\Networks\NetworkRegistry that parses each range once and memoizes the Range objects.

Storing and sorting addresses. Persist the getLong() value (as a string column if you care about IPv6) alongside the textual IP. Numeric form gives you correct sort order and lets you do BETWEEN lookups for "which subnet does this IP fall into" queries without recomputing ranges in PHP. Keep the original string too; you will want it for logs and abuse reports.

Blacklist / per-range iteration. Range is iterable, which is tempting for building scan lists, but treat it as a bounded tool: iterating a /24 (256 addresses) is fine, iterating a /8 (16 million) is not. If you need to walk large space, iterate subnets and process them in chunks rather than expanding to individual IPs.

Classification for logging and abuse handling. isPrivate(), isPublic(), and version checks are cheap and useful in an access-log pipeline — flag loopback/RFC1918 traffic differently from public traffic, and reject version mismatches (an IPv4-only endpoint receiving an IPv6 literal). Combine with filter_var($ip, FILTER_VALIDATE_IP) if you just need boolean validity and don't want to catch constructor exceptions.

Testable integration. Bind a thin adapter around Range in the container and swap it in tests; the underlying classes are static-friendly (Range::parse) and easy to construct with fixed values, so pure unit tests against contains() cover most of the risk.

Gotchas and Tips

  • Age and PHP compatibility. The last release is from 2016. Before adopting, run the suite on your PHP version (8.1+/8.2+) — expect deprecation notices around implicit nullable parameters and dynamic properties in older code, and verify the IPv6 path actually exercises your big-integer extension.
  • IPv6 math needs GMP or BCMath. IPv6 range arithmetic cannot use native int; check that ext-gmp (or whichever backend the package expects) is installed in every environment, including CI and the production image. A missing extension often surfaces as wrong comparisons rather than a clean error.
  • 32-bit overflow on getLong() for IPv4. On 32-bit PHP builds the numeric value can go signed/negative. Prefer 64-bit runtimes, and always cast to string before storing.
  • Invalid input throws. The constructors and Range::parse() raise exceptions (InvalidArgumentException and friends) on malformed input. Validate or try/catch at the boundary — never let a client-supplied X-Forwarded-For reach new IP() unguarded.
  • Host bits and normalization. A range like 192.168.1.5/24 describes a subnet whose first/last addresses are the network/broadcast host values. Confirm the package's normalization behavior before relying on getFirstIP() matching what you stored in config; test the off-by-one at the edges explicitly.
  • No Laravel-native rule / facade. There is no package-provided validation rule or service provider, and the namespace IpTools will not clash with Symfony's IpUtils unless you alias — but you will be writing your own Rule/Rule::in extension or middleware wrapper.
  • contains() is your friend, iteration is not. Re-check large ranges by nesting smaller CIDRs instead of expanding; this keeps memory bounded and makes the code read like the network design.
  • Extension points. Subclass IP/Range only if you need domain-specific behavior (custom __toString, extra classification helpers). For most apps the better seam is a wrapper service around Range::parse() so you can swap the implementation later without touching call sites.
  • Pin the version and audit. With zero dependents and a single maintainer, treat upgrades as manual work: pin in composer.json, keep a thin wrapper around the two public APIs, and add regression tests for the exact CIDRs your app trusts so a future replacement is a one-file change.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib