apacheborys / location-bundle
用于操作和存储地点的地点包
Requires
- php: ^7.0
Requires (Dev)
- phpunit/phpunit: ^6.5 || ^7.5
- symfony/cache: 3.4.37
This package is auto-updated.
Last update: 2024-09-06 03:46:45 UTC
README
使用此包,您可以构建自己的地理数据服务器。操作功能
优点
- 节省对真实地理数据提供者的请求(如果您将其用作缓存)
- 自己驱动的性能控制
- 有机会构建自己的地点、地点
- 可以使用高精度的坐标值(以浮点类型存储)
- 与地点工作的成品解决方案
安装
composer require apacheborys/location-bundle
用法
首先,您需要设置存储,其中将保存有关位置的数据库。可用的数据库提供者这里。例如,您可以使用FilesystemAdapter。
$database = new \Symfony\Component\Cache\Adapter\FilesystemAdapter();
之后,您需要设置数据库配置。如果您不想这样做,您可以通过创建不带任何参数的类来使用默认配置。注意useCompression
标志,它可以帮助节省存储空间。如果您将使用压缩,请确保您的数据库能够保存二进制数据。
$dbConfig = new \ApacheBorys\Location\Model\DBConfig();
之后,您就可以使用Location bundle了
$locationBundle = new \ApacheBorys\Location\Location($database, $dbConfig);
请注意,您需要关注您使用的数据库中保存的数据。此外,在最初,您需要添加您想要查找的未来地点。数据库中的每个地点都是一个特定的Place实体,它包含Address实体的集合和属性 - Polygons
、Bounds
、timezone
、providedBy
、currentLocale
和objectHash
。下面是一个如何保存信息的示例。这只是示例,请勿在生产环境中使用。
$headers = [ 'Accept-language' => 'en' ]; /* query for Kiev city, Ukraine */ $query = [ 'format' => 'geocodejson', 'osm_ids' => 'R421866', 'polygon_geojson' => 1, 'addressdetails' => 1, ]; $request = new \http\Client\Request('GET', 'https://nominatim.openstreetmap.org/lookup?' . http_build_query($query), $headers); /** @var \Psr\Http\Message\ResponseInterface $response */ $response = new \Http\Client\HttpClient($request); $rawGeoCodeJson = json_decode((string) $response->getBody()); $query['format'] = 'geojson'; unset($query['polygon_geojson'], $query['addressdetails']); $request = new \http\Client\Request('GET', 'https://nominatim.openstreetmap.org/lookup?' . http_build_query($query), $headers); $response = new \Http\Client\HttpClient($request); $rawGeoJson = json_decode((string) $response->getBody()); $rawGeoCodeJson['features'][0]['properties']['common']['bbox'] = $rawGeoJson['features'][0]['bbox']; $rawGeoCodeJson['features'][0]['properties']['common']['postcode'] = $rawGeoJson['features'][0]['properties']['address']['postcode']; $rawGeoCodeJson['features'][0]['properties']['geocoding']['country_code'] = $rawGeoJson['features'][0]['properties']['address']['country_code']; $locationBundle->addPlace(mapRawDataToPlace($rawGeoCodeJson)); private function mapRawDataToPlace(array $rawData): \ApacheBorys\Location\Model\Place { $root = $rawData['features'][0]; $polygons = []; foreach ($root['geometry']['coordinates'] as $rawPolygon) { $tempPolygon = new \ApacheBorys\Location\Model\Polygon(); foreach ($rawPolygon as $coordinates) { $tempPolygon->addCoordinates(new \ApacheBorys\Location\Model\Coordinates($coordinates[0], $coordinates[1])); } $polygons[] = $tempPolygon; } $addresses = []; foreach ($root['properties'] as $locale => $rawAddress) { if ('common' === $locale) { continue; } $addresses[$locale] = $this->mapRawDataToAddress($rawAddress, $locale); } return new \ApacheBorys\Location\Model\Place( $addresses, $polygons, \ApacheBorys\Location\Model\Place::DEFAULT_LOCALE, $root['properties']['common']['postcode'], null, $rawData['geocoding']['attribution'], new \ApacheBorys\Location\Model\Bounds( $root['properties']['common']['bbox'][0], $root['properties']['common']['bbox'][1], $root['properties']['common']['bbox'][2], $root['properties']['common']['bbox'][3] ) ); } private function mapRawDataToAddress(array $rawData, string $locale): \ApacheBorys\Location\Model\Address { $adminLevels = []; foreach ($rawData['geocoding']['admin'] as $adminLevel => $name) { $level = (int) substr($adminLevel, 5); $adminLevels[$level] = new \ApacheBorys\Location\Model\AdminLevel($level, $name); } return new \ApacheBorys\Location\Model\Address( $locale, new \ApacheBorys\Location\Model\AdminLevelCollection($adminLevels), $rawData['geocoding']['housenumber'] ?? '', $rawData['geocoding']['street'] ?? '', $rawData['geocoding']['state'] ?? '', $rawData['geocoding']['city'] ?? '', new \ApacheBorys\Location\Model\Country($rawData['geocoding']['country'], $rawData['geocoding']['country_code']) ); }
添加上述地点后,您将在reverseQuery
中收到该地点的任何包含在地点的多边形中的坐标。如果您添加具有最高行政级别的地点,您将收到新的地点。该提供者每次都会尝试为reverseQuery
方法提供具有最高行政级别的地点。
查找包含特定坐标点的地点
$address = $locationBundle->reverseQuery( new \ApacheBorys\Location\Query\ReverseQuery(new \ApacheBorys\Location\Model\Coordinates(50.4422519, 30.5423135)) );
通过文本查找地点
对于geocodeQuery
,请使用您想要查找的任何文本。
$address = $locationBundle->geocodeQuery(new \ApacheBorys\Location\Query\GeocodeQuery('Kyiv, Ukraine'));
有用功能
测量两个坐标之间的距离
为了测量距离,请将两个坐标传递给distance方法。请注意,高度也用于计算。
$distance = $this->location->distance( new \ApacheBorys\Location\Model\Coordinates(30.520620, 50.455414, 172.6), new \ApacheBorys\Location\Model\Coordinates(30.557294, 50.434596, 190.8) );
结果,您将得到未经四舍五入的公里数。结果,您将拥有超过毫米的精度。
在不同的地点中找到共同点
如果您想要找到与一个特定地点相邻的地点,这很容易做到。您还可以找到用于构建路径的交叉路线。您可以尝试找到包含共同点的所有地点。请注意,您可以指定要检查的地点作为第三个参数。
$neighbours = $this->location->findTouchedPlaces( $originalPlace, $maxDistanceToBorder, $specificPlaces );
其中originalPlace
是我们将用作基础的地点。并尝试从其他地点中找到共同点。maxDistanceToBorder
是到可能的共同点的最小距离的浮点值。默认值为100米。specificPlaces
是地点数组。如果您将一些地点传递给该参数,Location bundle将只检查该参数中的地点以查找共同点。
与数据库一起工作
该包具有实现数据库功能的方法
addPlace
- 添加Place对象,返回布尔值deletePlace
- 删除地点对象,返回布尔值getAllPlaces
- 获取数据库中所有存在的地点,返回\ApacheBorys\Location\Model\Place
对象数组。请注意分页。
请注意,数据库中每个地点对象都是根据 objectHash
属性进行标识的。请将该属性用作只读属性。如果您更改该属性,数据库提供程序将丢失与数据库中该地点的关系。
请注意,每个地址对象在数据库中的标识方式
- 管理员级别 - 管理员级别名称
- 地区、子地区、街道名称、街道号码
如果您想更改地点实体,应该删除该地点,然后添加一个新的地点,该地点包含已更改的对象。同时,请注意,数据库中的每个对象都有生命周期值(对于 PSR-6)。默认值为 365 天(1 年),您可以通过在创建 \ApacheBorys\Location\Model\DBConfig
时传递特定参数来设置它。
数据库提供程序
您可以选择要使用的数据库提供程序。现在有 2 个提供程序可用
\ApacheBorys\Location\Database\PdoDatabase
\ApacheBorys\Location\Database\Psr6Database
同时,请注意 \ApacheBorys\Location\Model\DBConfig
。您可以在其中找到许多配置值,这些值可以提供微调的可能性。
如果您想节省存储空间,可以在此处启用数据压缩 \ApacheBorys\Location\Model\DBConfig::$useCompression
。请注意,您可以在此处调整压缩级别 \ApacheBorys\Location\Model\DBConfig::$compressionLevel
(1-9 个值,默认为 5)。请注意,压缩通过命令 gzuncompress 和 gzcompress 执行。请注意,数据在压缩状态之间迁移时自行处理。
如果您不想在数据库中使用数据,应该自行处理删除。
PdoDatabase
如果您计划将地点存储在 sqlite、mysql 或 postgresql 中,可以使用此提供程序。对于构造函数,您需要将 \PDO
对象作为第一个参数传递。在第一次调用提供程序时将创建的表名称 - \ApacheBorys\Location\Database\PdoDatabase\HelperInterface::queryForCreateTables
。
Psr6Database
此提供程序更简单,将地点实体的数据存储在缓存中。请注意数据的有效时间(TTL),因为通常每个缓存(PSR-6)提供程序都有标准的 TTL 值。您还可以通过指定 \ApacheBorys\Location\Model\DBConfig::$ttlForRecord
的 TTL 值来调整它,默认值为 \ApacheBorys\Location\Model\DBConfig::TTL_FOR_RECORD
。
对于构造函数,您需要将实现 \Psr\Cache\CacheItemPoolInterface
的任何对象作为第一个参数传递。
测试
请运行 composer test
。
警告
请注意,每个地理数据都有所有者,并且您只能用于合法目的。