北德教堂 / ndk
NDK 支持开发 PHP 客户端,以连接北德教堂数据库
Requires
- php: >=8.1
- doctrine/cache: ^2.2
- guzzlehttp/guzzle: ^7.5
- kevinrob/guzzle-cache-middleware: ^4.0
- monolog/monolog: ^2.9
- php-di/php-di: ^7.0
- phpdocumentor/reflection-docblock: ^5.3
Requires (Dev)
- hmaus/drafter-php: ^6.1
- phpmd/phpmd: ^2.13
- phpmetrics/phpmetrics: ^2.8
- phpunit/phpunit: ^10.0
- squizlabs/php_codesniffer: ^3.7
This package is not auto-updated.
Last update: 2024-09-26 15:37:22 UTC
README
NDK 支持开发 PHP 客户端,以连接北德福音路德教堂(北德教堂)的数据库。为此,它使用北德教堂 API(简称 "NAPI")来获取地址和活动数据。
可以通过 NAPI 读取哪些数据,可以在 NAPI 文档 中找到。相同的过滤器和对象属性也存在于 NDK 中。因此,可以将此文档与 IDE 或适当编辑器的 IntelliSense/Autocomplete 一起使用,以使用 NDK 和其对象。
NDK 不是与 NAPI 通信的先决条件。它仅提供创建自己的应用程序的工具。
在此项目中使用的命名空间符合 PSR-4 标准。因此,在此文档中不会直接引用文件,而是引用命名空间和类名。
安装
安装最新版本
$ composer require nordkirche/ndk
设置
<?php $configuration = new \Nordkirche\Ndk\Configuration( getenv('NAPI_ID'), getenv('NAPI_ACCESSTOKEN') ); $configuration->setNapiHost('www.nordkirche.de')->setNapiPath('api/'); $api = new \Nordkirche\Ndk\Api($configuration);
NDK 依赖于一个配置对象,该对象至少需要用 ID 和访问令牌以及官方 NAPI 终结点进行初始化,以包含访问数据。
这样就可以初始化 NDK API,以在配置过程中获取其他对象。
数据查询
可以通过存储库类查询数据。所有可用的类都位于 \Nordkirche\Ndk\Domain\Repository
下。
可以通过查询类定义查询的过滤器和参数。所有查询类都位于 \Nordkirche\Ndk\Domain\Query
下。
所有存储库都可以使用 \Nordkirche\Ndk\Domain\Query\PageQuery
或 \Nordkirche\Ndk\Domain\Query\SimpleQuery
查询。一些但不是所有存储库都有特定的查询类,以便应用特殊过滤器。这些类遵循以下命名方案
\Nordkirche\Ndk\Domain\Repository\*Repository -> \Nordkirche\Ndk\Domain\Query\*Query
并且始终由 \Nordkirche\Ndk\Domain\Query\PageQuery
类派生。
查询中可用的存储库和过滤选项与 NAPI 文档中的端点和过滤选项等效。
示例查询
<?php $api = new \Nordkirche\Ndk\Api($configuration); $repository = $api->factory(\Nordkirche\Ndk\Domain\Repository\InstitutionRepository::class); $result = $repository->get(new \Nordkirche\Ndk\Domain\Query\InstitutionQuery()); foreach ($result as $institution) { echo $institution->getLabel() . ' (' . $institution->getName() . ')' . PHP_EOL; }
此示例包含两部分。一方面是初始化 API 和使用 factory()
方法创建存储库对象,另一方面是使用查询对象查询数据。
<?php $api = new \Nordkirche\Ndk\Api($configuration); $repository = $api->factory(\Nordkirche\Ndk\Domain\Repository\InstitutionRepository::class);
NDK 使用存储库,这些存储库代表 NAPI 的不同端点。在此示例中,我们使用了 InstitutionRepository
来查询机构。API 的 factory()
方法使用先前定义的配置实例化我们的存储库。
<?php $result = $repository->get(new \Nordkirche\Ndk\Domain\Query\InstitutionQuery()); foreach ($result as $institution) { echo $institution->getLabel() . ' (' . $institution->getName() . ')' . PHP_EOL; }
使用 get()
方法和查询对象查询机构列表。NDK 将这些打包到 \Nordkirche\Ndk\Service\Result
类的对象中,该对象除了以 \Nordkirche\Ndk\Domain\Model\Institution\Instituion
对象的形式提供资源对象外,还包含有关请求的额外元数据。
NAPI 按分页提供结果。因此,我们只能获得第一页。
元数据例如找到的所有对象的数量、当前页上的对象数量、可能的相关维度以进行进一步的过滤等。
此示例可以直接在 examples/2_simple_request.php
中执行。
查询
用户获取的页面、是否需要根据特定数据进行搜索或筛选等,都由一个查询对象决定。例如,在之前的示例中,使用了类 \Nordkirche\Ndk\Domain\Query\InstitutionQuery
。
由于大多数请求都是分页的,所以类 \Nordkirche\Ndk\Domain\Query\PageQuery
通常作为所有 *Query
类的父类。它可以用于所有查询,但如果没有特别指定,它将不提供如邮政编码之类的特殊筛选功能。
<?php $query = new \Nordkirche\Ndk\Domain\Query\InstitutionQuery(); $query->setPageSize(30)->setPageNumber(2)->setZipCodes([24103]); $result = $repository->get($query);
如 InstitutionQuery
这样的对象提供了各种选项来修改请求。除了定义所需页面 setPageNumber()
和每页条目数 setPageSize()
的常规选项外,我们还可以在机构和人员的情况下按邮政编码进行筛选。
建议查看 *Query
类的所有设置器。NAPI 的文档也提供了有关可能筛选器的信息。
资源对象
在 NDK 中,我们区分两种基于两个抽象类构建的模型类型。
\Nordkirche\Ndk\Domain\Model\AbstractModel
\Nordkirche\Ndk\Domain\Model\AbstractResourceObject
AbstractResourceObject
是 AbstractModels
的扩展,表示 NAPI 的资源对象。这些对象具有 ID、类型和其他资源的关联关系。它们通过存储库获取。
所有 AbstractModels
几乎都是资源的子对象,并组织资源对象的复杂数据。
属性
通常可以通过相应的 get*()
方法访问资源的属性。
但是,由于一些 get*()
方法是魔法方法,所以无法使用 method_exists()
检查属性是否可获取。为了允许动态检查和处理属性,可以使用 property_exists()
和通过 $object->property
直接访问属性。在此过程中,会考虑下一节中的 ResourcePlaceholder
和 ResolutionProxy
功能。
包含
NAPI 本身基于 JSON API 1.0 规范,因此它使用选项,即不直接返回与资源的关系,而是仅进行引用。
这导致相关资源对象不会自动包含在内,而是由 NDK 在需要时加载。以下以机构为例说明这种行为。
机构与其他资源对象有关联,例如它们的地址或类型。调用 getAddress()
方法将导致向 NAPI 发起另一个请求以获取机构的地址数据。
如果资源无法动态加载,则返回一个 ResourcePlaceholder
对象。该对象包含资源的生成标签以及可能的原因。
如果要以这种方式输出地址列表,则将为地址列表中的每个条目向 NAPI 发起另一个请求。
如果已知需要获取所有机构的地址,则可以将该关系包含在 NAPI 的响应中,从而避免不必要的请求。为此,将关系列表传递给查询对象。
<?php use Nordkirche\Ndk\Domain\Model\Institution\Institution; $query->setInclude([Institution::RELATION_ADDRESS, Institution::RELATION_INSTITUTION_TYPE]);
没有所有可能关系的列表,因为它们对资源对象是特定的。
所有包含关系的资源类都包含以 RELATION_
开头的常量,这些常量指示可能的关系,可以使用它们构建包含数组。
从存储库的名称总是可以推断出相应的资源类。
\Nordkirche\Ndk\Domain\Repository\PersonRepository -> \Nordkirche\Ndk\Domain\Model\Person\Person
包含可以嵌套,以包含关系的关联关系。
<?php use Nordkirche\Ndk\Domain\Model\Institution\Institution; $query->setInclude([ Institution::RELATION_ADDRESS, Institution::RELATION_PARENT_INSTITUTIONS => [ Institution::RELATION_ADDRESS ] ]);
在上面的示例中,我们包含了请求的所有机构的地址,包括上级机构及其相应的地址。
人们可能会倾向于总是包含所有关系,以确保在所有情况下都不会向NAPI发送不必要的查询。需要注意的是,包含数据会使查询变慢。因此,应有意选择需要哪些关系进行哪些查询。
通过查看 examples/3_includes.php
示例,可以理解带和不带 setIncludes()
的查询之间的区别。
动态加载与包含
如果希望资源永远不会动态加载,则可以取消此功能的激活。
<?php $configuration->setResolutionProxyDisabled(true);
此设置会导致未包含的关系返回 null
。访问未包含的关系将被记录并可以输出。更多关于日志记录的内容请参阅日志记录部分。
资源对象的自身关系
有时,可能需要在数据库中为数据库中的对象创建自己的关系,例如为北德意志教会的人创建关系。为此,可以将NDK的资源对象转换为URI,这些URI可以保存。
可以通过将资源对象转换为字符串或调用 __toString()
方法来获得这些URI。
<?php $uri = (string)$institution; // oder $uri = $institution->__toString();
生成的字符串格式为:napi://resource/type/1234
。这些URI可以方便地解析。
<?php $napi = $api->factory(\Nordkirche\Ndk\Service\NapiService::class); $result = $napi->resolveUrl($uri);
还可以直接使用NDK解析整个URI列表并处理缺失的对象。
<?php $uris = ['napi://resource/typeA/1234', 'napi://resource/typeB/4567', 'napi://resource/typeC/891011']; $napi = $api->factory(\Nordkirche\Ndk\Service\NapiService::class); foreach ($napi->resolveUrls($uris) as $result) { if ($result instanceof \Nordkirche\Ndk\Domain\Model\ResourcePlaceholder) { echo "Resource not found: " . $result->getLabel() . PHP_EOL; } else { echo "Found: " . $result->getName() . ' (' . $result->getId() . ')' . PHP_EOL; } }
在此数组中可能包含人员、机构、事件等。
examples/5_napi_urls.php
示例演示了转换和解析的实践操作。
图片
资源对象可以包含图片。例如,一个机构有一个 getLogo()
标志,或者一个活动有一个描述性图片 getPicture()
。图片由 \Nordkirche\Ndk\Domain\Model\File\Image
类的实例表示。
<?php $repository = $api->factory(\Nordkirche\Ndk\Domain\Repository\InstitutionRepository::class); $instituion = $repository->getById(1930); $imageUrl = $instituion->getLogo()->render(150); echo $imageUrl . PHP_EOL;
除了常见的图片和文件属性外,它还提供了 render($width, $height)
方法,以获得缩放版本的图片的URL。参数 $width
和 $height
都是可选的。如果两个参数都指定,并且其中一个(或两个)带有后缀 c
,则图片将被裁剪。
<?php $imageUrl = $event->getPicture()->render('100c', '100c');
通过 getDetails()
方法可以获取更多图片和文件属性。包括图片说明、版权信息等。
NDK的扩展配置
可以在第一部分创建的配置对象 \Nordkirche\Ndk\Configuration
中添加更多选项,以调整NDK的行为。
日志记录
可以使用PSR-3兼容的记录器来截取NDK到NAPI的查询。
<?php $logger = new \Monolog\Logger( 'stdout', [new \Monolog\Handler\StreamHandler('php://stdout')] ); $configuration->setLogger($logger);
请参阅 examples/5_logging.php
以了解使用Monolog的应用示例。
缓存
默认情况下,将HTTP查询到NAPI和内部数据临时存储在Doctrine ArrayCache中。
可以为应用中的特定方面设置PSR-6兼容的缓存,例如使用 doctrine/cache
中的不同驱动程序。
可以在 6_Caching.php
中查看和执行示例配置。
doctrine/cache
包本身提供了对多种后端的支持。
对于所有可配置的缓存,建议使用内存缓存作为后端。例如 APCu、Redis 或 Memcache。
HTTP缓存
<?php $configuration->setHttpCacheProvider(new \Doctrine\Common\Cache\FilesystemCache('./cache/http'));
配置HTTP缓存中间件的后端。NAPI检查缓存中的查询是否包含新数据,并在必要时从自己的HTTP缓存中获取现有数据。
NDK特定缓存
<?php $configuration->setReflectionCacheProvider(new \Doctrine\Common\Cache\FilesystemCache('./cache/reflection')); $configuration->setDependencyInjectionCacheProvider(new \Doctrine\Common\Cache\FilesystemCache('./cache/di'));
这些内部缓存提高了NDK的总体执行速度。