我一直犹豫是否称它为“API”,因为我非常确定这与“API”的含义并不完全相同。但是,它确实是在与应用程序交互的编程,所以就这样吧。上周我介绍了一段可以包含在页面上的 JavaScript 代码,用于从 Quotes on Design 在你的页面上添加随机的设计名言。今天,我们将讨论它的构建方式和工作原理。再次感谢 David Walsh 帮助我创建它。
它是如何工作的?
我真的很想确保它尽可能易于使用,这基本上意味着它必须是一个“代码片段”。它肯定需要是 JavaScript,因为这使我们能够修改 DOM 并根据需要插入引号。起初,我完全使用 JavaScript。我让它读取站点的 RSS 输出并随机插入其中一个。结果证明它慢得令人痛苦,需要一个 JavaScript 库,并且仅限于最后添加的 10 个引号。
David 建议将 JavaScript 文件实际上改为 PHP 文件。什么?
狡猾的伎俩 - JavaScript 实际上是 PHP
最终,JavaScript 需要真正成为 JavaScript。但是,我们可以先使用 PHP 收集我们需要的信息,然后动态地输出我们需要的内容。如果您 直接加载 JS 文件,可以看到它在实际工作。
使服务器将其视为 PHP
首先,我们需要确保服务器将文件解释为 PHP,尽管它的文件扩展名是 .js。我们使用一些 HTAccess 魔术来实现这一点。
<FilesMatch "^.*?api.*?$">
SetHandler php-script
</FilesMatch>
我把这个 .htaccess 文件放在服务器上的“api”目录中。它基本上表示任何名称中包含“api”的文件都应解释为 PHP。这仅适用于 Apache 服务器,并且在不同的服务器上会有所不同。这正是我在 Media Temple (gs) 上使用的方法。
使浏览器将其视为 JavaScript
我们的文件 api.js 现在可以被服务器解释为 PHP 了,我们只需要确保浏览器仍然将其视为 JavaScript,所以让我们通过将以下代码放在顶部来确保。
<?php
header('Content-Type: text/javascript');
?>
所需的 JavaScript 输出
在开始使用 PHP 之前,让我们看看我们最终需要从 JavaScript 中获得什么。我们需要一个简单的函数,使用getElementById方法来定位我们的“quote”div,然后使用innerHTML属性将引号注入到正确的标记中。
function getQuote(id) {
document.getElementById(id).innerHTML = "<p class='qod-quote'>',QUOTE-GOES-HERE,'</p><p class='qod-author'><a href='',PERMALINK-GOES HERE,''>',AUTHOR-GOES-HERE,'</a></p>";
}
不要担心 QUOTE-GOES-HERE 这件事,这是我们稍后需要 PHP 的地方。然后我们需要在主机站点加载时调用此函数。
window.onload = getQuote("quote");
使用 PHP 获取数据
显然,我们需要用实际数据填充上面函数中的空白。这就是我们需要 PHP 的原因。数据位于 WordPress 数据库中,因此我们需要连接到该数据库,然后设计一个查询来获取我们需要的内容。
连接到数据库
$link = mysql_connect('localhost','database_user','database_password');
mysql_select_db('database_name',$link);
查询随机引号
以下代码将从数据库中获取一个随机条目。其中大部分是特定于 WordPress 数据库的,因此我们执行一些特殊操作,例如确保条目已发布并且是帖子(而不是页面)。
$query = 'SELECT post_content AS quote, post_title AS author, guid AS permalink FROM wp_posts WHERE post_status = 'publish' AND post_type = 'post' ORDER BY rand() LIMIT 1';
$result = mysql_query($query,$link) or die(mysql_error().': '.$query);
将结果转换为数组
$row = mysql_fetch_assoc($result);
将数据插入函数
我们已经看到了最终的 JavaScript 应该是什么样子,但是现在我们可以用正确的数据填充它了!我们可以从我们的 $result 数组中直接放入大部分数据,但引号需要进行一些特殊的清理以处理特殊字符。
$quote = str_replace('"','"',$row['quote']);
对于最终的函数,我们可以简单地输出输出
echo 'function getQuote(id) { document.getElementById(id).innerHTML = "<p class='qod-quote'>',$quote,'</p><p class='qod-author'>',$row['author'],'</p>"; } window.onload = getQuote("quote");';
如您所见,在我们定义函数后,我们在窗口的 onload 事件期间调用它,这会在调用它的页面准备好时触发它。
我有哪些选择?
只有一个,如果您真的不想在链接上显示指向 Quotes on Design 的永久链接,您可以通过在 URL 中附加参数 (?link=no) 来关闭它。这又是使用 PHP/JavaScript 组合的另一个很酷的原因!
<script type="text/javascript" src="http://quotesondesign.com/api/api.js?link=no"></script>
此代码应该相当容易适应,以添加几乎任何 WordPress 博客的“API”。
需要一个小 API,Chris!JavaScript 非常方便,因为它可以使用 PHP 生成,并且可以避免大量客户端编程。
如果这些问题很密集,请原谅我。
js 文件使用 api 作为名称进行别名是为了将其解析为 PHP,以克服可能存在的限制,即无法服务器端包含非同域文件(如在 PHP.INI 中调整 url_fopen 或类似内容以加强安全性)?
另外,为什么必须运行 onload 函数,因为 PHP 可以(如您所示)直接从您在网页上放置引号的任何位置输出内容(和 div 包装器)?
感谢您的时间(和优秀的“api”),Chris 和 David!
1. 实际上不需要 htaccess 的技巧...只需 http://quotesondesign.com/api 就足够了...您可以通过 content-type 标头使 /api/index.php 服务器成为 JS 文件
2. 为什么您要重载 window.onload ...这不会覆盖任何其他 window.onload 行为吗?
3. 我宁愿不使用 PHP API,而是将所有引言都存储在文本文件中(例如 1.xml、2.xml…),然后使用 JavaScript(简单的 JavaScript,不使用 PHP)随机生成一个数字,再下载并显示该引言(可以使用 XMLHttpRequest)。
主要目的是服务器不需要一直运行 PHP,也不需要每次请求引言时都执行随机选择和数据库查询。
例如,api.js 会选择一个随机数字,下载 $RANDOM.xml,并将其用于在 window.onload 中添加行为,并将 $RANDOM.xml 中的引言插入页面。
随着引言数量的增加,您需要修改 api.js,但除此之外,其他方面应该都没问题…
每个新引言都发布到 CURRENT_MAX_QUOTES+1.xml 文件中。
好主意!就我个人而言,我更喜欢使用 JSON 而不是 XML,尤其是考虑到简单的数据结构…
很有用。感谢“Tricky Tricky”部分。:-)
我讨厌 PHP,习惯了 Rails,从那以后就没再碰过 PHP。
@duryodhan,你的解决方案听起来不错,但为什么要使用单独的 XML 文件呢?为什么不将引言作为标签,例如
<quote>
<quote-content>
"Hello."
</quote-content>
<quote-author>
"John Smith"
</quote-author>
</quote>
我对 XML 不太熟悉,只是想知道为什么应该使用多个文件…
我曾经做过类似的事情,用于在博客网络中同步标题。这是一个非常有用的技巧。
htaccess 的魔法实际上没有必要,因为它只是美化了 JS 文件的 URL——浏览器不会关心文件扩展名,设置 content-type 就足够了。
因此,您也可以将 api.js 重命名为 api.php,并告诉人们包含以下内容:
<script type="text/javascript" src="http://quotesondesign.com/api/api.php?link=no"></script>
此外,您应该建立某种缓存机制,以避免每次获取随机引言时都必须连接到 MySQL。例如,您可以将所有引言存储在一个文件中,并从该文件中随机选择一个引言,而不是从数据库中选择。
将您的引言放入数组中,并使用 serialize() + unserialize() 存储数组**或**(我更喜欢这个方法,因为它性能似乎更好)使用 var_export() 并将文件作为 PHP 文件包含。
建立一个刷新缓存的例程(例如,如果缓存文件超过一小时——filemtime())。
使用 array_rand() 选择一个随机引言。
我刚刚尝试了你的建议,使用一个简单的 PHP 文件,该文件只向浏览器输出“hello world”。即使在 php.ini 文件中设置了 allow_url_fopen = on 和 allow_url_include = on,也没有任何反应。首先,我尝试了 src=非同域类型的 PHP 文件,然后尝试了一个包含非同域 PHP 文件的本地 PHP 文件。两者都没有成功。有什么建议吗?
如果您想知道,在 allow_url_fopen = on 和 allow_url_include = on 的情况下,如果我简单地包含本地 PHP 文件(并且它依次包含非同域 PHP 文件),则如预期的那样,我得到了“hello world”的输出。
如果我误解了你的问题,我深感抱歉,但是你是否尝试了他的第一个建议,只是包含了文件扩展名为 php 的 javascript?如果是这样,据我所知,“allow_url_include”和“allow_url_fopen”与此无关。
请记住,PHP 脚本必须输出 javascript 代码。如果您从浏览器访问 PHP 脚本,并且它只是在屏幕上打印“hello world”,这就像包含一个内容为“hello world”的 javascript 文件。尝试让 PHP 输出以下内容:alert('hello world');,可以将其更改为动态地将“hello world”放入页面而不是警报的 javascript 代码。
还要记住包含 Chris 在上面提到的 header 语句。
再次抱歉,如果我误解了你想要做什么。
感谢 Chris 和 David 创建了这个!Chris,一如既往地感谢你精彩的帖子!我记得第一次发现 PHP 可以打印可以包含在页面中的 javascript 代码。我当时非常惊讶…。
哇,我看到这里有一些疯狂的科学实验。谢谢 Chris。阅读你的帖子总是很愉快。继续保持疯狂!
@Paul:这和我说的基本一样。
@Johan
这只是一个引言.. Chris 有上千个引言,他想随机显示一个…所以我说他可以有 1.xml、2.xml…1000.xml.. JavaScript 会生成一个随机数字,然后下载相应的 .xml.. 它们都会使用相同的样式表,
我非常相信 KISS 原则,因此我选择了这种方法。
选择 JSON/XML/微格式等等都是次要的.. 我的主要观点是设计的选择…
是的,我知道,但是在我阅读的关于 XML 的少量内容中,据说可以使用 JavaScript 访问 XML 文件中的所有节点,就像数组一样:quote[0]、quote[1]…quote[1000]。我可能错了,但在我看来,为每个新引言创建一个新文件似乎很奇怪。你不觉得吗?
您也可以创建一个 PHP API。
api.php
$quote = getQuoteFromDatabase(); // 返回数组
echo serialize($quote);
site.php
$quoteData = file_get_contents('http://qod/api.php');
$quote = unserialize($quoteData);
echo $quote['author'] . ' said: ' . $quote['quote'];
您可以为 http://quotesondesign.com/api/api.js 添加一个远期失效的 header 吗?这会让 YSlow 更开心一些。
我想我们可以使用下载文件,不是吗?:D