やったこと

webサービスを作るときに考えたことを垂れ流します

cakephpサーバとajaxの通信をしてるときに「"Unexpected token <"」のエラーが出る

cakephpのサーバとajax通信をしてるときに、ブラウザ側で「"Unexpected token <"」のエラーが出て通信失敗するとき、これはおそらくcakephpのコードがどこかでエラーしていると思われる。

クライアント側に応答メッセージとしてHTML文が返ってきていて、その中にある"<"の文字をパースできなくてブラウザが怒っているのだろう。

ブラウザ側で下記のように「jqXHR」の中をデバッグしてみると、responceTextという領域にHTMLのエラー文が入っているのが分かる。このHTML文を読めばcakephpのどの箇所でエラーしてるか分かるので、頑張って修正してみてください。

$.ajax({
  type: 'POST',
  url: 'hogege',
  dataType: 'json',
  cache: false,
  data:reqdata
}).done(function(data, textStatus, jqXHR) {
  //成功

}).fail(function(jqXHR, textStatus, errorThrown) {
  //失敗
  console.log(jqXHR);
});


以上です(こんなことで一日はまってしまった・・)

twitteroauthの使い方(2015年3月時点)

twitteroauthを使ってtwitter APIによりtwitterアカウント情報を取得する方法です。

■まずアブラハムさんのページからtwitteroauthのzipをダウンロードします。
https://github.com/abraham/twitteroauth

■zipを解凍すると「twitteroauth-master」のフォルダが出てくるので、これをそのまま利用したいディレクトリに置きます。

phpで以下のようなコードを叩くとtwitteroauthが利用できます。

<?php
require_once("./twitteroauth-master/autoload.php");
use Abraham\TwitterOAuth\TwitterOAuth;

$consumer_key = "hogege";
$consumer_secret = "hogegege";
$access_token = "fugaga";
$access_secret = "fugagaga";

//タイムラインの情報をゲット
$tw = new TwitterOAuth($consumer_key, $consumer_secret, $access_token, $access_secret);
$ret = $tw->get("statuses/home_timeline", array("count" => 10, "exclude_replies" => true));
print_r($ret);
?>


twitteroauthの使い方は何だか情報がいろいろ錯綜してるみたいですが、2015年3月時点では上記のやり方でいけました(ちなみにPHPのバージョンは5.4.35、twitteroauthのバージョンは0.5.2、さくらのレンタルサーバーの環境です)。

phpで利用する場合はこれでいいとして、実は自分がやりたいのはcakePHPでtwitteroauthを使うこと。cakePHPでtwitteroauthを使う場合はどうやらこんな生易しいことではいかなさそうなので、使い方を発明したらまたブログに書きたいと思います。

postメッセージで空の配列を送信してくれない

javascriptでクライアント→サーバにpostメッセージを送信しようとしたら、「空の配列」を送信してくれなくて困った。

以下のようにしてajaxでpostメッセージを送信したんだけど、「test1」「test2」「test4」のデータはメッセージに含まれていたけど、「test3」のデータがメッセージに含まれていなかった(ブラウザは Chrome ver.41)。

//クライアント側コード
var reqdata = new Object();
var test1 = 0;
var test2 = "";
var test3 = new Array();
var test4 = null;

reqdata["test1"] = test1;
reqdata["test2"] = test2;
reqdata["test3"] = test3;
reqdata["test4"] = test4;

$.ajax({
  type: 'POST',
  url: 'hoge',
  dataType: 'json',
  cache: false,
  data:reqdata
}).done(function(data, textStatus, jqXHR) {
    console.log("success");
}).fail(function(jqXHR, textStatus, errorThrown) {
  console.log("fail");
});
//サーバ側受信内容
[data] => Array
    (
        [test1] => 0
        [test2] =>
        [test4] =>
    )


仕方がないので、以下のようにして配列が空だった場合""を入れるようにしたら、test3がpostメッセージとして送信されるようになった。

//クライアント側コード
var test1 = 0;
var test2 = "";
var test3 = new Array();
var test4 = null;

if (test3.length == 0){
  test3 = "";
}


※P.S.

サーバ側PHPで以下のように(array)でキャストしてあげる方法もあるみたい。これをすると"test3"が省略されずにちゃんと「空の配列」として扱ってくれるようになる。

$_POST['test3'] = (array)$_POST['test3'];

以上。

SQLite3で「database schema has changed」のログが出るとき

この前自分のサイトにアクセスが急増する出来事があって、そのときにwebサーバに見たことないエラーログが出力されていた。

