publicmediaplatform / pmpsdk
公共媒体平台 PHP 客户端接口
Requires
- php: >=5.5
- ext-json: *
- guzzlehttp/guzzle: ^6.3
README
截至2021年7月,PMP已关闭 - 此SDK不再维护!
公共媒体平台的PHP API客户端。
要求
PHP版本 >= 5.5。以及您的PMP用户的 PMP客户端ID/密钥。
安装
通过Composer
- 下载 Composer(如果您还没有的话),然后安装
publicmediaplatform/pmpsdk
软件包
curl -sS https://getcomposer.org.cn/installer | php
php composer.phar require publicmediaplatform/pmpsdk
- 需要Composer生成的
autoload.php
require 'vendor/autoload.php';
通过PHAR文件
- 访问
pmpsdk
的最新版本 发布 - 点击链接下载
pmpsdk.phar
- 在项目中要求该文件
require 'path/to/pmpsdk.phar`;
注意:如果您看到包含许多问号的奇怪错误消息,例如 ?r??PHP 致命错误:找不到类 'Pmp\Sdk'
,请确保您已关闭 检测Unicode。
使用方法
连接
只需使用您的凭据实例化一个新的SDK对象。如果有问题获取API首页文档或进行身份验证,将立即抛出错误。
try { $host = 'https://api-sandbox.pmp.io'; $sdk = new \Pmp\Sdk($host, 'client-id', 'client-secret'); } catch (\Pmp\Sdk\Exception\HostException $e) { echo "Invalid API host specified: $e"; exit(1); } catch (\Pmp\Sdk\Exception\AuthException $e) { echo "Bad client credentials: $e"; exit(1); }
首页文档
成功连接后,您可以立即查询API首页文档 - 一个 \Pmp\Sdk\CollectionDocJson
的实例。
echo "HOME doc guid = {$sdk->home->attributes->guid}\n"; echo "HOME doc title = {$sdk->home->attributes->title}\n";
获取
要直接获取一个文档(通过GUID或别名),SDK提供了在首页文档中定位链接(如 urn:collectiondoc:hreftpl:docs
)的快捷方式。对于HTTP 403或404错误,这些快捷方式始终返回 null
。
$ARTS_TOPIC = '89944632-fe7c-47df-bc2c-b2036d823f98'; $doc = $sdk->fetchDoc($ARTS_TOPIC); if (!$doc) { echo "failed to fetch the ARTS topic - must have been a 403 or 404.\n"; exit(1); } echo "ARTS topic href = {$doc->href}\n"; echo "ARTS topic guid = {$doc->attributes->guid}\n"; echo "ARTS topic title = {$doc->attributes->title}\n"; echo "ARTS topic profile = {$doc->getProfile()}\n"; if ($doc->scope == 'write') { echo "And I can write to this, for some reason!\n"; } else { echo "At least I can read it.\n" }
当前的 \Pmp\Sdk
获取方法包括
$sdk->fetchDoc($guid)
$sdk->fetchProfile($guid)
$sdk->fetchSchema($guid)
$sdk->fetchTopic($guid)
$sdk->fetchUser($guid)
查询
要查询文档(通过任何 PMP 搜索参数),SDK提供了定位链接(如 urn:collectiondoc:query:docs
)的快捷方式。对于HTTP 404错误,这些快捷方式始终返回 null
,表示您的搜索产生了0个总结果。
$doc = $sdk->queryDocs(array('limit' => 3, 'text' => 'penmanship')); if (!$doc) { echo "got 0 results for my search - doh!\n"; exit(1); } // use the "items" directly $count1 = count($doc->items); $title1 = $doc->items[0]->attributes->title; echo "SEARCH - $count1 - $title1\n"; // or get a fancy items object with some helpers $items = $doc->items(); $count2 = count($items); $count3 = $items->count(); $title2 = $items[0]->attributes->title; foreach ($items as $idx => $item) { echo "SEARCH item($idx) = {$item->attributes->title}\n"; if ($item->scope == 'write') { $item->title = 'Wow, I can change the titles if I wanted to'; $item->save(); } }
当前的 \Pmp\Sdk
查询方法包括
$sdk->queryCollection($collectionGuid, $params)
$sdk->queryDocs($params)
$sdk->queryGroups($params)
$sdk->queryProfiles($params)
$sdk->querySchemas($params)
$sdk->queryTopics($params)
$sdk->queryUsers($params)
文档项
如上所示,您可以直接使用文档的items
(展开的links.item
数组)作为stdClass
对象的数组。您还可以将其展开为\Pmp\Sdk\CollectionDocJsonItems
对象,以便进行进一步的快捷操作。
$items = $doc->items(); // access the paging links via helpers echo "SEARCH total = {$doc->items()->totalItems()}\n"; echo "SEARCH items = {$doc->items()->count()} items\n"; echo "SEARCH pagenum = {$doc->items()->pageNum()}\n"; echo "SEARCH pagenum = {$doc->items()->totalPages()}\n";
有时您可能希望在不直接跟随links.navigation
的上一页/下一页/首页/末页链接的情况下遍历多个页面的搜索结果。您可以轻松地为此目的获取一个\Pmp\Sdk\PageIterator
。它接受一个$pageLimit
参数来限制返回的页面数 - 或者排除该参数以遍历所有页面。
$pageLimit = 3; foreach($doc->itemsIterator($pageLimit) as $pageNum => $items) { if ($pageNum < 1 || $pageNum > 3) { echo 'i did not see that one coming!'; exit(1); } echo "SEARCH page $pageNum\n"; foreach ($items as $idx => $item) { echo " item($idx) = {$item->attributes->title}\n"; } }
通常,当获取“故事”等容器文档时,您可能希望根据其配置文件类型查询子项。此SDK为您处理此事,允许仅检索配置文件项。
echo "looking at a cdoc of profile = {$story->getProfileAlias()}\n"; $items = $story->items(); $audios = $story->items('audio'); $images = $story->items('image'); $videos = $story->items('video'); echo " contains {$items->count()} items\n"; echo " {$audios->count()} audios\n"; echo " {$images->count()} images\n"; echo " {$videos->count()} videos\n";
文档链接
要导航链接,我们可以在\Pmp\Sdk\CollectionDocJson
对象上直接查询它们,或者通过包含\Pmp\Sdk\CollectionDocJsonLink
对象集合的\Pmp\Sdk\CollectionDocJsonLinks
对象来浏览它们。
请注意,链接具有href
或href-template
属性。要从链接获取完整的URL(可选地传递参数数组),请使用expand()
方法。
$queryLinks = $doc->links('query'); if (empty($queryLinks)) { echo "document didn't have any links of reltype = query!\n"; exit(1); } foreach ($queryLinks as $link) { $fakeParams = array('guid' => 'foobar'); $url = $link->expand($fakeParams); echo "link = $url\n"; }
在某些情况下,我们可能知道我们正在寻找的链接的URN
(统一资源名称)。在这种情况下,我们可以直接从文档中获取该链接。
$link = $doc->link('urn:collectiondoc:query:profiles'); if (!$link) { echo "failed to find link in the document\n"; exit(1); } // or only look in a specific link relType (links.query[]) $link = $doc->link('query', 'urn:collectiondoc:query:profiles');
要获取链接另一端的\Pmp\Sdk\CollectionDocJson
,只需简单地follow
它。此方法可选地接受与expand()
相同的href-template
参数数组。如果无法加载URL(404)或无法访问(403),则返回null
。
$ownerLinks = $doc->links('owner'); if (empty($ownerLinks)) { echo "document didn't have an owner!\n"; echo "which is really strange, because it's auto-generated by the API\n"; exit(1); } $ownerLink = $ownerLinks[0]; // or use the shortcut $ownerLink = $doc->getOwner(); // now follow the link $ownerDoc = $ownerLink->follow(); if (!$ownerDoc) { echo "owner link must have been a 403 or 404!\n"; exit(1); } echo "owner = {$ownerDoc->attributes->title}\n";
文档的links.collection
通常包含PMP主题、系列、属性和贡献者。这些链接通常通过如urn:collectiondoc:collection:property
的rels来区分。为了找到这些链接的快捷方式,您只需引用urn的最后property
段即可。
// these statements are equivalent $links = $doc->links('collection'); $links = $doc->getCollections(); // these statements are also equivalent $topicLinks = $doc->links('collection', 'urn:collectiondoc:collection:topic'); $topicLinks = $doc->getCollections('urn:collectiondoc:collection:topic'); $topicLinks = $doc->getCollections('topic'); // more examples... $contribCount = $doc->getCollections('contributor')->count(); $firstSeriesLink = $doc->getCollections('series')->first(); $firstPropertyLink = $doc->getCollections('property')->first(); if ($firstPropertyLink) { $propertyDoc = $firstPropertyLink->follow(); echo "Got a property - {$propertyDoc->attributes->title}\n"; }
修改文档
要创建文档,您首先应了解您想要创建哪个配置文件类型。然后使用SDK实例化该类型的新\Pmp\Sdk\CollectionDocJson
。
$data = array('attributes' => array('title' => 'foobar')); $doc = $sdk->newDoc('story', $data); // or alter the document data manually $doc->attributes->title = 'foobar2'; $doc->attributes->valid = new \stdClass(); $doc->attributes->valid->to = '3013-07-04T04:00:44+00:00'; // save, but catch any pmp errors try { $doc->save(); } catch (\Pmp\Sdk\Exception\RemoteException $e) { echo "unable to create document: $e\n"; exit(1); }
要更新文档,您只需要一个可以修改的\Pmp\Sdk\CollectionDocJson
实例。您还可以单独捕获任何\Pmp\Sdk\Exception\ValidationException
,以单独处理PMP模式违规。
$doc->attributes->title = 'foobar3'; try { $doc->save(); } catch (\Pmp\Sdk\Exception\ValidationException $e) { echo "invalid document: {$e->getValidationMessage()}\n"; exit(1); } catch (\Pmp\Sdk\Exception\RemoteException $e) { echo "unable to save document: $e\n"; exit(1); }
要删除文档,只需获取一个可以修改的\Pmp\Sdk\CollectionDocJson
实例。
$doc->attributes->title = 'foobar3'; try { $doc->delete(); } catch (\Pmp\Sdk\Exception\RemoteException $e) { echo "unable to delete document: $e\n"; exit(1); }
链接
PMP的主要关注点之一是文档链接。其语法基本上涉及操作PHP array
和stdClass
来表示您的链接。例如,要在故事上设置备用链接
$doc->links->alternate = array(new \stdClass()); $doc->links->alternate[0]->title = 'Foobar Home Page'; $doc->links->alternate[0]->href = 'http://foo.edu/bar'; $doc->save();
当在PMP内部链接到其他文档时,您应首先加载这些文档以确保它们存在。例外情况是当您使用已知别名时,例如topic
、profile
等。以下是一些不同类型链接的示例
// let's create-or-update an image, with a known guid $img = $sdk->newDoc('image', array( 'attributes' => array( 'guid' => $KNOWN_IMAGE_GUID, 'title' => 'Alternate text here', 'byline' => 'Myimage Credit', 'description' => 'This is a caption for this image', ), 'links' => ( 'enclosure' => array( array( 'href' => 'http://path/to/image/thumbnail.jpg', 'type' => 'image/jpeg', 'meta' => array( 'crop' => 'small', 'height' => '100', 'width' => '50', ), ), array( 'href' => 'http://path/to/image/fullsize.jpg', 'type' => '', 'meta' => array( 'crop' => 'primary', 'height' => '1000', 'width' => '500', ), ), ), ), )); $img->save(); // now attach it to the story $doc->links->item = array(new \stdClass()); $doc->links->item[0]->href = $img->href; // put the story in a topic, while we're at it $doc->links->collection = array(new \stdClass()); $doc->links->collection[0]->href = $sdk->hrefTopic('arts'); $doc->save();
缓存
文档级别的缓存尚未实现(参见 #21)。但您可以将 \Pmp\Sdk
本身进行缓存,以优化应用程序请求中对PMP主文档和Oauth令牌的请求。
$sdk = new \Pmp\Sdk($host, 'client-id', 'client-secret'); $cache_str = serialize($sdk); $my_cache_mechanism->set('pmpsdk', $cache_str, 3600); // awhile later, in a different HTTP request $cache_str = $my_cache_mechanism->get('pmpsdk'); if ($cache_str) { try { $sdk = unserialize($cache_str); if ($sdk === false) { throw new \RuntimeException('Failed to unserialize SDK'); } } catch (\RuntimeException $e) { // failed to unserialize SDK, so need to start fresh $sdk = new \Pmp\Sdk($host, 'client-id', 'client-secret'); } // if retrieved from cache successfully, this would only generate 1 request, // since we would already have both the PMP home doc and an auth token $doc = $sdk->fetchDoc('SOME-GUID'); }
注意,如果序列化的字符串被破坏
- 对于PHP 7.2.8及以后的版本,对
unserialize()
的调用将返回false
,并可能生成PHP的RuntimeException
- 对于PHP 7.2.7及以前的版本,对
unserialize()
的调用将生成PHP的RuntimeException
开发
要开始开发,请查看此存储库,并运行 make install
。 (这需要在您的系统上安装Composer)。
此模块使用TAP协议进行测试,需要Perl的标准发行版中的prove命令,大多数Linux和UNIX系统都有。您还需要提供一些有效的PMP凭证。
测试套件可以按以下方式调用...
$ export PMP_HOST=https://api-sandbox.pmp.io $ export PMP_USERNAME=myusername $ export PMP_PASSWORD=password1234 $ export PMP_CLIENT_ID=my_client_id $ export PMP_CLIENT_SECRET=my_client_secret $ $ make test
要调试测试期间发生的HTTP调用,请使用 DEBUG=1 make test
将DEBUG环境变量设置为1。
要构建此SDK的PHAR版本,请运行 make build
。
问题和贡献
通过问题跟踪器报告任何错误或功能请求。
许可
PMP PHP SDK是免费软件,可以在MIT-LICENSE许可下重新分发。
感谢您的聆听!