定制 foysal50x/h3-php 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

foysal50x/h3-php

Composer 安装命令:

composer require foysal50x/h3-php

包简介

PHP FFI bindings for Uber's H3 hexagonal hierarchical geospatial indexing system

README 文档

README

H3 PHP Build Status Tests Latest Stable Version

H3 PHP FFI Bindings

PHP FFI bindings for Uber's H3 hexagonal hierarchical geospatial indexing system.

Based on H3 v4.4.1 - the latest version as of November 2025.

Requirements

  • PHP 8.1 or higher
  • PHP FFI extension enabled (ffi.enable=1 in php.ini)

Installation

1. Enable PHP FFI Extension

The FFI extension must be enabled in your php.ini:

; Enable the FFI extension
extension=ffi

; Enable FFI for all scripts (required for this library)
ffi.enable=true

Note: ffi.enable can be set to:

  • true or 1 - Enable FFI for all scripts (recommended for development)
  • preload - Enable FFI only in preloaded scripts (recommended for production)

To verify FFI is enabled:

php -m | grep FFI
php -i | grep ffi.enable

2. Install the PHP Package

composer require foysal50x/h3-php

This package includes pre-built H3 libraries for common platforms:

  • macOS (Apple Silicon & Intel)
  • Linux (x64 & ARM64)
  • Windows (x64)

The library will automatically detect and use the appropriate bundled binary.

3. (Optional) System H3 Library

If the bundled library doesn't work for your platform, you can install the H3 C library system-wide:

macOS (Homebrew):

brew install h3

Ubuntu/Debian:

sudo apt install libh3-dev

From source:

git clone https://github.com/uber/h3.git
cd h3
cmake -B build
cmake --build build
sudo cmake --install build

Quick Start

<?php

use Foysal50x\H3\H3;

$h3 = new H3();

// Convert coordinates to H3 cell
$cell = $h3->latLngToCell(37.7749, -122.4194, 9);
echo "H3 Index: " . $h3->h3ToString($cell) . "\n";

// Get cell center coordinates
$coords = $h3->cellToLatLng($cell);
echo "Center: {$coords['lat']}, {$coords['lng']}\n";

// Get neighboring cells
$neighbors = $h3->gridDisk($cell, 1);
echo "Neighbors: " . count($neighbors) . "\n";

API Reference

Indexing Functions

// Convert lat/lng to H3 cell
$cell = $h3->latLngToCell(float $lat, float $lng, int $resolution): int

// Convert H3 cell to lat/lng center
$coords = $h3->cellToLatLng(int $cell): array{lat: float, lng: float}

// Get cell boundary vertices
$boundary = $h3->cellToBoundary(int $cell): array

Inspection Functions

$h3->getResolution(int $cell): int
$h3->getBaseCellNumber(int $cell): int
$h3->h3ToString(int $cell): string
$h3->stringToH3(string $str): int
$h3->isValidCell(int $cell): bool
$h3->isResClassIII(int $cell): bool
$h3->isPentagon(int $cell): bool

Traversal Functions

// Get all cells within k distance (filled disk)
$cells = $h3->gridDisk(int $origin, int $k): array

// Get cells with their distances
$results = $h3->gridDiskDistances(int $origin, int $k): array

// Get cells in a hollow ring at exactly k distance
$cells = $h3->gridRing(int $origin, int $k): array

// Get grid distance between two cells
$distance = $h3->gridDistance(int $origin, int $destination): int

// Get path between two cells
$path = $h3->gridPathCells(int $start, int $end): array

Hierarchy Functions

// Get parent cell at coarser resolution
$parent = $h3->cellToParent(int $cell, int $parentRes): int

// Get all children at finer resolution
$children = $h3->cellToChildren(int $cell, int $childRes): array

// Get center child at finer resolution
$child = $h3->cellToCenterChild(int $cell, int $childRes): int

// Compact cells to minimal representation
$compacted = $h3->compactCells(array $cells): array

// Uncompact cells to specific resolution
$cells = $h3->uncompactCells(array $cells, int $res): array

Directed Edge Functions

$h3->areNeighborCells(int $origin, int $destination): bool
$h3->cellsToDirectedEdge(int $origin, int $destination): int
$h3->isValidDirectedEdge(int $edge): bool
$h3->getDirectedEdgeOrigin(int $edge): int
$h3->getDirectedEdgeDestination(int $edge): int
$h3->directedEdgeToCells(int $edge): array{origin: int, destination: int}
$h3->originToDirectedEdges(int $origin): array
$h3->directedEdgeToBoundary(int $edge): array

Vertex Functions

$h3->cellToVertex(int $cell, int $vertexNum): int
$h3->cellToVertexes(int $cell): array
$h3->vertexToLatLng(int $vertex): array{lat: float, lng: float}
$h3->isValidVertex(int $vertex): bool

Measurement Functions

// Average hexagon area at resolution
$h3->getHexagonAreaAvgKm2(int $res): float
$h3->getHexagonAreaAvgM2(int $res): float

// Exact cell area
$h3->cellAreaKm2(int $cell): float
$h3->cellAreaM2(int $cell): float
$h3->cellAreaRads2(int $cell): float