下記のような感じのログ。

code:17,database schema has changed

このエラーは、PDOのプリペアドステートメントを使ってデータベース(sqlite3)を更新する箇所で発生していた。

エラー文の意味を英語ブログを読み解きながら調べてみたら、どうも以下のようなことが起きたらしい(日本語ブログには全然説明がなかったぞ!)

プリペアドステートメントの機能として、SQL構文のチェックの高速化のためにDBの構造(スキーマ)をキャッシュする、というものがあるらしいんだけど、このキャッシュを利用する際に、もし他のプロセスがDBテーブルの登録・削除処理行って構造(スキーマ)が変わってしまっていた場合、キャッシュが利用できなくなったとみなしてエラーを発生させる、という動作をするようだ。このとき掲題のようなエラーログが出力される。

コードでいうと以下のようなところでエラーが発生する(PHP 5の処理)。

  //DBに接続
  try {
    $db = new PDO('sqlite:hogege/tes.sqlite3');
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  } catch (Exception $e) {
    logging_err("cannot open sql database ".$e->getTraceAsString());
    return (-1);
  }
  //SQL文発行
  try {
    //★ここの処理中でDBのスキーマが変更される  
    $sql = "select * from hoge_table where user_id = :user_id";
    $stmt = $db->prepare($sql);
    $stmt->bindValue(':user_id', 1234, PDO::PARAM_INT);
    $stmt->execute();
  } catch (PDOException $e){
    //★このエラーパスに入る
    $err = $db->errorInfo();
    $errcode = $err[1];
    $errmsg = $err[2];
    logging_err("code:".$errcode.",".$errmsg);
    unset($db);
    return (-1);
  }

つまり今回のエラーは、あるユーザーがサイトを閲覧しているときにちょうど同じタイミングで他のユーザーが登録処理を行ってしまって、そのせいでプリペアドキャッシュが使えなくなってSQLの読み込みエラーが発生した、というようなことが起きたんだと思う(登録処理はうまくいったけど閲覧処理が失敗していた)。

う~ん・・、こんなんでいちいちエラーを吐いてたら使い物にならないやんsqlite・・。データの矛盾が生じないようにうまく排他をしていても、キャッシュの考慮まではできていないという感じなんだろうか。キャッシュがなかったら直でSQL発行にいくようなモードがあるかと思って探したんだけど見つからなかったし、ちょっと困りものだなこの現象は・・。

どうしたらこのエラーを回避できるかいろいろ試してみたけど、どうもテーブルを変更する処理のところでトランザクションを設けるとうまいこといくようだ。

コードでいうと下記のような感じ(PHP 5の処理)。

  try {
    $db->exec("BEGIN EXCLUSIVE;");★
    $sql = "create table hoge_table (hogege integer, fugaga text)";
    $stmt = $db->prepare($sql);
    $stmt->execute();
  } catch (PDOException $e){
    $db->exec("ROLLBACK;");★
    $err = $db->errorInfo();
    $errcode = $err[1];
    $errmsg = $err[2];
    logging_err("code:".$errcode.",".$errmsg);
    unset($db);
    return (-1);
  }
  $db->exec("COMMIT;");★

おそらく「EXCLUSIVE」のトランザクションを入れると、テーブル変更処理のところで厳密にREAD処理も排他してくれるようになるんだと思う。

sqlite3ではDB更新処理のときにデフォルトで「DEFERRED」というロックがかかるらしいんだけど、正直今回のようなエラーが発生するようでは「DEFERRED」は使い物にならなさそう。今度からテーブル操作をするときは必ず上記の「EXCLUSIVE」を使うようにしよう。

こういうのってデータベースをいじる人にとっては常識的なことなのかな、自分がすごい基本レベルのポカをしているようでなんか不安になってきた・・。

webページが謎の文字化けした

cakephpで作ったページが文字化けしてしまった。

View部分のファイルを編集してたらいつのまにか文字コードUTF-8 から Shift_JIS になってしまっていたようだ。

以下のようにindex.ctpの文字コードUTF-8に直したらちゃんと表示されるようになった。

(文字コード確認)
$nkf -g index.ctp
Shift_JIS (LF)

(UTF-8に変換)
$nkf -Lu --utf8 --overwrite index.ctp

(修正OK)
$nkf -g index.ctp
UTF-8 (LF)

しかしファイルの修正を進めていくとまた Shift_JIS に戻ってしまう現象が発生した。

