Category Archives: php

動的に生成されるURLに対して固有のOGPを生成する方法メモ

http://hoge.com/#1000 みたいな、ハッシュ以下の値に対してコンテンツを書き換えるサイトで、それぞれのハッシュに応じて異なるOpen Graph Protocol(OGP)を吐き出したい時の対処法。

フェイスブック、ミクシィ、グリーで使われている OGP (Open Graph Protocol) とは何か
http://d.hatena.ne.jp/amachang/20110117/1295233078

1. まず同一ドメイン内に、OGP吐き出し用のPHPを用意する。

ex) http://hoge.com/share.php

2. 元のhtmlと同一のハッシュを受け取ってその値に応じたOGPを吐くようにする。

ex) http://hoge.com/share.php?id=1000

3. html内に設置したShareボタン、Likeボタンの対象URLを上記のshare.phpにする。

 <div data-href="http://hoge.com/share.php?id=1000" data-send=false data-layout="button_count" data-width=450 data-show-faces=false></div>

4. このままだとウォールにshare.phpのURLが投稿されてしまい、ウォールからアクセスしたユーザーがshare.phpに飛んでしまうので、share.php内でfacebookのクローラー以外を元のhtmlにリダイレクトする。
facebookのクローラーはUserAgant内の“facebookexternalhit”の有無で判定する。

Best Practices – Facebook開発者
http://developers.facebook.com/docs/best-practices/

5. 以下share.phpの概要

<?php
$id = $_GET["id"];
$ua = $_SERVER['HTTP_USER_AGENT'];
 
//facebook crowlerじゃなかったらリダイレクト
if (!preg_match('/facebookexternalhit/i', $ua))
{
    header("HTTP/1.1 301 Moved Permanently");
    header("Location: http://hoge.com/#" . $id);
    exit;
}
 
//idに応じて情報を取得する
$api = "http://hoge.com/api?id=" . $id;
$json = file_get_contents($api);
$user_data = json_decode($json);
$username = htmlspecialchars($user_data->result->username);
$img_path = htmlspecialchars($user_data->result->img_path);
 
?><!DOCTYPE html> 
<html lang="en" xmlns:og="http://ogp.me/ns#"> 
    <head>
        <meta charset="utf-8"> 
        <meta property="og:title" content="<?=$username?>'s page">
        <meta property="og:description" content="SITE DESCRIPTION">
        <meta property="og:url" content="http://hoge.com/#<?=$id?>">
        <meta property="og:image" content="<?=$img_path?>">
        <link rel="image_src" href="<?=$img_path?>">
        <title><?=$username?>'s page</title>
    </head>
    <body>
        <script type="text/javascript">location.replace("http://hoge.com/#<?=$id?>");</script>
    </body>
</html>

simpleXML manners 2

phpの命名規約で許可されていない文字を持つxml要素にアクセスする方法。

<data>
<first-name lang="jp">hanako</first-name>
</data>

このxmlのfirst-name要素の値hanakoを取得する時は、

(string) $xml->data->{"first-name"};

lang属性を取得する時は、

(string) $xml->data->{"first-name"}[0]["lang"];

simpleXML manners

<data>
	<elem name="A" age="10"/>
	<elem name="B" age="20"/>
	<elem name="C" age="30"/>
</data>

みたいなxmlの、nameがAのelemのage、要するに10をsimpleXMLで取得しゅる方法。

まずxmlを読み込んで、

$xml = simplexml_load_file("data.xml");

xpathでnameがAのエレメントを抽出する。

$elem = $xml->xpath('//elem[@name="A"]');

$elemがsimpleXMLElementオブジェクトなのでstring型にキャストする。

$age = (string) $elem[0]["age"];
echo $age;
//10

このstringにキャストする部分でだいぶハマった。直感的なようで直感的でないsimpleXML。

using simpleXML to parse xml with namespace

simpleXMLを使ったnamespase付きxmlのパースでハマったのでメモ。

パースするxmlを文字列として$strに代入。

$str = <<<XML
<html xmlns="http://www.w3.org/TR/xhtml1">
	<body>
		<p>test</p>
	</body>
</html>
XML;

$strに代入した文字列をSimpleXMLElementオブジェクト化する。

$xml = new SimpleXMLElement($string);

simpleXMLElementのregisterXPathNamespaceでnamespaceを登録する。第一引数はnamespaceプレフィックス。こういうの<prefix:html>とかこういうやつ<xml:html>。たぶんここは適当でいい。第二引数はパースするxmlのnamespace。

$xml->registerXPathNamespace("xhtml", "http://www.w3.org/TR/xhtml1");

xpathで検索する時は先のプレフィックス付きで渡す。

$p = $xml->xpath("//xhtml:p");
echo $p[0];

結果は

test

なんかnamespaceって仕様があとづけっぽくて肌が合わない。