こないだ「以前つくったCoCキャラシート作成ツールをブラウザで動作させてみようとしている」と書いたが、ようやっとひいこら実現させた。機能はもちろんpython版とほぼおなじで、

  • ステータスをランダムに振ってHPやSANを自動計算
  • 入力したデータは整形し別タブで出力

という感じだが、python版の機能に加えて

  • 年収欄、キャンペーン・シナリオ欄追加
  • 出力テキストに、どの技能に職業P興味Pを振ったか明示
  • 作成データはデータベースに保存可能
  • 保存データは下部で一覧を閲覧可能
  • 一覧からも整形テキストを出力可能

といった機能を追加した。

いや、データベース機能はもともとつける気はなかったんだ。ただ、PHPとApacheをインストールする際に使用したソフトウェアにMySQLというデータベースも含まれており、「なんじゃこりゃ、でーたべーす?」と調べているうちに面白くなってきたのでついでに組み込んでしまった。どうやらPythonでもデータベースを利用することはできるそうなので、「ついで」で世界が広がり結果オーライといったところか。あと組み込める機能としては、保存データを、テキスト出力するだけでなく編集もできるようにするってところか。実装の構成もわりと容易に考えつく。ただ、まあ、サーバマシンがないからどうせ公開は不可能だしな?

ズコー、としたところで「公開できないならノウハウを晒せばいいじゃない!」今回はこれを作るのに詰まったところやtipsなどを書くぜ。いやこんなコアなネタをありがたがる人はここの読者にはいないと思うけれどさ、初心者むけの講座が多数並ぶなか、超初心者の「実際にやってみたわ」レポートが存在しているのってそう悪くないとも思うんだよな。

PHPからDBをいじりたい

PHP標準クラスのPDOを使え。

$pdo = new PDO(
    "mysql:dbname=/*使うスキーマの名前*/",
    "接続に使うユーザ名",
    "接続に使うパスワード",
    array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION) # 意味はしらん
    );

で接続をつくる。

 

PDOでSELECT, INSERTがしたい

# SELECT
$record = $pdo->query("SELECT/*クエリを書く*/")->fetch(PDO::FETCH_ASSOC);

で$recordに array("id"=>1, "name"=>"me") って感じの連想配列が入る。

$records = $pdo->query("SELECT/*クエリを書く*/")->fetchALL(PDO::FETCH_ASSOC);

で$recordsに array(0=>array("id"=>1, "name"=>"me"), 1=>array("id"=>2, "name"=>"you")) って感じの連想配列が入る。

# INSERT, UPDATE
$insert = $pdo->prepare("INSERT/*ここにクエリを書くが、サニタイズのため書き込む値は :id という風にしておく*/");
$insert->bindValue(":id", /*ここでようやく実際に書き込む値を書く*/, PDO::PARAM_INT);
$insert->bindValue(":name", /*おなじく*/, PDO::PARAM_STR);
$insert->execute();

でレコードの挿入。UPDATEはクエリが違うだけで他はINSERTと同じ。

 

spanタグに幅を設定したい

styleに display:inline-block; を入れろ。htmlにはインライン要素とブロック要素があり、幅の指定はブロック要素にしかできない。 span はインライン要素であるため、幅は設定できないことになる。だったら inline-block でブロック要素にしてしまえという話。

 

divを横に並べたい

並べたい divstylefloat:left; を追加。並べるのをやめたいところで styleclear:both; を追加した空divを置く。

 

javascriptとphp間で配列のやり取りをしたい

javascriptが扱える形にするときはphp側で json_encode() を使いJSON形式にする。 json_decode() で元に戻る。

 

javascriptでランダム値を作りたい

Math.random() を使え。ただこいつがちとくせもので、Pythonの random() 関数のように引数をとって指定範囲のランダム値を出すというような器用な真似はしてくれない。これ単体では、0から0.999...の乱数を返すのみなので…

// 0から15のランダム値が欲しければこいつに16を掛け、小数点以下を切り捨てればよい。
var result = Math.floor(Math.random() * 16);
// 範囲を指定したければ、最大値から最小値を引いた範囲での乱数を出し、そこに最小値を足せばよい。
var result = min + Math.floor(Math.random() * (max+1 - min));

 