vimの設定とかphp.iniの設定とかいろんなとこを見直してみたけどみんなちゃんと UTF-8 になってるし、いったいどこに Shift_JIS になってしまう要素があるのか分からなくていろいろ調べてたけど、いつの間にか Shift_JIS になる現象は収束して再現しなくなってしまった。

いったいなんだったんだこれは・・・。

愛着スタイル診断のサイト作った!

愛着スタイル診断のサイト作りました!
http://absgexp.net/psyscale/asscale

愛着スタイルを診断できる心理テストのサイトはいくつかあるみたいだけど、この「ECR-GO」というテストを使って診断できるものはまだないみたいだったので、作ってみました。

愛着スタイルとは、人間が対人関係を形成する場面でみられる心理的な傾向(愛着行動の様式)のことです。自分が以下の四つの類型のうちどれに当てはまるかチェックできます。
・安定型
・とらわれ型
・拒絶型
・恐れ型

(参考文献:「" 一般他者" を想定した愛着スタイル尺度の信頼性と妥当性の検討」)

※このサイトは、ちゃんと論文に記載されてるパラメータを使って診断してるのでそれなりの結果は得られるとは思いますが、あくまで傾向を確かめるお遊び程度のテストなので、正確な診断をしたい方はちゃんとした医療機関を受診することをお勧めします。

アブさんの工作疑惑を検証してみた

ニコニコ動画の人気ゲーム実況者アブさんがネットで炎上してるらしい。動画のマイリスト数を意図的に吊り上げて、ランキング工作をしてるのではないかと疑われてるそうだ。
【炎上】ニコ動No.1ゲーム実況者「アブ」に不正水増し疑惑が浮上 | netgeek

自分の手元には以前「ニコニコ人気ユーザーランキング」のサイトを作ったときのデータ収集のためのツールがいろいろあるので、これを使えばニコニコのデータを集めて今回の件について検証することができそうだ。

ということで、今回はアブさん疑惑についていろいろ調査してみた。

検証データの用意

まずは検証に使うためのデータを用意した。

アブさんが最近公開した動画300件をニコニコサーバーから取得して「マイリス数÷再生数」と「マイリス数÷コメ数」の比率が高い順トップ10を並べてみた(データは2015 2/25時点のもの)。アブさんの動画でマイリス工作が行われたものがあるとしたら、おそらくこの中に含まれている可能性が高いだろう。

以下がアブさんのデータ
f:id:absg:20150225203739p:plain:w400 f:id:absg:20150225210308p:plain:w400

また、他の実況者のデータと比較するために、ニコニコ人気ユーザーランキングの常連さんである「レトルトさん」と「つわはすさん」に対しても同じように情報を取得してみた。

以下がレトルトさんのデータ
f:id:absg:20150225212123p:plain:w400 f:id:absg:20150225212904p:plain:w400

以下がつわはすさんのデータ
f:id:absg:20150225213552p:plain:w400 f:id:absg:20150225214343p:plain:w400

以上のデータをもとにして、アブさん疑惑についていろいろと検証をしてみる。

アブさん疑惑その1

アブさんの動画には、再生数・コメント数に比べてマイリス数が異常に多いものがいくつかあるらしい。これらはアブさんが吊り上げ工作をしたのでは、と噂されているものだ。まずはこの疑惑について調べてみる。

検証データ表にあるアブさん・レトルトさん・つわはすさんの動画の中で、マイリス÷再生数が大きいものトップ5をピックアップしてみた。

 1.レトルトさん 変人だらけのトモダチコレクション【ソングアルバム】
 (マイリス/再生数 = 0.0635)
 2.アブさん【実況】 約束を思い出す part4 【Re;member】
 (マイリス/再生数 = 0.0599)
 3.アブさん【実況】 約束を思い出す part2 【Re;member】
 (マイリス/再生数 = 0.0301)
 4.アブさん【実況】 約束を思い出す part1 【Re;member】
 (マイリス/再生数 = 0.0285)
 5.アブさん【実況】 あなたの知らない恐怖 #1 【Kraven Manor】
 (マイリス/再生数 = 0.0241)

1位はレトルトさんの動画だけど、それ以外の動画はアブさんが上位を占めている。どうやらアブさんの動画にマイリス数が異常に多いものがいくつかあるのは確かなようだ。特にアブさんの「約束を思い出す」シリーズにはその傾向が強く感じられる。

