IT系おじさんのチラシの裏
2018年10月~
当サイトの記事にはアフィリエイト広告のリンクが含まれる場合があります

PHPでjson_encode/json_decodeする例

Webサイトを運営していると、運営サイト上のデータを取得して、ローカルで処理したいケースがあります。

そんなときに便利なPHPのjson_encodeとjson_decodeの話。

事例

例えば、登録型のリンク集を運営している場合。

  1. 運営サイト(レンタルサーバー)の登録フォームで、訪問者がサイト情報を登録
  2. サーバー上ではChromeが起動できないため、ローカルのWindows PCでChromeを起動してスクリーンショットを撮る

2番目のChromeでスクリーンショットを、というのは「コマンドラインでWebサイトのスクリーンショットを撮る簡単な方法」で紹介したHeadless Chromeのことです。

このケースの場合、サーバー上でHeadless Chromeを動かせないので、ローカルで実行するわけですね。

サーバーが共有のレンタルサーバーではなく、VPSだったりする場合は自前でNode.jsやpuppeteerを入れてHeadless Chromeが動くようにしても良いのですけれど、まぁ今回はレンタルサーバーを想定ということで。

サンプルコード

サーバー側がCentOS等で動いている一般的なレンタルサーバー、ローカル側はWindows PCで動いている運営管理用のWebサーバーとします。双方がWebサーバーなので、要するにサーバー間の通信ですね。

通信方法は色々あって、それこそソケット通信をしても良いし、流行り(?)のXMLでやりとりしても良いし、レガシーなCSVでやりとりするのもアリでしょう。

でも今回はJSONを使います。なぜならJSONが一番らくちんでコードが見やすいと信じているから!

サーバー側でJSONを生成する例

サーバー上のDBにはsiteというテーブルがあって、serial型のseqとURLが入った列があるという想定です。

<?php
//変数初期化
$site_array = array();
//PDO設定
$pdo_dsn = 'mysql:host=localhost;dbname=test;charset=utf8;';
$pdo_user = 'root';
$pdo_pass = '********';
$pdo_option = array(
	PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
	PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
	PDO::ATTR_EMULATE_PREPARES => false,
	PDO::ATTR_STRINGIFY_FETCHES => false
);			
//データベース接続
$pdo = new PDO($pdo_dsn, $pdo_user, $pdo_pass, $pdo_option);
//SQL発行
$query = "SELECT seq,url FROM site ORDER BY seq DESC LIMIT 10";
$stmt = $pdo->query($query);

while ($row = $stmt->fetch()) {
	$filename = './cache/site_'.$row['seq'].'.png';
	if (!file_exists($filename)) {
		$site_array[] = $row;
	}
}
echo json_encode($site_array, JSON_UNESCAPED_UNICODE);
?>

siteテーブルを最大10件読み込み、ひとつひとつキャッシュ用のPNGがあるかないかチェックしています。キャッシュがなければSSを撮る必要があるため、$site_array配列に情報を格納、という流れ。

CSVだったら、seqとURLを並べて出力するところですが、CSVって区切り記号に気を使うじゃないですか。

あまり見ませんけど、URLにカンマを使うことも出来ますし。

なので、あえてカンマ以外の区切り記号を使ってCSVを使っている例も見かけますけど、ともかく、区切り記号に気を使わなければいけないのは事実ですよね。

一方で、JSONなら連想配列をまとめてシリアライズしてくれるのが素敵。

json_encode関数のオプションでJSON_UNESCAPED_UNICODEを指定していますが、これはマルチバイトのUnicode文字をそのままの形式で出力する、という意味です。デフォルトでは\uXXXXみたいにエスケープされてサイズが大きくなってしまうので、どうせ受け取り側もUTF-8で処理するとわかっているのならあえてエスケープする必要もないだろう、と。

ローカル側でJSONを受け取る例

<?php
//サイト一覧を取得
$json = file_get_contents('https://example.com/site_json.php');
$site_array = json_decode($json, true);

foreach ($site_array as $site) {
	$filename = 'site_'.$site['seq'].'.png';
	//chromeでSSを取得
	$command = '"C:/Program Files (x86)/Google/Chrome/Application/chrome.exe" --headless --disable-gpu --screenshot='.$filename.' '.$site['url'].' 2>&1';
	$output = null;
	$ret = false;
	exec($command, $output, $ret);

	//実際はこのへんでSSのサムネイルを作成する処理を書いたりする
}
?>

先程書いたサーバー側の処理は https://example.com/site_json.php に保存されていると仮定しています。

file_get_contentsでJSONを読み込み、json_decodeで連想配列に戻すだけなので簡単らくちんですね。

json_decodeの2番目の引数に true と指定しているのは「連想配列にしてね」という意味です。これがないとただの配列になってしまうため、seqやurl等の添字が使えません。

あと、サンプルなので$filenameには相対パスを入れていますが、実際は絶対パス指定したほうが良いでしょう。Chromeから見てのパスになるので。

まとめ

ここまでで、下記の処理が完了しました。

  1. 運営サーバーで登録されたサイト情報の一覧を取得
  2. 最近登録された一覧からそれぞれのサイトのスクリーンショットを取得

あとは出来上がったPNGをアップロードして完了ですね。

アップロードする処理のサンプルも需要あるかなぁ。

うちのブログでは下記のとおりDLする処理ばかり紹介してた気がしますね。

これの逆をするだけなので、あまり必要ない気もしますが、アップロード処理についてはまた機会があれば書こうと思います。

関連記事

Windows環境にphpmyadminをインストールする

最近のレンタルサーバーなら管理ページでポチっとボタンひとつでphpmyadminのインストールくらい完了しますし、手動でやるとしても公式サイトからZIPをダウンロードして解凍してアップロードする程度で

Windows版PHPでSFTP接続するにはphp_ssh2.dllが必要

Web運営のメンテナンス作業(ローカルへのバックアップ作業とか)を自動化する方法について4回にわけて記事にしてきました。 WSHでブラウザを自動操作する PHPでファイルとDB(Postgre

コメント

新しいコメントを投稿する

[新規投稿]
 
TOP