PHPackages                             limepie/ip-lib - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. limepie/ip-lib

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

limepie/ip-lib
==============

Handle IPv4, IPv6 addresses and ranges

01PHP

Since May 13Pushed 2y agoCompare

[ Source](https://github.com/yejune/ip-lib)[ Packagist](https://packagist.org/packages/limepie/ip-lib)[ RSS](/packages/limepie-ip-lib/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependenciesVersions (1)Used By (0)

[![Tests](https://github.com/mlocati/ip-lib/actions/workflows/tests.yml/badge.svg)](https://github.com/mlocati/ip-lib/actions?query=workflow%3A%22tests%22)[![Coverage Status](https://camo.githubusercontent.com/1116e44607d403beac1ade9102aff25dd175bab1886bf76c6b4a6199fd1edbba/68747470733a2f2f636f766572616c6c732e696f2f7265706f732f6769746875622f6d6c6f636174692f69702d6c69622f62616467652e7376673f6272616e63683d6d6173746572)](https://coveralls.io/github/mlocati/ip-lib?branch=master)[![Scrutinizer Code Quality](https://camo.githubusercontent.com/52a849b5e8e56ebb7f84010f3e37f3db06c12d752566dca134139e48d7f22c3d/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f6d6c6f636174692f69702d6c69622f6261646765732f7175616c6974792d73636f72652e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/mlocati/ip-lib/?branch=master)[![Packagist Downloads](https://camo.githubusercontent.com/955c593f1ff5643f3f2d75e4c242f6f495cc3ff00dd85ab430e5551b72d20651/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f646d2f6d6c6f636174692f69702d6c6962)](https://camo.githubusercontent.com/955c593f1ff5643f3f2d75e4c242f6f495cc3ff00dd85ab430e5551b72d20651/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f646d2f6d6c6f636174692f69702d6c6962)[![Open in Gitpod](https://camo.githubusercontent.com/fec93bccac506b047a803d0d74b686d922da6209406ca9fac454ace2bd185c8f/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4f70656e253230696e2d476974706f642d2532333263623634633f6c6f676f3d676974706f64)](https://gitpod.io/#https://github.com/mlocati/ip-lib)

IPLib - Handle IPv4, IPv6 and IP ranges
=======================================

[](#iplib---handle-ipv4-ipv6-and-ip-ranges)

Introduction
------------

[](#introduction)

IPLib is a modern, PSR-compliant, test-driven IP addresses and subnets manipulation library. It implements primitives to handle IPv4 and IPv6 addresses, as well as IP ranges (subnets), in CIDR format (like `::1/128` or `127.0.0.1/32`) and in pattern format (like `::*:*` or `127.0.*.*`).

Requirements
------------

[](#requirements)

IPLib has very basic requirements as:

- Works with any PHP version greater than 5.3.3 (PHP **5.3.x**, **5.4.x**, **5.5.x**, **5.6.x**, **7.x**, and **8.x** are fully supported).
- **No external dependencies**
- **No special PHP configuration needed** (yes, it will **always work** even if PHP has not been built with IPv6 support!).

Installation
------------

[](#installation)

### Manual installation

[](#manual-installation)

[Download](https://github.com/mlocati/ip-lib/releases) the latest version, unzip it and add these lines in our PHP files:

```
require_once 'path/to/iplib/ip-lib.php';
```

### Installation with Composer

[](#installation-with-composer)

Simply run

```
composer require mlocati/ip-lib
```

or add these lines to your `composer.json` file:

```
"require": {
    "mlocati/ip-lib": "^1"
}
```

Sample usage
------------

[](#sample-usage)

### Parse an address

[](#parse-an-address)

To parse an IPv4 address:

```
$address = \IPLib\Address\IPv4::parseString('127.0.0.1');
```

To parse an IPv6 address:

```
$address = \IPLib\Address\IPv6::parseString('::1');
```

To parse an address in any format (IPv4 or IPv6):

```
$address = \IPLib\Factory::parseAddressString('::1');
$address = \IPLib\Factory::parseAddressString('127.0.0.1');
```

### Get the next/previous addresses

[](#get-the-nextprevious-addresses)

```
$address = \IPLib\Factory::parseAddressString('::1');

// This will print ::
echo (string) $address->getPreviousAddress();

// This will print ::2
echo (string) $address->getNextAddress();
```

### Get the addresses at a specified offset

[](#get-the-addresses-at-a-specified-offset)

For addresses:

```
$address = \IPLib\Factory::parseAddressString('::1');

// This will print ::1
echo (string) $address->getAddressAtOffset(0);

// This will print ::2
echo (string) $address->getAddressAtOffset(1);

// This will print ::3
echo (string) $address->getAddressAtOffset(2);

// This will print ::3e9
echo (string) $address->getAddressAtOffset(1000);

// This will print ::
echo (string) $address->getAddressAtOffset(-1);

// This will print NULL
echo var_dump($address->getAddressAtOffset(-2));
```

For ranges:

```
$range = \IPLib\Factory::parseRangeString('::ff00/120');

// This will print ::ff00
echo (string) $range->getAddressAtOffset(0);

// This will print ::ff10
echo (string) $range->getAddressAtOffset(16);

// This will print ::ff64
echo (string) $range->getAddressAtOffset(100);

// This will print NULL because the address ::1:0 is out of the range
var_dump($range->getAddressAtOffset(256));

// This will print ::ffff
echo (string) $range->getAddressAtOffset(-1);

// This will print ::fff0
echo (string) $range->getAddressAtOffset(-16);

// This will print ::ff00
echo (string) $range->getAddressAtOffset(-256);

// This will print NULL because the address ::feff is out of the range
var_dump($range->getAddressAtOffset(-257));
```

### Parse an IP address range

[](#parse-an-ip-address-range)

To parse a subnet (CIDR) range:

```
$range = \IPLib\Range\Subnet::parseString('127.0.0.1/24');
$range = \IPLib\Range\Subnet::parseString('::1/128');
```

To parse a pattern (asterisk notation) range:

```
$range = \IPLib\Range\Pattern::parseString('127.0.0.*');
$range = \IPLib\Range\Pattern::parseString('::*');
```

To parse an address as a range:

```
$range = \IPLib\Range\Single::parseString('127.0.0.1');
$range = \IPLib\Range\Single::parseString('::1');
```

To parse a range in any format:

```
$range = \IPLib\Factory::parseRangeString('127.0.0.*');
$range = \IPLib\Factory::parseRangeString('::1/128');
$range = \IPLib\Factory::parseRangeString('::');
```

### Retrieve a range from its boundaries

[](#retrieve-a-range-from-its-boundaries)

You can calculate the smallest range that comprises two addresses:

```
$range = \IPLib\Factory::getRangeFromBoundaries('192.168.0.1', '192.168.255.255');

// This will print 192.168.0.0/16
echo (string) $range;
```

You can also calculate a list of ranges that exactly describes all the addresses between two addresses:

```
$ranges = \IPLib\Factory::getRangesFromBoundaries('192.168.0.0', '192.168.0.5');

// This will print 192.168.0.0/30 192.168.0.4/31
echo implode(' ', $ranges);
```

### Retrieve the boundaries of a range

[](#retrieve-the-boundaries-of-a-range)

```
$range = \IPLib\Factory::parseRangeString('127.0.0.*');

// This will print 127.0.0.0
echo (string) $range->getStartAddress();

// This will print 127.0.0.255
echo (string) $range->getEndAddress();
```

### Format addresses and ranges

[](#format-addresses-and-ranges)

Both IP addresses and ranges have a `toString` method that you can use to retrieve a textual representation:

```
// This will print 127.0.0.1
echo \IPLib\Factory::parseAddressString('127.0.0.1')->toString();

// This will print 127.0.0.1
echo \IPLib\Factory::parseAddressString('127.000.000.001')->toString();

// This will print ::1
echo \IPLib\Factory::parseAddressString('::1')->toString();

// This will print ::1
echo \IPLib\Factory::parseAddressString('0:0::1')->toString();

// This will print ::1/64
echo \IPLib\Factory::parseRangeString('0:0::1/64')->toString();
```

When working with IPv6, you may want the full (expanded) representation of the addresses. In this case, simply use a `true` parameter for the `toString` method:

```
// This will print 0000:0000:0000:0000:0000:0000:0000:0000
echo \IPLib\Factory::parseAddressString('::')->toString(true);

// This will print 0000:0000:0000:0000:0000:0000:0000:0001
echo \IPLib\Factory::parseAddressString('::1')->toString(true);

// This will print 0fff:0000:0000:0000:0000:0000:0000:0000
echo \IPLib\Factory::parseAddressString('fff::')->toString(true);

// This will print 0000:0000:0000:0000:0000:0000:0000:0000
echo \IPLib\Factory::parseAddressString('::0:0')->toString(true);

// This will print 0001:0002:0003:0004:0005:0006:0007:0008
echo \IPLib\Factory::parseAddressString('1:2:3:4:5:6:7:8')->toString(true);

// This will print 0000:0000:0000:0000:0000:0000:0000:0001/64
echo \IPLib\Factory::parseRangeString('0:0::1/64')->toString();
```

The address and range objects implements the `__toString()` method, which call the `toString()` method. So, if you want the string (short) representation of an object, you can do any of the following:

```
$address = \IPLib\Address\IPv6::parseString('::1');

// All these will print ::1
echo $address->toString();
echo $address->toString(false);
echo (string) $address;
```

### Check if an address is contained in a range

[](#check-if-an-address-is-contained-in-a-range)

All the range types offer a `contains` method, and all the IP address types offer a `matches` method: you can call them to check if an address is contained in a range:

```
$address = \IPLib\Factory::parseAddressString('1:2:3:4:5:6:7:8');
$range = \IPLib\Factory::parseRangeString('0:0::1/64');

$contained = $address->matches($range);
// that's equivalent to
$contained = $range->contains($address);
```

Please remark that if the address is IPv4 and the range is IPv6 (or vice-versa), the result will always be `false`.

### Check if a range contains another range

[](#check-if-a-range-contains-another-range)

All the range types offer a `containsRange` method: you can call them to check if an address range fully contains another range:

```
$range1 = \IPLib\Factory::parseRangeString('0:0::1/64');
$range2 = \IPLib\Factory::parseRangeString('0:0::1/65');

$contained = $range1->containsRange($range2);
```

### Getting the type of an IP address

[](#getting-the-type-of-an-ip-address)

If you want to know if an address is within a private network, or if it's a public IP, or whatever you want, you can use the `getRangeType` method:

```
$address = \IPLib\Factory::parseAddressString('::');

$type = $address->getRangeType();

$typeName = \IPLib\Range\Type::getName($type);
```

The most notable values of the range type are:

- `\IPLib\Range\Type::T_UNSPECIFIED` if the address is all zeros (`0.0.0.0` or `::`)
- `\IPLib\Range\Type::T_LOOPBACK` if the address is the localhost (usually `127.0.0.1` or `::1`)
- `\IPLib\Range\Type::T_PRIVATENETWORK` if the address is in the local network (for instance `192.168.0.1` or `fc00::1`)
- `\IPLib\Range\Type::T_PUBLIC` if the address is for public usage (for instance `104.25.25.33` or `2001:503:ba3e::2:30`)

### Getting the type of an IP address range

[](#getting-the-type-of-an-ip-address-range)

If you want to know the type of an address range, you can use the `getRangeType` method:

```
$range = \IPLib\Factory::parseRangeString('2000:0::1/64');

// $type will contain the value of \IPLib\Range\Type::T_PUBLIC
$type = $range->getRangeType();

// This will print Public address
echo \IPLib\Range\Type::getName($type);
```

Please note that if a range spans across multiple range types, you'll get NULL as the range type:

```
$range = \IPLib\Factory::parseRangeString('::/127');

// $type will contain null
$type = $range->getRangeType();

// This will print Unknown type
echo \IPLib\Range\Type::getName($type);
```

### Converting IP addresses

[](#converting-ip-addresses)

This library supports converting IPv4 to/from IPv6 addresses using the [6to4 notation](https://tools.ietf.org/html/rfc3056) or the [IPv4-mapped notation](https://tools.ietf.org/html/rfc4291#section-2.5.5.2):

```
$ipv4 = \IPLib\Factory::parseAddressString('1.2.3.4');

// 6to4 notation
$ipv6 = $ipv4->toIPv6();

// This will print 2002:102:304::
echo (string) $ipv6;

// This will print 1.2.3.4
echo $ipv6->toIPv4();

// IPv4-mapped notation
$ipv6_6to4 = $ipv4->toIPv6IPv4Mapped();

// This will print ::ffff:1.2.3.4
echo (string) $ipv6_6to4;

// This will print 1.2.3.4
echo $ipv6_6to4->toIPv4();
```

### Converting IP ranges

[](#converting-ip-ranges)

This library supports IPv4/IPv6 ranges in pattern format (eg. `192.168.*.*`) and in CIDR/subnet format (eg. `192.168.0.0/16`), and it offers a way to convert between the two formats:

```
// This will print ::*:*:*:*
echo \IPLib\Factory::parseRangeString('::/64')->asPattern()->toString();

// This will print 1:2::/96
echo \IPLib\Factory::parseRangeString('1:2::*:*')->asSubnet()->toString();

// This will print 192.168.0.0/24
echo \IPLib\Factory::parseRangeString('192.168.0.*')->asSubnet()->toString();

// This will print 10.*.*.*
echo \IPLib\Factory::parseRangeString('10.0.0.0/8')->asPattern()->toString();
```

Please remark that all the range types implement the `asPattern()` and `asSubnet()` methods.

### Getting the subnet mask for IPv4 ranges

[](#getting-the-subnet-mask-for-ipv4-ranges)

You can use the `getSubnetMask()` to get the subnet mask for IPv4 ranges:

```
// This will print 255.255.255.0
echo \IPLib\Factory::parseRangeString('192.168.0.*')->getSubnetMask()->toString();

// This will print 255.255.255.252
echo \IPLib\Factory::parseRangeString('192.168.0.12/30')->getSubnetMask()->toString();
```

### Getting the range size

[](#getting-the-range-size)

You can use the `getSize()` to get the count of addresses this IP range contains:

```
// This will print 256
echo \IPLib\Factory::parseRangeString('192.168.0.*')->getSize();

// This will print 4
echo \IPLib\Factory::parseRangeString('192.168.0.12/30')->getSize();

// This will print 1
echo \IPLib\Factory::parseRangeString('192.168.0.1')->getSize();
```

### Getting the reverse DNS lookup address

[](#getting-the-reverse-dns-lookup-address)

To perform reverse DNS queries, you need to use a special format of the IP addresses.

You can use the `getReverseDNSLookupName()` method of the IP address instances to retrieve it easily:

```
$ipv4 = \IPLib\Factory::parseAddressString('1.2.3.255');
$ipv6 = \IPLib\Factory::parseAddressString('1234:abcd::cafe:babe');

// This will print 255.3.2.1.in-addr.arpa
echo $ipv4->getReverseDNSLookupName();

// This will print e.b.a.b.e.f.a.c.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.d.c.b.a.4.3.2.1.ip6.arpa
echo $ipv6->getReverseDNSLookupName();
```

To parse addresses in reverse DNS lookup format you can use the `IPLib\ParseStringFlag::ADDRESS_MAYBE_RDNS` flag when parsing a string:

```
$ipv4 = \IPLib\Factory::parseAddressString('255.3.2.1.in-addr.arpa', \IPLib\ParseStringFlag::ADDRESS_MAYBE_RDNS);
$ipv6 = \IPLib\Factory::parseAddressString('e.b.a.b.e.f.a.c.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.d.c.b.a.4.3.2.1.ip6.arpa', \IPLib\ParseStringFlag::ADDRESS_MAYBE_RDNS);

// This will print 1.2.3.255
echo $ipv4->toString();

// This will print 1234:abcd::cafe:babe
echo $ipv6->toString();
```

You can also use `getReverseDNSLookupName()` for IP ranges. In this case, the result is an array of strings:

```
$range = \IPLib\Factory::parseRangeString('10.155.16.0/22');

/*
 * This will print:
 * array (
 *   0 => '16.155.10.in-addr.arpa',
 *   1 => '17.155.10.in-addr.arpa',
 *   2 => '18.155.10.in-addr.arpa',
 *   3 => '19.155.10.in-addr.arpa',
 * )
*/
var_export($range->getReverseDNSLookupName());
```

### Using a database

[](#using-a-database)

This package offers a great feature: you can store address ranges in a database table, and check if an address is contained in one of the saved ranges with a simple query.

To save a range, you need to store the address type (for IPv4 it's `4`, for IPv6 it's `6`), as well as two values representing the start and the end of the range. These methods are:

```
$range->getAddressType();
$range->getComparableStartString();
$range->getComparableEndString();
```

Let's assume that you saved the type in a field called `addressType`, and the range boundaries in two fields called `rangeFrom` and `rangeTo`.

When you want to check if an address is within a stored range, simply use the `getComparableString` method of the address and check if it's between the fields `rangeFrom` and `rangeTo`, and check if the stored `addressType` is the same as the one of the address instance you want to check.

Here's a sample code:

```
/*
 * Let's assume that:
 * - $pdo is a PDO instance
 * - $range is a range object
 * - $address is an address object
 */

// Save the $range object
$insertQuery = $pdo->prepare('
    insert into ranges (addressType, rangeFrom, rangeTo)
    values (:addressType, :rangeFrom, :rangeTo)
');

$insertQuery->execute(array(
    ':addressType' => $range->getAddressType(),
    ':rangeFrom' => $range->getComparableStartString(),
    ':rangeTo' => $range->getComparableEndString(),
));

// Retrieve the saved ranges where an address $address falls:
$searchQuery = $pdo->prepare('
    select * from ranges
    where addressType = :addressType
    and :address between rangeFrom and rangeTo
');

$searchQuery->execute(array(
    ':addressType' => $address->getAddressType(),
    ':address' => $address->getComparableString(),
));

$rows = $searchQuery->fetchAll();
$searchQuery->closeCursor();
```

Handling non-standard address and range strings
-----------------------------------------------

[](#handling-non-standard-address-and-range-strings)

### Accepting ports

[](#accepting-ports)

If you want to accept addresses that may include ports, you can specify the `IPLib\ParseStringFlag::MAY_INCLUDE_PORT` flag:

```
use IPLib\Factory;
use IPLib\ParseStringFlag;

require_once __DIR__ . '/../ip-lib.php';

// These will print NULL
var_export(Factory::parseAddressString('127.0.0.1:80'));
var_export(Factory::parseAddressString('[::]:80'));

// This will print 127.0.0.1
echo (string) Factory::parseAddressString('127.0.0.1:80', ParseStringFlag::MAY_INCLUDE_PORT);
// This will print ::
echo (string) Factory::parseAddressString('[::]:80', ParseStringFlag::MAY_INCLUDE_PORT);
```

### Accepting IPv6 zone IDs

[](#accepting-ipv6-zone-ids)

If you want to accept IPv6 addresses that may include a zone ID, you can specify the `IPLib\ParseStringFlag::MAY_INCLUDE_ZONEID` flag:

```
use IPLib\Factory;
use IPLib\ParseStringFlag;

// This will print NULL
var_export(Factory::parseAddressString('::%11'));

// This will print ::
echo (string) Factory::parseAddressString('::%11', ParseStringFlag::MAY_INCLUDE_ZONEID);
```

### Accepting non-decimal IPv4 addresses

[](#accepting-non-decimal-ipv4-addresses)

IPv4 addresses are usually expressed in decimal notation, for example as `192.168.0.1`.

By the way, the GNU (used in many Linux distros), BSD (used in Mac) and Windows implementations of `inet_aton` and `inet_addr` accept IPv4 addresses with numbers in octal and/or hexadecimal format. Please remark that this does not apply to the `inet_pton` and `ip2long` functions, as well as to the Musl implementation (used in Alpine Linux) of `inet_aton` and `inet_addr`.

So, for example, these addresses are all equivalent to `192.168.0.1`:

- `0xC0.0xA8.0x0.0x01` (only hexadecimal)
- `0300.0250.00.01` (only octal)
- `192.0250.0.0x01` (decimal, octal and hexadecimal numbers)

(try it: if you browse to [`http://0177.0.0.0x1`](http://0177.0.0.0x1), your browser will try to browse `http://127.0.0.1`).

If you want to accept this non-decimal syntax, you may use the `IPLib\ParseStringFlag::IPV4_MAYBE_NON_DECIMAL` flag:

```
use IPLib\Factory;
use IPLib\ParseStringFlag;

// This will print NULL
var_export(Factory::parseAddressString('0177.0.0.0x1'));

// This will print 127.0.0.1
var_export((string) Factory::parseAddressString('0177.0.0.0x1', ParseStringFlag::IPV4_MAYBE_NON_DECIMAL));

// This will print NULL
var_export(Factory::parseRangeString('0177.0.0.0x1/32'));

// This will print 127.0.0.1/32
var_export((string) Factory::parseRangeString('0177.0.0.0x1/32', ParseStringFlag::IPV4_MAYBE_NON_DECIMAL));
```

Please be aware that the `IPV4_MAYBE_NON_DECIMAL` flag may also affect parsing decimal numbers:

```
use IPLib\Factory;
use IPLib\ParseStringFlag;

// This will print 127.0.0.10 since the last digit is assumed to be decimal
var_export((string) Factory::parseAddressString('127.0.0.010'));

// This will print 127.0.0.8 since the last digit is assumed to be octal
var_export((string) Factory::parseAddressString('127.0.0.010', ParseStringFlag::IPV4_MAYBE_NON_DECIMAL));
```

### Accepting IPv4 addresses in not-quad-dotted notation

[](#accepting-ipv4-addresses-in-not-quad-dotted-notation)

IPv4 addresses are usually expressed with 4 numbers, for example as `192.168.0.1`.

By the way, the GNU (used in many Linux distros), BSD (used in Mac) and Windows implementations of `inet_aton` and `inet_addr` [accept IPv4 addresses with 1 to 4 numbers](https://man7.org/linux/man-pages/man3/inet_addr.3.html#DESCRIPTION).

Please remark that this does not apply to the `inet_pton` and `ip2long` functions, as well as to the Musl implementation (used in Alpine Linux) of `inet_aton` and `inet_addr`.

If you want to accept this non-decimal syntax, you may use the `IPLib\ParseStringFlag::IPV4ADDRESS_MAYBE_NON_QUAD_DOTTED` flag:

```
use IPLib\Factory;
use IPLib\ParseStringFlag;

// This will print NULL
var_export(Factory::parseAddressString('1.2.500'));

// This will print 0.0.0.0
var_export((string) Factory::parseAddressString('0', ParseStringFlag::IPV4ADDRESS_MAYBE_NON_QUAD_DOTTED));

// This will print 0.0.0.1
var_export((string) Factory::parseAddressString('1', ParseStringFlag::IPV4ADDRESS_MAYBE_NON_QUAD_DOTTED));

// This will print 0.0.1.244
var_export((string) Factory::parseAddressString('0.0.500', ParseStringFlag::IPV4ADDRESS_MAYBE_NON_QUAD_DOTTED));

// This will print 255.255.255.255
var_export((string) Factory::parseAddressString('4294967295', ParseStringFlag::IPV4ADDRESS_MAYBE_NON_QUAD_DOTTED));
```

### Accepting compact IPv4 subnet notation

[](#accepting-compact-ipv4-subnet-notation)

Even if there isn't an RFC that describe it, IPv4 subnet notation may also be written in a compact form, omitting extra digits (for example, `127.0.0.0/24` may be written as `127/24`). If you want to accept such format, you can specify the `IPLib\ParseStringFlag::IPV4SUBNET_MAYBE_COMPACT` flag:

```
use IPLib\Factory;
use IPLib\ParseStringFlag;

// This will print NULL
var_export(Factory::parseRangeString('127/24'));

// This will print 127.0.0.0/24
echo (string) Factory::parseRangeString('127/24', ParseStringFlag::IPV4SUBNET_MAYBE_COMPACT);
```

### Combining multiple flags

[](#combining-multiple-flags)

Of course, you may use more than one `IPLib\ParseStringFlag` flag at once:

```
use IPLib\Factory;
use IPLib\ParseStringFlag;

// This will print 127.0.0.255
var_export((string) Factory::parseAddressString('127.0.0.0xff:80', ParseStringFlag::MAY_INCLUDE_PORT | ParseStringFlag::IPV4_MAYBE_NON_DECIMAL));

// This will print ::
var_export((string) Factory::parseAddressString('[::%11]:80', ParseStringFlag::MAY_INCLUDE_PORT | ParseStringFlag::MAY_INCLUDE_ZONEID));
```

Gitpod Environment Variables
----------------------------

[](#gitpod-environment-variables)

The following features can be enabled through environment variables that have been set in your [Gitpod preferences](https://gitpod.io/variables).:

\* *Please note that storing sensitive data in environment variables is not ultimately secure but should be OK for most development situations.*

- ### Sign Git commits with a GPG key

    [](#sign-git-commits-with-a-gpg-key)

    - `GPG_KEY_ID` (required)
        - The ID of the GPG key you want to use to sign your git commits
    - `GPG_KEY` (required)
        - Base64 encoded private GPG key that corresponds to your `GPG_KEY_ID`
    - `GPG_MATCH_GIT_TO_EMAIL` (optional)
        - Sets your git user.email in `~/.gitconfig` to the value provided
    - `GPG_AUTO_ULTIMATE_TRUST` (optional)
        - If the value is set to `yes` or `YES` then your `GPG_KEY` will be automatically ultimately trusted
- ### Activate an Intelliphense License Key

    [](#activate-an-intelliphense-license-key)

    - `INTELEPHENSE_LICENSEKEY`
        - Creates `~/intelephense/licence.txt` and will contain the value provided
        - This will activate [Intelliphense](https://intelephense.com/) for you each time the workspace is created or restarted

Do you really want to say thank you?
------------------------------------

[](#do-you-really-want-to-say-thank-you)

You can offer me a [monthly coffee](https://github.com/sponsors/mlocati) or a [one-time coffee](https://paypal.me/mlocati) 😉

###  Health Score

13

—

LowBetter than 1% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity1

Limited adoption so far

Community16

Small or concentrated contributor base

Maturity18

Early-stage or recently created project

 Bus Factor1

Top contributor holds 84.7% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://www.gravatar.com/avatar/5c818085e28bfa56c39e978ee317fc88ffa1aa47450d78fc080a4de212d9e4e0?d=identicon)[peanut](/maintainers/peanut)

---

Top Contributors

[![mlocati](https://avatars.githubusercontent.com/u/928116?v=4)](https://github.com/mlocati "mlocati (161 commits)")[![ernix](https://avatars.githubusercontent.com/u/343556?v=4)](https://github.com/ernix "ernix (10 commits)")[![metagusto-opensource](https://avatars.githubusercontent.com/u/17709402?v=4)](https://github.com/metagusto-opensource "metagusto-opensource (3 commits)")[![vstelmakh](https://avatars.githubusercontent.com/u/2980619?v=4)](https://github.com/vstelmakh "vstelmakh (3 commits)")[![peter279k](https://avatars.githubusercontent.com/u/9021747?v=4)](https://github.com/peter279k "peter279k (2 commits)")[![Empornium](https://avatars.githubusercontent.com/u/25505583?v=4)](https://github.com/Empornium "Empornium (2 commits)")[![yejune](https://avatars.githubusercontent.com/u/3735511?v=4)](https://github.com/yejune "yejune (2 commits)")[![mikeSimonson](https://avatars.githubusercontent.com/u/907613?v=4)](https://github.com/mikeSimonson "mikeSimonson (1 commits)")[![detain](https://avatars.githubusercontent.com/u/1364504?v=4)](https://github.com/detain "detain (1 commits)")[![githubjeka](https://avatars.githubusercontent.com/u/874234?v=4)](https://github.com/githubjeka "githubjeka (1 commits)")[![henry-spanka](https://avatars.githubusercontent.com/u/10375269?v=4)](https://github.com/henry-spanka "henry-spanka (1 commits)")[![cowsay1](https://avatars.githubusercontent.com/u/60675651?v=4)](https://github.com/cowsay1 "cowsay1 (1 commits)")[![strausmann](https://avatars.githubusercontent.com/u/4519228?v=4)](https://github.com/strausmann "strausmann (1 commits)")[![tomsim](https://avatars.githubusercontent.com/u/16625255?v=4)](https://github.com/tomsim "tomsim (1 commits)")

### Embed Badge

![Health badge](/badges/limepie-ip-lib/health.svg)

```
[![Health](https://phpackages.com/badges/limepie-ip-lib/health.svg)](https://phpackages.com/packages/limepie-ip-lib)
```

###  Alternatives

[wireui/wireui

TallStack components

1.8k1.3M16](/packages/wireui-wireui)[sllh/composer-versions-check

Checks if packages are up to date to last major versions after update

2352.4M16](/packages/sllh-composer-versions-check)[verbb/buttonbox

A collection of utility field types.

8963.7k1](/packages/verbb-buttonbox)[overtrue/php-opencc

中文简繁转换，支持词汇级别的转换、异体字转换和地区习惯用词转换（中国大陆、台湾、香港、日本新字体）。基于 \[BYVoid/OpenCC\](https://github.com/BYVoid/OpenCC) 数据实现。

12130.7k](/packages/overtrue-php-opencc)[opensoft/rollout-bundle

A Symfony2/3/4 Bundle for opensoft/rollout

42122.0k](/packages/opensoft-rollout-bundle)[armincms/json

A Laravel Nova field.

25149.4k3](/packages/armincms-json)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