検証データの表を見ると、他のアブさん動画のマイリス数が高いものとして「フリーソフトだけで作る実況プレイ動画作成講座」というシリーズもある。しかし、このシリーズについてはあまりあやしい匂いは感じなかった。このシリーズはそもそも再生数がとても小さいのでとても工作が入ったようには見えないし、動画作成講座として実用的な価値がある動画なので、おそらくあとから見返したい人たちによって純粋にマイリスされているシリーズなのではないかと感じた。同じマイリス数が高い動画でも、あやしい匂いがするものと特に不自然は感じないものの二種類がある様子だ。

ゲーム実況系の動画でマイリス数÷再生数が0.02を超えているようなものは、なんらかの工作の疑惑があると考えていいかもしれない。

アブさん疑惑その2

アブさんの動画には、公開初日に異常なマイリス数が付く動画がいくつかあるそうだ(マイリス数がコメント数の2倍近く付いている動画など)。次はこの疑惑について調べてみる。

動画の公開初日のマイリス数はニコニコチャートのサイトで調べることができる。筆者はニコニコチャートで検証データ表に載っている全ての動画について調査を行い、公開初日に異常なマイリス数が付いた動画(マイリス数がコメント数を上回る動画)をピックアップしてみた。以下がその結果である。

 ・アブさん【実況】 約束を思い出す part4 【Re;member】
 (コメント数:4,129、マイリス数:4,323)
 ・アブさん【実況】 約束を思い出す part2 【Re;member】
 (コメント数:4,162、マイリス数:7,141)
 ・アブさん【実況】 約束を思い出す part1 【Re;member】
 (コメント数:2,358、マイリス数:6,145)※これは公開二日目の動き
 ・アブさん【実況】 あなたの知らない恐怖 #1 【Kraven Manor】
 (コメント数:3,964、マイリス数:8,789)※これは公開二日目の動き

該当する動画は、すべてアブさんのものであった(レトルトさん・つわはすさんは無かった)。やはりアブさんの動画に公開初日付近に異常なマイリス数が付くものがあるというのは本当のようだ。ここで挙げた動画は「疑惑1」にある動画とかぶっているので、これらの動画に対して何か特別な工作が行われた可能性は高そうだ。しかし少し見方を変えてみると、アブさんの動画のうちでここに挙げた以外のものについては、異常なマイリス数が付くものはほぼ無い様子だった。もしアブさんの動画になんらかの工作が行われていたとしたら、それはほんの一部の動画についてだけ、という考え方もできそうだ。

アブさん疑惑その3

アブさんの動画「【実況】 約束を思い出す part3 【Re;member】」において起きた出来事。この動画のマイリス数が一日にして2000以上も減少する奇妙な現象が起きたそうだ。ニコニコユーザー達は「アブさんが水増ししたマイリストを抜き去った痕なのでは?」と疑っているらしい。次はこの疑惑について調べてみよう。

ニコニコチャートのサイトで確認したところ、たしかにこの動画の公開5日目のタイミングで、2849マイリス数が減少している記録が残っていた。筆者は検証データ表に載っている全ての動画について、公開後数日間のマイリス数の推移を調べてみたが、一日に2000以上もマイリスが減少している動画は、このアブさんの動画以外に見受けられなかった(数百くらいの減少ならあるけど、四桁台も減少しているものはない)。やはりこのアブさんのマイリス数が減少した件は、めったに起きない特別な事例であるといえそうだ。

しかしここで一点疑問なのが、他の疑わしい動画では起きていないマイリス数の減少が、なぜこの動画だけで起きているのだろうかということだ。筆者は、もしこの動画に工作が行われていたのだとしたら、おそらくこの動画に対してなんらかのイレギュラーな出来事が起きて、誤ってマイリストが外れてしまったのではないかと想像した。ニコニコの運営に工作活動がバレて規正されてしまったとか、工作ツールの不具合でマイリストが外れてしまったとか、何かそういった手違いが起きたのかもしれない。ともあれ、この動画に対して何か特別な人為的な介入が行われた可能性は高いといえそうだ。

結論

以上、巷で噂されているアブさんの疑惑についていろいろと検証してみたが、どのケースも根も葉もない言いがかりとか単なる誹謗中傷といった類ではなく、ちゃんとした数値に裏づけされた正当な申し立てであると感じた。その上で、筆者が考えたいくつかの結論を以下に示してみる。

