利用 oEmbed 和 PHP 访问第三方内容

将来自流行应用程序和网站的富内容和数据添加到自己的 web 页面

oEmbed 规范提供了一种方法,可以在 web 页面中显示来自第三方内容共享站点的内容的嵌入式表示。本文介绍 oEmbed API,并在一个 PHP 应用程序上下文中进行演示,解释如何使用它来嵌入来自诸如 Flickr、YouTube、Slideshare、Wikipedia 等流行网站的内容。

Vikram Vaswani, 创始人, Melonfire

Vikram Vaswani 的照片Vikram Vaswani 是 Melonfire 的创始人和 CEO,该公司是一家专门研究开源工具和技术的咨询服务公司。他还著有 PHP Programming SolutionsHow to do Everything with PHP and MySQL 等著作。



2011 年 4 月 25 日

简介

Web 2.0 的故事就是用户生成内容的故事。诸如 Flickr、Facebook、MySpace 和 YouTube 之类的网站允许用户使用简单的在线工具,将自己原创的照片或视频素材上传到云,与更广泛的社团共享。基于云的内容创建和共享工具的普及,加上允许开发人员以编程方式访问用户生成内容的 web 服务,已使得组合来自不同来源的内容以支持新的、内容驱动的应用程序(mashups)成为可能。

常用缩写词

  • API:应用程序编程接口
  • HTML:超文本标记语言
  • JSON:JavaScript 对象符号
  • OOP:面向对象编程
  • SQL:结构化查询语言
  • URL:统一资源定位符
  • UTF-8:8 位 UCS 转换格式
  • XML:可扩展标记语言
  • XSS:跨站脚本攻击

但是有一个小问题。如果您在 Flickr 上有照片,YouTube 上有视频,Hulu 上有电视节目,那么如何将它们全都组织到 Blogger 上的博客帖子中呢?当然,您可以通过超链接适当的内容来达此目的,但是在适当的地方将它们嵌入到帖子中不是更好吗?

进入 oEmbed。顾名思义,oEmbed 为这个问题提供一个解决方案,允许用户将到外部网站(如 Flickr 和 YouTube)上富内容(比如照片和视频)的 URL 转换成这些内容的嵌入式表示。本文中,我向您介绍 oEmbed,并展示如何使用它和 PHP 来在 web 页面中嵌入第三方内容。


理解 oEmbed

