先日、とあるホームページを作っている時に、ブログと連動したいという要望をいただいたので、ブログをGoogleBloggerで書いてその情報をホームページに読み込むという処理を作りました。
その時に作ったコードをブログで紹介します。
そもそも、ブログを主体としたWordpressなどのシステムで作っている場合は、今回のような作り込みは必要ないのですが、個人的にアンチWordpressなので、
このような少しややこしい開発をすることになっています。
ということで、用途が限られているプログラムであることは間違いないので、今回紹介する方法が最善とは言いませんが、手軽にブログシステムと連携するというやり方の一例として見てもらえると言いかと思います。
要望と仕様と条件
まず大前提として、ホームページはどこのサーバーで作っていてもブログ情報を取得して、トップページのブログ一覧に表示するようにします。
ホームページのJavascriptでサクっとBloggerの情報を読み込められればいいのですが、ブラウザセキュリティ縛りのために、簡単にはできません。
ということで、今回はPHPをAPI踏み台としてつくことにします。
APIをよく使う場合は、自己サイトでJavascript用の踏み台としての
RestAPIを作っておくと便利かもしれませんね。
ソースコード
blogger.js
/**
* Bloggerの記事一覧を取得するAPIからデータを取得するライブラリ
*/
export class Blogger{
static datas = null
constructor(options){
this.options = options
this.promise = new Promise((resolve, reject) => {
this.resolve = resolve
this.reject = reject
this.load()
})
}
get default_api_url(){
return import.meta.url.replace("blogger.js" , "blogger.php")
}
load(){
const query = {
mode : "blogger",
api : this.options.api || this.default_api_url,
feed : this.options.feed,
}
const xhr = new XMLHttpRequest()
xhr.withCredentials = true
xhr.open('POST' , this.options.api , true)
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")
xhr.onload = this.loaded.bind(this)
const query_string = Object.entries(query).map(([key, val]) => `${encodeURIComponent(key)}=${encodeURIComponent(val)}`).join('&')
xhr.send(query_string)
}
loaded(e){console.log(e)
const res = JSON.parse(e.target.response)
// console.log(res)
if(res && res.status === "success"){
Blogger.datas = res.datas
}
this.finish()
}
finish(){
this.resolve(Blogger.datas)
}
}
main.php
<?php
/**
* javascriptからの問い合わせ用エンドポイント
*/
switch(@$_POST["mode"]){
case "blogger":
require_once "blogger.php";
$inst = new Blogger($_POST);
$res = [
"status" => $inst->datas ? "success" : "error",
"datas" => $inst->datas,
"options" => $inst->options,
];
echo json_encode($res , JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
break;
}
blogger.php
<?php
class Blogger{
var $datas = [];
var $options = [];
function __construct($options){
$this->options = $options;
$this->datas = $this->get_datas($options["feed"]);
}
function get_datas($feed_url){
$result = array();
// "@" is for error handling
$feed = @simplexml_load_file($feed_url);
$ns = $feed->getNamespaces(true);
//atom
if (isset($feed->entry)) {
$result['rss_ver'] = 'atom';
$result['title'] = (string)$feed->title;
$result['link'] = (string)$feed->link->attributes()->href;
foreach ($feed->entry as $e){
if(!empty($e->issued)) {
$date = date('Y-m-d H:i:s', strtotime($e->issued));
} else if ($e->updated) {
$date = date('Y-m-d H:i:s', strtotime($e->updated));
}
$result['items'][] = array(
'title' => (string)$e->title,
'link' => (string)$e->link['href'],
'date' => $date,
'category' => (string)$e->category,
'media' => (string)$e->media['src'],
);
}
}
//rss1.0
elseif (isset($feed->item)) {
$result['rss_ver'] = 'rss1.0';
$result['title'] = (string)$feed->title;
$result['link'] = (string)$feed->link;
foreach ($feed->item as $i){
$dc = $i->children('http://purl.org/dc/elements/1.1/');
$result['items'][] = array(
'title' => (string)$i->title,
'link' => (string)$i->link,
'date' => date('Y-m-d H:i:s', strtotime($dc->date)),
'category' => (string)$i->category,
'media' => (string)$i->media,
);
}
}
//rss2.0
elseif (isset($feed->channel->item)) {
$result['rss_ver'] = 'rss2.0';
$result['title'] = (string)$feed->channel->title;
$result['link'] = (string)$feed->channel->link;
foreach ($feed->channel->item as $i){
$d = strtotime($i->pubDate);
$ymd = date('Y/m/d', $d);
$his = date('H:i:s', $d);
$result['items'][] = array(
'title' => (string)$i->title,
'link' => (string)$i->link,
'date' => `$ymd $his`,
'ymd' => $ymd,
'hid' => $his,
'category' => (string)$i->category,
'media' => (string)$i->children($ns['media'])->thumbnail->attributes()->url,
);
}
}
else {
return false;
}
return $result;
}
}
上記を呼び出すJavascript
import { Blogger } from "./blogger.js"
class Main{
constructor(){
new Blogger({
api : "main.php",
feed : "https://example.blogspot.com/feeds/posts/default?alt=rss", // ブロガーのfeed url
}).promise.then(datas => {
// ブログ情報読み取り後の処理を記載
})
}
}
switch(document.readyState){
case "complete":
case "interactive":
new Main()
break
default:
window.addEventListener("DOMContentLoaded", (()=>new Main()))
}
あとがき
自分の備忘録的なブログとして書いておきました。
「ブログ情報読み取り後の処理を記載」の箇所は、取得したデータを見て、itemsというところに、ブログ記事の一覧が入っているので、一覧表示するようなコードを書けば、
どこのホームページでも手軽にブロガーと連携して、ブログ表示することができます。
ちなみに、以前も似たようなモノを作っていたので紹介すると、
https://myntinc.com
うちの会社のホームページで、ブログ記事を表示しているのは、このコードを使っています。
ブロガーをコンテンツデータベースにして、それをホームページでコントロールして、一覧(または単一)を扱うプログラムが書ければ、色々なシステム構築ができてしまうと思いません?
今回PHPで書いていますが、RubyやPythonやGoやRestで書いても手軽にAPI化できてしまうでしょう。
ややこしく思える踏み台APIですが、慣れてしまえばとても便利にブラウザセキュリティにも優しい環境が作れるのでオススメですよ。
お試しあれ!
0 件のコメント:
コメントを投稿