・その1 ~やっぱりアブさんがやった説~
真っ先に思いつくのが「やっぱりアブさんやっちゃった」という説である。アブさんはニコニコのクリエイター奨励金やyoutubeからの収入で、かなりの収益をあげていると思うので、さらに上を目指すめにブーストをかけてしまったというシナリオが考えられる。「疑惑1」でレトルトさんの動画も挙がっているが、もしかしたらレトルトさんも同じような手口でブーストをかけてしまったのかもしれない。(★注1)しかし、少し違和感があるのは、工作の痕跡が見られるのは上記で挙がったいくつかの動画だけで、それ以外の動画についてはあまり介入の手は見られないということだ。痕跡が残らないようなもっと上手いブースト方法に切り替えたのか、それとも実験的に数個だけブーストをかけたけどもそれ以降はやらなくなったのか。いったい裏でどういうことが起きているのだろうといろいろ想像が膨らんでしまう。

・その2 ~偶然こうなった説~
可能性は低そうだけど「偶然こうなったのでは」という説も考えられる。アブさんはニコニコのNo.1実況者なので、通常の統計からはずれた特異な出来事が起きやすいのかもしれない。特にツイッターフェイスブックなどで話題になって祭り状態になるような極端な状況では、急激にマイリス数が上昇するような奇妙な現象も起き得るのかも(日中に動画が見れなくて夜に見ようと思ってみんながマイリスするとか、海外で紹介されて外国からのマイリスが集中するとか)。マイリスが一気に減少する現象は、ニコニコのサーバ側でなにか不具合が起きてマイリスが外れてしまう事故が発生したとか、そういった偶然が色々重なってこういう結果をもたらした可能性もあるのかも(ちょっと苦しい言い分だけどね・・)。

・その3 ~第三者がやった説~
筆者が一番ありそうだと思うのが、この第三者がやった説である。例えばランキング吊り上げ専門の業者か何かが、自分の開発したシステムの実験を行っていて、その対象に選ばれてしまったのがアブさんであったとか、もしかするとそういったことが起きたのかもしれない。アブさんは常にランキング上位にいるので、いかにも彼らの目に付いてしまう可能性が高そうだ。自分もニコニコ人気ユーザーランキングのサイトを作るときは、アブさんから情報を取得する実験をしていたくらいだし(ランキング1位にいたからね)、有名人になると何かとこの手の実験台にされやすいんだと思う。犯人が業者じゃなかったとしても、アブさんのファンの子が応援したくてブーストで援護射撃してしまったとか、アンチの人がアブさんを陥れるために攻撃を仕掛けてきたとか、いろんなシナリオが考えられそうだ。もし動画に工作がなされていたとしても、なにもアブさん本人がやったとは限らないからね。この説なら工作が行われた痕跡がある動画がほんの数個くらいにとどまっていることもよく説明できると思う。

しかし、もし身に覚えのない第三者に工作をされてしまったんだとしたら、アブさんも飛んだ災難といったところだろうな。ネット上でこんなに炎上してしまったら、ヒートアップした人々はおそらく疑わしきは罰せずっていう冷静な気持ちを持ちづらくなると思うから、どう転んでもアブさんは今回の出来事で多かれ少なかれ評価を落としてしまうことになりそうだ。こういう不幸な出来事が起きないためにも、ニコニコの運営の人たちにはランキング工作への対策を頑張ってもらいたいね。

とアブさん好きの筆者がフォローを入れたところで今回はお開きです、以上ご清聴ありがとうございました。

追記:
(★注1)
コメント欄にて、レトルトさんの動画「 変人だらけのトモダチコレクション【ソングアルバム】」は、レトルトさんがトモダチコレクションで作った歌を総集編としてまとめた動画なのでマイリス数が集まったのでは、というご指摘いただきました。

この動画について少し調べましたが、以下のことから吊り上げ工作等は行われていないと感じました。
①この動画は今までの総集編としての記念碑的価値があるものなので、通常のゲーム実況動画より特別にマイリス数が集まった可能性がある。
②公開初日付近のマイリス数の推移を見ても、「マイリス数>コメント数」となるような極端なマイリス数の上昇は起きていない。
③「マイリス数」と「公開マイリス数」の比率が自然であり、ボット等ではなくちゃんとした一般ユーザー達にマイリスされている可能性が高い。
レトルトさんの動画に工作が入っているのでは?と疑うような発言をしましたが、ここに訂正をしておきます。



・・・・宣伝です・・・・
Twitterアカウント同士でバトルするRPGツイッターバトラーズ!」というゲーム作りました!
よかったら遊んでみてね。
f:id:absg:20150531173308j:plain:w200