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 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=1in 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:
trueor1- 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:
-
FFI Extension Not Loaded
The FFI extension is not loaded. Please enable it in your php.ini by adding "extension=ffi". -
FFI Not Enabled
FFI is not enabled. Please set "ffi.enable=true" or "ffi.enable=preload" in your php.ini. -
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 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 foysal50x/h3-php 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
QuadTree implementation in PHP
A library to manipulate KML/KMZ files
Geo-Toolkit for PHP
Cowegis GeoJSON - PHP GeoJSON specification (RFC 7946) implementation
Doctrine2 simple support for spatial types and functions
Open-source native PHP library for doing geometry operations. Can read and write a wide variety of formats: (E)WKT, (E)WKB, TWKB, GeoJSON, KML, GPX, GeoRSS. Works with all Simple-Feature geometries (Point, LineString, Polygon...) and can be used to get centroids, bounding-boxes, area, etc.
统计信息
- 总下载量: 8.1k
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 12
- 点击次数: 20
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2025-11-28