javascriptで、htmlから値を取得したり値を突っ込んだりしたい

document.getElementById().valuedocument.forms[].elements[].value を使う。

<!--html側-->
<form id="f">
<input type="text" id="in">
<output id="out"></output>
</form>
// javascript側
var a = document.getElementById("in").value;
document.forms["f"].elements["out"].value = a;

この項目はまだ理解しきれていない。そもそも前者のほうではエレメントのidしか求められていないのに、後者ではフォームのidとセットで要求されていやがる。おかしいだろ。まあ別の機会でまた詰まって、詳しく知ることになるだろうさ。

 

別ウィンドウにPOST変数を送りたい

本スクリプトでは、入力されたデータ(並びにそれの計算結果)は連想配列にまとめて別ウィンドウへPOSTで送るが、それは以下のような手順で行っている。これは自分で首をかしげてしまうほど強引なやり口なんだが…。

<!--html側-->
<form name="f" method="post">
<input type="hidden" id="monkey">
<input type="button" onclick="output();">
</form>
// javascript側
var obj = {};
function output() {
    document.getElementById("monkey").value = /*回収したデータを連想配列にまとめたもの*/;
    var num = Object.keys(obj).length;
    obj["win" + num] = window.open("", "win" + num);
    document.f.target = "win" + num;
    document.f.submit();
}

要するに、javascript側だけでデータをPOST変数に格納して送る方法が思いつかないので、データを一度htmlにぶち込み、javascriptからフォームのsubmitを蹴飛ばし無理矢理POSTで送っているのである。いやjavascriptお前、submitがいじれるのならデータのPOST化くらいやれよと言いたくなる。絶対あると思うんだけどなー。ちなみにobjはなぜ登場しているのかといえば、別ウィンドウが増えるたびにそれらのウィンドウに別々の名前を割り振るためだ。この処理を挟まないと開ける別ウィンドウはひとつだけになってしまう。

 

上で言うようなやり方をやったがデータがobjectとかになっちゃってうまくいかんぞ

オブジェクトを文字列として表示するときはJSON.stringify()を通す。

 

ページの一部だけ更新したい

jQueryをインポートしてajax処理をする。

$(function() {
    $.ajax({
        url:"gccs.php",
        type:"post",
        data:{
            "a":1 /*リクエスト変数として送りたいデータをオブジェクトで*/
        }
    })
    .done(function(data) {
        /*実行したい内容*/
    });
});

doneメソッド内の仮引数dataにはサーバのphpから返ってきた内容が入っているので、あとはそれをhtmlのoutputにでもはめ込めばよい。ただし上の方で書いた方法ではテキストデータとして扱われてしまう。htmlデータとして扱ってもらうには次のように書く。

// こうする
$("out").html(data);
// これはダメ
document.getElementById("out").value = data;

 

リアルタイムで(計算ボタンなど押さずとも)計算を行う

これはPython版では「1秒ごとに延々と関数を実行する」ことで実現した機能だったが、「キー入力があったら関数を実行する」ってのがjQueryでちゃっちゃと実装できた。

$(function() {
    $("#id", "#id2").bind('input', function() {
        // 指定したidに入力があったら実行したい内容
    });
});

期せずしてPHP、SQL、JavaScriptに一気に触れることになってしまったが、Pythonとの違いにいちいち目をぱちくりさせたりできて結構楽しかったぜ。恥ずかしながら正直に言うと、最初は完全にPython贔屓な態度で「なんじゃこの文法、ヘンなの」とか言っていた。でもいまでは言語ごとに得意分野があるのもわかったし、自然言語と同じく、多言語に触れるほど世界観が広がるのも感じてる。最近ではむしろPythonに目新しさを覚える始末で、

初期「うっわPHPとかJSって、毎行終わりにセミコロンをつけるのかよ面倒くさ!」
最近「ヤベ、Pythonコードなのにずっとセミコロンつけてた」

初期「波括弧つけるの面倒くさ!」
最近「ヤベ、Pythonコードなのに波括弧つけてた」

初期「for文に毎回括弧つけるのかよ!!」
最近「ヤベ、Pythonコードなのに括弧つけてた」

初期「『$』!!!!???」
最近「ヤベ、Pythonコードなのに『$』つけてた」

以下の記事からリンクされています