// Average edge length at resolution
$h3->getHexagonEdgeLengthAvgKm(int $res): float
$h3->getHexagonEdgeLengthAvgM(int $res): float

// Exact edge length
$h3->edgeLengthKm(int $edge): float
$h3->edgeLengthM(int $edge): float
$h3->edgeLengthRads(int $edge): float

// Great circle distance between coordinates
$h3->greatCircleDistanceKm(float $lat1, float $lng1, float $lat2, float $lng2): float
$h3->greatCircleDistanceM(float $lat1, float $lng1, float $lat2, float $lng2): float

Utility Functions

$h3->getNumCells(int $res): int
$h3->getRes0Cells(): array
$h3->getPentagons(int $res): array
$h3->degsToRads(float $degrees): float
$h3->radsToDegs(float $radians): float

Local IJ Coordinates

$h3->cellToLocalIj(int $origin, int $cell, int $mode = 0): array{i: int, j: int}
$h3->localIjToCell(int $origin, int $i, int $j, int $mode = 0): int

Error Handling

All methods that can fail will throw an H3Exception:

use Foysal50x\H3\H3;
use Foysal50x\H3\H3Exception;

try {
    $h3 = new H3();
    $cell = $h3->latLngToCell(37.7749, -122.4194, 20); // Invalid resolution
} catch (H3Exception $e) {
    echo "Error: " . $e->getMessage() . "\n";
    echo "H3 Error Code: " . $e->getH3ErrorCode() . "\n";

    if ($e->isInvalidResolution()) {
        echo "Resolution must be between 0 and 15\n";
    }
}

Common Exceptions

The library will throw H3Exception in these cases:

  1. FFI Extension Not Loaded

    The FFI extension is not loaded. Please enable it in your php.ini by adding "extension=ffi".
    
  2. FFI Not Enabled

    FFI is not enabled. Please set "ffi.enable=true" or "ffi.enable=preload" in your php.ini.
    
  3. H3 Library Not Found

    Could not find H3 library. Please install H3 or provide the library path.
    

Custom Library Path

If the H3 library is not in a standard location:

$h3 = new H3('/custom/path/to/libh3.so');

Singleton Pattern

For convenience, you can use the singleton pattern:

$h3 = H3::getInstance();
// ... use $h3 ...

// Reset if needed (required before using a different library path)
H3::resetInstance();

Note: If you try to get an instance with a different library path than the existing singleton, an exception will be thrown. Call resetInstance() first if you need to change the library path.

Security & Safety Features

This library includes several security and safety measures to prevent common FFI-related vulnerabilities:

Input Validation

All user inputs are validated before being passed to the C library:

// Coordinate validation (rejects NaN, Inf, out of range)
$h3->latLngToCell(NAN, 0.0, 9);  // Throws H3Exception

// H3 string validation (rejects null bytes, invalid hex, too long)
$h3->stringToH3("invalid!");     // Throws H3Exception
$h3->stringToH3("abc\0def");     // Throws H3Exception (null byte)

// Resolution relationship validation
$h3->cellToChildren($cell, 3);   // Throws if cell resolution >= 3
$h3->cellToParent($cell, 10);    // Throws if cell resolution <= 10

Memory Safety

Grid operations have configurable limits to prevent memory exhaustion:

// Default max k value is 500 (results in ~751,501 cells)
$h3->gridDisk($cell, 1000);  // Throws H3Exception

// Adjust the limit if needed for your use case
H3::setMaxGridK(1000);
$h3->gridDisk($cell, 1000);  // Now works

// Check current limit
$maxK = H3::getMaxGridK();

Descriptive Error Messages

Exceptions include detailed error information:

try {
    $h3->cellToChildren($cell, 3);
} catch (H3Exception $e) {
    // "Failed to get children cells: Resolution mismatch (code: 12)"
    echo $e->getMessage();
    echo $e->getCode();  // H3 error code
}

Resolution Guide

Resolution Avg Hex Area Avg Edge Length
0 4,357,449.416 km² 1,281.256 km
1 609,788.441 km² 483.057 km
2 86,801.780 km² 182.512 km
3 12,393.434 km² 68.979 km
4 1,770.347 km² 26.071 km
5 252.903 km² 9.854 km
6 36.129 km² 3.724 km
7 5.161 km² 1.406 km
8 0.737 km² 531.414 m
9 0.105 km² 200.786 m
10 0.015 km² 75.863 m
11 0.002 km² 28.663 m
12 307.092 m² 10.830 m
13 43.870 m² 4.092 m
14 6.267 m² 1.546 m
15 0.895 m² 0.584 m

Running Tests

composer install
composer test

License

MIT License - see LICENSE file.

Links

foysal50x/h3-php 适用场景与选型建议

foysal50x/h3-php 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 8.1k 次下载、GitHub Stars 达 12, 最近一次更新时间为 2025 年 11 月 28 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「geography」 「gis」 「spatial」 「geospatial」 「indexing」 「hexagonal」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 foysal50x/h3-php 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 foysal50x/h3-php 我们能提供哪些服务?
定制开发 / 二次开发

基于 foysal50x/h3-php 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 8.1k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 12
  • 点击次数: 20
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 12
  • Watchers: 0
  • Forks: 2
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2025-11-28