首先是 oEmbed 的简单介绍。根据其官方网站的说法 (http://www.oembed.com),oEmbed 是:

“……一种允许第三方站点上 URL 的嵌入式表示的格式……当用户发布一个到某资源的链接时,[它]允许网站显示此嵌入式内容(比如照片或视频),无需直接解析该资源。”

参与 oEmbed 事务的有两方:提供者和消费者。消费者通过对提供者的 API 端点发出请求而请求特定的内容条目。提供者通过返回所请求内容条目的 XML 或 JSON 编码的表示而服务这些请求。

此方法是如何实际工作的呢?好的,假设您写了一个博客帖子,想要显示您上传的一个来自 YouTube 的视频。有两种方式做这件事:

  • 您可以超链接它;用户点击链接时,他们被定向到 YouTube 以查看该视频。
  • 您可以使用 YouTube 的嵌入式媒体播放器来将视频直接嵌入到博客帖子中。

第一种方法很简单,但是它导致用户从您的站点转移到 YouTube,很混乱。第二种方法将访问者保持在您的站点上,但是要求进行一些研究,了解 YouTube 的嵌入式播放器是如何工作的。

oEmbed 提供另外一种更简单的解决方案。由于 YouTube 是一个 oEmbed 提供者,所以您可以向它的 oEmbed API 端点发送一个请求,请求刚才提到的视频。该请求的响应是一个包含嵌入式视频播放器的 HTML 代码的 XML 或 JSON 文档,此代码可以直接用在您的博客帖子中以显示视频,无需任何进一步的手工干预。

清单 1 展示了一个 YouTube 视频的 oEmbed 请求和响应的样子:

清单 1. 一个 oEmbed 请求
GET http://www.youtube.com/oembed?url=http://www.youtube.com/watch?v=hI-BDR2UcmU
&format=xml

<?xml version="1.0" encoding="utf-8"?>
<oembed>
  <provider_url>http://www.youtube.com/</provider_url>
  <title>NORAD Tracks Santa - US Region</title>
  <html><object width="425" height="344"><param name="movie"
  value="http://www.youtube.com/v/hI-BDR2UcmU?fs=1"></param><param 
  name="allowFullScreen" value="true"></param><param 
  name="allowscriptaccess" value="always"></param><embed 
  src="http://www.youtube.com/v/hI-BDR2UcmU?fs=1" 
  type="application/x-shockwave-flash" width="425" 
  height="344" allowscriptaccess="always" 
  allowfullscreen="true"></embed></object></html>
  <author_name>NORADTracksSanta</author_name>
  <height>344</height>
  <thumbnail_width>480</thumbnail_width>
  <width>425</width>
  <version>1.0</version>
  <author_url>http://www.youtube.com/user/NORADTracksSanta</author_url>
  <provider_name>YouTube</provider_name>
  <thumbnail_url>http://i1.ytimg.com/vi/hI-BDR2UcmU/hqdefault.jpg</thumbnail_url>
  <type>video</type>
  <thumbnail_height>360</thumbnail_height>
</oembed>

注意,请求被发送到 http://www.youtube.com/oembed,这是 oEmbed 请求的 YouTube API 端点。在 "url" 请求参数中给该 API 传递了所请求视频的 URL。此请求的响应包含一些视频元数据,比如视频的作者和标题以及适当的 HTML 嵌入代码。

oEmbed 提供者可以返回 XML 或 JSON 格式的响应。所有响应都以 UTF-8 编码。可以用一个附加的 "format" 参数在请求中指定响应格式。清单 2 展示了一个例子。

清单 2. 使用 YouTube oEmbed API
GET http://www.youtube.com/oembed?url=http://www.youtube.com/watch?v=hI-BDR2UcmU
&format=json

{
  "provider_url": "http:\/\/www.youtube.com\/", 
  "title": "NORAD Tracks Santa - US Region", 
  "html": "<object width=\"425\" height=\"344\"><param name=\"movie\"
  value=\"http:\/\/www.youtube.com\/v\/hI-BDR2UcmU?fs=1\"><\/param>
  <param name=\"allowFullScreen\" value=\"true\"><\/param>
  <param name=\"allowscriptaccess\" value=\"always\"><\/param>
  <embed src=\"http:\/\/www.youtube.com\/v\/hI-BDR2UcmU?fs=1\" 
  type=\"application\/x-shockwave-flash\" width=\"425\" height=\"344\" 
  allowscriptaccess=\"always\" allowfullscreen=\"true\"><\/embed><\/object>", 
  "author_name": "NORADTracksSanta", 
  "height": 344, 
  "thumbnail_width": 480, 
  "width": 425, 
  "version": "1.0", 
  "author_url": "http:\/\/www.youtube.com\/user\/NORADTracksSanta", 
  "provider_name": "YouTube", 
  "thumbnail_url": "http:\/\/i1.ytimg.com\/vi\/hI-BDR2UcmU\/hqdefault.jpg", 
  "type": "video", 
  "thumbnail_height": 360
}

利用 oEmbed 嵌入内容

既然明白了 oEmbed 是如何工作的,现在我们就来看一些代码。整篇文章中我都假设您熟悉 HTML、SQL 和 XML,并且您有一个可以工作的 Apache 或 PHP 开发环境。我还假设您了解在 PHP 中处理类和对象的基本知识,因为本文中使用的 PHP 组件都是以遵循 OOP 原则的方式编写的。

要在 PHP 应用程序中使用 oEmbed,有两个库供您选择:PEAR Services_oEmbed 或 php-oembed。本文中的大多数例子都使用 PEAR Services_oEmbed(尽管我也包含一些使用 php-oembed 的例子供参考),所以就安装这个库吧。您可以从 PEAR 网站(参见 参考资料 中的链接)手动下载并安装它,或者像这里展示的一样使用 PEAR 安装程序自动安装。

shell> pear install Services_oEmbed-0.2.0

安装它之后,尝试一个简单的例子,如 清单 3 所示:

清单 3. 使用 YouTube oEmbed API
<?php
// include class
include 'Services/oEmbed.php';

// define content URL
$url = 'http://www.youtube.com/watch?v=hI-BDR2UcmU';

// define API endpoint
$options = array(
  Services_oEmbed::OPTION_API => 'http://www.youtube.com/oembed'
);

// get oEmbed representation
$oEmbed = new Services_oEmbed($url, $options);
$video = $oEmbed->getObject();
?>
<html>
  <head></head>
  <body>
    <div>
    <?php echo $video; ?>
    </div>    
  </body>
</html>

清单 3 首先是加载 Services_oEmbed 类,然后定义将被嵌入内容(在本例中是一个 YouTube 视频)的 URL。接下来,初始化 Services_oEmbed 类的一个实例,类构造函数被传递两个参数:YouTube URL 和一组选项。

options 数组的关键元素是使用的 oEmbed API 端点;在本例中是 YouTube 的 oEmbed 端点,即 http://www.youtube.com/oembed。最后,对服务对象的 getObject() 方法的调用负责执行 oEmbed 请求并返回指定视频的对象表示。

该对象表示包含被请求视频的详细信息,比如它的 URL、作者、提供者和标题。它还可以包含缩略图和视频对象的大小信息。图 1 演示了对象的样子。

图 1. PEAR Services_oEmbed 返回的 oEmbed 对象
PEAR Services_oEmbed 返回的 oEmbed 对象的屏幕截图

图 2 演示了 清单 3 的输出。本例中的视频是美国的 NORAD 跟踪圣诞老人。

图 2. 一个嵌入式 YouTube 视频
一个嵌入式 YouTube 视频的屏幕截图

处理内容元数据

您可以为嵌入的媒体添加一些元数据,如 清单 4 中所示。

清单 4. 使用 oEmbed 元数据
<?ph4
// include class
include 'Services/oEmbed.php';

// define content URL
$url = 'http://www.youtube.com/watch?v=hI-BDR2UcmU';

// define API endpoint
$options = array(
  Services_oEmbed::OPTION_API => 'http://www.youtube.com/oembed'
);

// get oEmbed representation
$oEmbed = new Services_oEmbed($url, $options);
$video = $oEmbed->getObject();
?>
<html>
  <head></head>
  <body>
    <div>
    <?php echo $video; ?>
    </div>

    <div>
    Type: <?php echo $video->type;?> <br/>
    Title: <?php echo $video->title;?> <br/>
    Author: <a href="<?php echo $video->author_url;?>">
    <?php echo $video->author_name;?></a> <br/>
    Provider: <a href="<?php echo $video->provider_url;?>">
    <?php echo $video->provider_name;?></a> <br/>
    </div>
  </body>
</html>

图 3 显示了 清单 4 的输出,带有视频和附加的详细信息,比如类型 (video)、标题 (NORAD Tracks Santa - US Region)、作者 (NORADTracksSanta) 和提供者 (YouTube)。

图 3. 一个带有附加元数据的嵌入式 YouTube 视频
一个带有附加元数据的嵌入式 YouTube 视频的屏幕截图

请注意,oEmbed 规范定义了四种类型的媒体:photo(照片)、video(视频)、link(链接) 和 rich(富媒体)。为每种类型返回的元数据会各不相同;例如,视频具有 html 参数,其中包含视频播放器的嵌入代码,而照片具有 url 参数,指定了到照片的 URL。查阅此规范(参见 参考资料 中的链接),获得请求和响应参数的完整列表。

还要注意,您可以在对 getObject() 的调用中包含一个附加的参数:即一个包含 maxheightmaxwidth 参数的数组,这些参数指定返回的表示的高度和宽度。


使用来自多个来源的内容

oEmbed 的一个优点是受到很多不同的流行 web 服务的支持:Flickr、Facebook、YouTube、Vimeo、Viddler、Revision3,这只是列举了那么几个。来看一下 清单 5,它演示了嵌入一个来自 Revision3 的视频的过程。

清单 5. 使用 Revision3 oEmbed API
<?php
// include class
include 'Services/oEmbed.php';

// define content URL
$url = 'http://revision3.com/foundation/jackdorsey';

// define API endpoint
$options = array(
  Services_oEmbed::OPTION_API => 'http://revision3.com/api/oembed/'
);

// get oEmbed representation
$oEmbed = new Services_oEmbed($url, $options);
$object = $oEmbed->getObject();
?>
<html>
  <head></head>
  <body>
    <div>
    <?php echo $object; ?>
    </div>

    <div>
    Type: <?php echo $object->type;?> <br/>
    Title: <?php echo $object->title;?> <br/>
    Author: <a href="<?php echo $object->author_url;?>">
    <?php echo $object->author_name;?></a> <br/>
    Provider: <a href="<?php echo $object->provider_url;?>">
    <?php echo $object->provider_name;?></a> <br/>
    </div>
  </body>
</html>

图 4 显示了输出,带有视频和附加的详细信息,比如类型 (video)、标题 (Jack Dorsey)、作者 (Foundation) 和提供者 (Revision3)。

图 4. 一个嵌入式 Revision3 视频
一个嵌入式 Revision3 视频的屏幕截图

清单 6 中有另一个例子,它嵌入一个来自 deviantART 网站的分形图。

清单 6. 使用 deviantART oEmbed API
<?php
// include class
include 'Services/oEmbed.php';

// define content URL
$url = 'http://undead-academy.deviantart.com/art/Spool-192326055';

// define API endpoint
$options = array(
  Services_oEmbed::OPTION_API => 'http://backend.deviantart.com/oembed'
);

// get oEmbed representation
$oEmbed = new Services_oEmbed($url, $options);
$object = $oEmbed->getObject();
?>
<html>
  <head></head>
  <body>
    <div>
    <?php echo $object; ?>
    </div>

    <div>
    Type: <?php echo $object->type;?> <br/>
    Title: <?php echo $object->title;?> <br/>
    Author: <a href="<?php echo $object->author_url;?>">
    <?php echo $object->author_name;?></a> <br/>
    Provider: <a href="<?php echo $object->provider_url;?>">
    <?php echo $object->provider_name;?></a> <br/>
    </div>
  </body>
</html>

图 5 显示了输出,带有照片和附加的详细信息,比如类型 (photo)、标题 (Spool)、作者 (Undead_Academy) 和提供者 (DeviantART)。

图 5. 一幅嵌入式 deviantART 图像
一幅嵌入式 deviantART 图像的屏幕截图

使用 oohEmbed 服务

尽管很多 web 应用程序已经提供了自己的 oEmbed API 端点,但是还是有一些没有提供。不过,仍然可以通过 oohEmbed 服务(它标榜自己是“各种网站的 HTML 嵌入代码的提供者,兼容 oEmbed”)访问这些应用程序。您可通过 oohEmbed 访问的附加应用程序和服务包括 amazon.com 产品图像、Twitter 状态更新、Google Video、Metacafe、Slideshare、TwitPic、Wikipedia、Wordpress,等等。但是请注意,oohEmbed 只支持 JSON 输出,并且通常忽略 maxwidthmaxheight 参数。

清单 7 中有一个例子,使用 oohEmbed 将 Wikipedia 内容嵌入到 web 页面中。

清单 7. 使用 oohEmbed 和 Wikipedia
<?php
// include class
include 'Services/oEmbed.php';

// define content URL
$url = 'http://en.wikipedia.org/wiki/Drupal';

// define API endpoint
$options = array(
  Services_oEmbed::OPTION_API => 'http://oohembed.com/oohembed/'
);

// get oEmbed representation
$oEmbed = new Services_oEmbed($url, $options);
$object = $oEmbed->getObject();
?>
<html>
  <head></head>
  <body>
    <div>
    <?php echo $object->html; ?>
    </div>

    <div>
    Type: <?php echo $object->type;?> <br/>
    Title: <?php echo $object->title;?> <br/>
    Author: <a href="<?php echo $object->author_url;?>">
    <?php echo $object->author_name;?></a> <br/>
    Provider: <a href="<?php echo $object->provider_url;?>">
    <?php echo $object->provider_name;?></a> <br/>
    </div>
  </body>
</html>

注意,在 清单 7 中,指定的 API 端点属于 oohEmbed,不属于 Wikipedia。oohEmbed 工作方式类似于一个代理,接收 oEmbed 请求并寻找对应的链接,向调用者返回一个 oEmbed 兼容的响应,其中包含所请求的数据。

图 6 演示了 清单 7 的输出,带有视频和附加的详细信息,比如类型 (link)、标题 (Drupal)、作者(这一项为空,没有指明特定的作者)和提供者 (Wikipedia):

图 6. 一个嵌入式 Wikipedia 页面
一个嵌入式 Wikipedia 页面的屏幕截图

清单 8 中有一个例子,使用 oohEmbed 在 web 页面中嵌入 Slideshare 表示(一种富媒体类型)。

清单 8. 使用 oohEmbed 和 Slideshare
<?php
// include class
include 'Services/oEmbed.php';

// define content URL
$url = 
'http://www.slideshare.net/weierophinney/best-practices-of-php-development-presentation';

// define API endpoint
$options = array(
  Services_oEmbed::OPTION_API => 'http://oohembed.com/oohembed/'
);

// get oEmbed representation
$oEmbed = new Services_oEmbed($url, $options);
$object = $oEmbed->getObject();
?>
<html>
  <head></head>
  <body>
    <div>
    <?php echo $object; ?>
    </div>

    <div>
    Type: <?php echo $object->type;?> <br/>
    Title: <?php echo $object->title;?> <br/>
    Author: <a href="<?php echo $object->author_url;?>">
    <?php echo $object->author_name;?></a> <br/>
    Provider: <a href="<?php echo $object->provider_url;?>">
    <?php echo $object->provider_name;?></a> <br/>
    </div>
  </body>
</html>

图 7 演示了 清单 8 的输出,带有一个演示文稿和附加的详细信息,比如类型 (rich)、标题 (Best Practices of PHP Development)、作者(weierophinney,一个可打开的链接)和提供者(SlideShare,一个可打开的链接)。

图 7. 一个嵌入的 Slideshare 演示文稿
一个嵌入的 Slideshare 演示文稿的屏幕截图

清单 9 使用 oohEmbed 来检索和嵌入一个来自产品 URL 的 amazon.com 产品图像。

清单 9. 使用 oohEmbed 和 amazon.com
<?php
// include class
include 'Services/oEmbed.php';

// define content URL
$url = 'http://www.amazon.com/Framework-Beginners-Guide-Vikram-Vaswani/dp/007163939X';

// define API endpoint
$options = array(
  Services_oEmbed::OPTION_API => 'http://oohembed.com/oohembed/'
);

// get oEmbed representation
$oEmbed = new Services_oEmbed($url, $options);
$object = $oEmbed->getObject();
?>
<html>
  <head></head>
  <body>

    <div>
    <?php echo $object; ?>
    </div>

    <div>
    Type: <?php echo $object->type;?> <br/>
    Title: <?php echo $object->title;?> <br/>
    Author: <a href="<?php echo $object->author_url;?>">
    <?php echo $object->author_name;?></a> <br/>
    Provider: <a href="<?php echo $object->provider_url;?>">
    <?php echo $object->provider_name;?></a> <br/>
    </div>
  </body>
</html>

图 8 演示了 清单 9 的输出,带有一个书封面的照片和附加的详细信息,比如类型 (photo)、标题 (Zend Framework, A Beginner's Guide)、作者(Vikram Vaswani,一个可打开的链接)和提供者(Amazon Product Image,一个可打开的链接)。

图 8. 一个嵌入的 Amazon 产品图像
一个嵌入的 Amazon 产品图像的屏幕截图

使用替代的 PHP 库

PEAR Services_oEmbed 库的一个替代品是 php-oembed 库,后者也可以用来在 web 页面中嵌入内容。安装该库很简单;下载它(参见 参考资料 中的链接),并将它复制到 PHP 包含路径中的某个位置。但是,配置比 Services_oEmbed 要稍微复杂一些。

php-oembed 库在其安装目录中一个名为 providers.xml 的 XML 文件中维护有它自己的 oEmbed 提供者和 API 端点的列表。因此,在可以开始使用某个特定的 oEmbed 提供者之前,您必须首先将它添加到这个文件中。例如,如果您希望使用 deviantART oEmbed API,那么必须首先编辑 providers.xml 文件并向其中添加一个项,如 清单 10 所示。

清单 10. 编辑 providers.xml 文件并向其中添加一个项
<?xml version="1.0"?>
<providers>
  <provider>
    <url>http://*.flickr.com/*</url>
    <endpoint>http://www.flickr.com/services/oembed/</endpoint>
  </provider>
  <provider>
    <url>http://*.pownce.com/*</url>
    <endpoint>http://api.pownce.com/2.1/oembed.{format}</endpoint>
  </provider>
  <provider>
    <url>http://*.deviantart.com/*</url>
    <endpoint>http://backend.deviantart.com/oembed</endpoint>
  </provider>
  <provider>
    <url>http://*.youtube.*/*</url>
    <endpoint>http://www.youtube.com/oembed</endpoint>
  </provider>
</providers>

添加提供者之后,您就可以在 PHP 脚本中使用 php-oembed 了,如 清单 11 所示。

清单 11. 使用 oohEmbed 和 deviantART 及 php-oembed 库
<?php
// define provider configuration
define('PROVIDER_XML', 'providers.xml');

// include classes
include 'ProviderManager.class.php';
include 'EmbedProvider.class.php';
include 'OEmbedProvider.class.php';
include 'LazyTemplateEngine.class.php';
include 'OEmbed.class.php';
include 'PhotoEmbed.class.php';

// create provider manager
$manager = ProviderManager::getInstance();

// define content URL
$url = 'http://undead-academy.deviantart.com/art/Spool-192326055';

// get oEmbed representation
$object = $manager->provide($url, 'object');
?>
<html>
  <head></head>
  <body>

    <div>
    <img src="<?php echo $object->url; ?>" />
    </div>

    <div>
    Type: <?php echo $object->type;?> <br/>
    Title: <?php echo $object->title;?> <br/>
    Author: <a href="<?php echo $object->author_url;?>">
    <?php echo $object->author_name;?></a> <br/>
    Provider: <a href="<?php echo $object->provider_url;?>">
    <?php echo $object->provider_name;?></a> <br/>
    </div>
  </body>
</html>

清单 11 首先是定义 providers.xml 文件的位置并包含 php-oembed 需要的所有相关的类。它然后生成一个 ProviderManager 服务对象,并使用该对象的 provide() 方法来检索内容 URL 的 oEmbed 表示。该表示可以各种格式返回:XML、JSON、PHP 对象、PHP 数组或序列化字符串。

图 9 演示了返回的对象的样子。(查看 图 9 的文本版本。)

图 9. php-oembed 返回的 oEmbed 对象
php-oembed 返回的 oEmbed 对象的屏幕截图

现在很容易使用该对象的属性和在 web 页面中包含嵌入的表示,带有照片和附加的详细信息,比如类型 (photo)、标题 (Spool)、作者 (Undead_Academy) 和提供者 (DeviantART),如 图 10 所示。

图 10. 一个嵌入的 deviantART 图像
一个嵌入的 deviantART 图像的屏幕截图

示例应用程序:内联内容嵌入

既然您了解了使用 PHP 与 oEmbed 的基本知识,现在我们就来看它们在示例应用程序的上下文中是如何工作的。由于 oEmbed 的全部作用就是在 web 页面中嵌入内容,所以示例应用程序向用户提供一个表单来输入内容(比如说博客帖子)并且使用 oEmbed 自动地将该内容中的超链接转换成嵌入的表示。

清单 12 中是完整的代码。

清单 12. 内联内容嵌入的示例应用程序
<html>
  <head></head>
  <body>
    <?php if (isset($_POST['submit'])): ?>
    <?php
      // include class
      include 'Services/oEmbed.php';

      // define API endpoint
      $options = array(
        Services_oEmbed::OPTION_API => 'http://oohembed.com/oohembed/'
      );

      // get post body
      // extract all URLs into array
      $oBody = $_POST['body'];
      $title = $_POST['title'];
      preg_match_all('!https?://[\S]+!', $oBody, $matches);
      $urls = $matches[0];
      $embeds = array();      

      // for each URL
      // get embed code from oohembed if available
      // else convert to simple hyperlink
      foreach ($urls as $url) {
        // get oEmbed representation
        $oEmbed = new Services_oEmbed($url, $options);
        try {
          $object = $oEmbed->getObject(array('maxheight' => '100', 'maxwidth' => '100'));
          $embeds[] = (string)$object;
        } catch (Exception $e) {
          $embeds[] = "<a href=\"" . $url . "\">" . $url . "</a>";
        }
      }

      // replace URLs in body with code
      // print revised output
      $nBody = str_replace($urls, $embeds, $oBody);
    ?>

      <h1>Preview New Post</h1>
      <h2><?php echo $title; ?></h2>
      <p>
        <?php echo nl2br($nBody); ?>
      </p>

    <?php else: ?>

    <h1>Add New Post</h1>
    <form method="post" action="<?php echo htmlentities($_SERVER['PHP_SELF']); ?>">
    <p>
      Title: <br/>
      <input type="text" name="title" size="40" />
    </p>
    <p>
      Body: <br/>
      <textarea name="body" rows="10" cols="50"></textarea>
    </p>
    <input type="submit" name="submit" />    
    </form>

    <?php endif; ?>

  </body>
</html>

清单 12 分成两个部分,由一个 if-else() 条件测试分隔。该测试检查表单提交;如果没有找到,它就显示一个简单的 web 表单,要求用户输入页面标题和主体内容。用户可以在这些字段中都输入文本,需要时可以包含超链接。图 11 演示了 清单 12 生成的 web 表单,带有一些示例输出。(查看 图 11 的文本版本。)

图 11. 一个支持内联内容嵌入的 web 表单
一个支持内联内容嵌入的 web 表单的屏幕截图

在表单提交之后,脚本初始化一个新的 Services_oEmbed 对象,给它传递 oohEmbed API 端点。它然后解析用户提交的内容,通过一个简单的正则表达式抽取出主体中找到的所有 URL。(注意:这个正则表达式不应该使用在生产环境中,因为它对于 XSS 攻击不安全。)这种方式识别的 URL 被存储在一个名为 $urls 的 PHP 数组中。

接下来,一个 foreach() 循环和 try-catch{} 块被用来迭代通过 URL 数组,将每个 URL 传递给 Services_oEmbed 对象的 getObject() 方法。这一步导致向 oohEmbed API 请求对应的远程内容。如果内容在受支持的服务上,那么 getObject() 方法返回对应的 HTML 嵌入代码,此代码保存到一个名为 $embeds 的单独数组中。如果内容不受支持,那么代码抛出一个异常,此异常由 try-catch{} 块捕捉到。此异常暗示着,URL 的嵌入式表示不可用;因此,URL 简单地转换为 HTML 锚标记并保存到 $embeds 数组。

最后一步是在用户提交的原始内容上执行搜索和替换操作,用对应的 HTML 嵌入代码或 HTML 超链接替换每个 URL。然后,修订后的主体被输出到 web 页面。

图 12 演示了产生的输出,内联地显示了嵌入的内容。

图 12. 一个带有内联嵌入式内容的 web 页面
一个带有内联嵌入式内容的 web 页面的屏幕截图

结束语

本文介绍了如何使用 oEmbed 规范将存储在第三方 web 服务上的富内容(比如照片、视频和幻灯片)嵌入到 web 页面中。该规范提供一种高效而直观的方式,将来自多个流行应用程序和网站的数据嵌入到 web 页面中。本文中的例子使用了两个用于 oEmbed 的 PHP 客户端库,并且讨论了对很多流行网站(包括 Flickr、YouTube、SlideShare、Wikipedia 和 amazon.com)使用 oEmbed。

正如这些例子所演示的,oEmbed 是一个简单的专为特定目的构建的 API,只设计用于一件事情 — 嵌入内容— 并且它把这个任务完成得相当好。它为想要实现内容聚合和搜索而构建创造性新应用程序的开发人员提供一种灵活的工具。亲自试用一下,看看它的效果。

参考资料

学习

  • oEmbed 规范:更多地了解 oEmbed,此格式支持第三方站点上 URL 的嵌入式表示。
  • PEAR Services_oEmbed 组件:这个开放的规范用于寻找关于 URI 的信息,包括结构元数据(比如对象类型、标题、作者信息或缩略图详细信息)。
  • oohEmbed 服务:这是一个各种网站 HTML 嵌入代码的提供者,兼容 oEmbed。
  • 本作者的更多文章(Vikram Vaswani,developerWorks,2007 年 8 月至今):阅读关于 XML、附加 Google API 和其他技术的文章。
  • developerWorks XML 专区:在 XML 专区获取提高您的专业技能所需的资源。
  • IBM XML 认证:了解如何才能成为一名 IBM 认证的 XML 和相关技术的开发人员。
  • XML 技术库:访问 developerWorks XML 专区,获得广泛的技术文章和技巧、教程、标准和 IBM 红皮书。此外,阅读更多的 XML 技巧
  • developerWorks 技术活动网络广播:随时关注这些活动中的技术。
  • developerWorks 播客:收听面向软件开发人员的有趣访谈和讨论。
  • developerWorks 按需演示:观看演示,内容包括面向初学者的产品安装和设置演示,以及为经验丰富的开发人员提供的高级功能。

获得产品和技术

  • PEAR Services_oEmbed 组件:下载这个用于寻找关于 URI 的信息的开放规范。
  • php-oembed 库:下载这个 PHP 库,它提供一个兼容 OEmbed 的接口供 JavaScript 和 PHP 客户端使用。它通过充当代理来处理 OEmbed 提供者,并具有一个插件系统,您可以在那里添加自己的嵌入式提供者。
  • IBM 产品评估试用版软件:下载或 IBM SOA Sandbox for People,并开始使用来自 DB2®、Lotus®、Rational®、Tivoli® 和 WebSphere® 的应用程序开发工具和中间件产品。

讨论

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=XML, Open source, Web development
ArticleID=650465
ArticleTitle=利用 oEmbed 和 PHP 访问第三方内容
publish-date=04252011