Love澤's Room

技術系ネタをまとめていたブログ。現在はカテゴリにこだわらず更新中。

JpGraph Error: 25049が出た時の対処方法

新サイトへ移転しました
約3秒後に自動的にリダイレクトします。

やりたかったこと

JpGraphを使って折れ線グラフを描画する。

エラーが起きた状況

PHPでJpGraphを利用する際に、以下のように記述。フォントは明朝体に設定。

<?php
(中略)
// グラフの描画先
$g = new Graph(400, 400); // サイズ
$g->setScale('textlin'); // 目盛り
$g->title->setFont(FF_MINCHO, FS_NORMAL, 14); // タイトルフォント
$g->title->set('テストタイトル'); // タイトル
$g->legend->setFont(FF_MINCHO, FS_NORMAL, 14); // 凡例フォント
(中略)
?>

エラー内容

以下の様なエラーが出た。

画像ではipampp.ttfとなっているが、エラーを起こすためにわざとそのようにした。実際のエラーは以下のとおり。

JpGraphError: 25049
Font file "/usr/share/fonts/ipa-gothic/ipam.ttf" is not readable or does not exist.

エラー文をみると、「ipa-gothic」ディレクトリに明朝体フォント「ipam.ttf」を探しに行っていることがわかる。

対策(簡単)

必要フォントを、「JpGraphに関するファイルが保存されているディレクトリ/fonts/」に配置する。

色々と試行錯誤したが、結局はこちらの対策に落ち着いた。

自分の場合だと、以下の様な構成になっている。

  • public_html/
    • line.php
    • JpGraph/
      • jpg-config.inc.php, jpgraph_ttf.inc.php, など
      • fonts/
        • ipag.ttf, ipagp.ttf, ipam.ttf, ipamp.ttf

JpGraphでは、JpGraph/Fonts/にフォントがあるか読み込みに行き、ない場合にはシステムのフォントディレクトリにを読み込みに行く。そのため、JpGraph/Fonts/に必要フォントを配置することで、問題が解決される。

対策(ちょっと面倒)

jpg-config.inc.phpとjpgraph_ttf.inc.phpの設定を調整する。

設定ファイル類を直接いじることになるので、ちょっと面倒。上でも書いたが、エラー文をみると、「ipa-gothic」ディレクトリに明朝体フォント「ipam.ttf」を探しに行っているため、それを解消することを試みる。

まずjpg-config.inc.phpは40行目あたりを以下のように設定する。

<?php
// define('MBTTF_DIR','/usr/share/fonts/ipa-gothic/');  // delete
// define('TTF_DIR','/usr/share/fonts/ipa-gothic/');    // |
define('TTF_DIR_M', '/usr/share/fonts/ipa-mincho/');    // add
define('TTF_DIR_PM', '/usr/share/fonts/ipa-pmincho/');  // |
define('TTF_DIR_G', '/usr/share/fonts/ipa-gothic/');    // |
define('TTF_DIR_PG', '/usr/share/fonts/ipa-pgothic/');  // |
?>

上記からもわかるように、なぜかTTF_DIRやMBTTF_DIRがipa-gothicに設定されていた。今回、JpGraphは古いサーバで使っていたものを新しいサーバへコピーしてきたものである。おそらく、これはデフォルトでこのようになっていたのではなく、古いサーバにあわせて書き換えられていたのだと思う。

次に、ipgraph_ttf.inc.phpは495行目あたりを以下のように設定する。

<?php
// check jpgraph/src/fonts dir
$jpgraph_font_file = $jpgraph_font_dir . $font_file;
if (file_exists($jpgraph_font_file) === true && is_readable($jpgraph_font_file) === true) {
    $font_file = $jpgraph_font_file;
    break;
}

// check OS font dir
// if ($family >= FF_MINCHO && $family <= FF_PGOTHIC) {  // delete
//     $font_file = MBTTF_DIR.$font_file;                // |
if ($family == FF_MINCHO) {              // add
    $font_file = TTF_DIR_M.$font_file;   // |
}                                        // |
else if ($family == FF_PMINCHO) {        // |
    $font_file = TTF_DIR_PM.$font_file;  // |
}                                        // |
else if ($family == FF_GOTHIC) {         // |
    $font_file = TTF_DIR_G.$font_file;   // |
}                                        // |
else if ($family == FF_PGOTHIC) {        // |
    $font_file = TTF_DIR_PG.$font_file;  // |
}
// else {                                // delete
//     $font_file = TTF_DIR.$font_file;  // |
// }                                     // |
?>

以上の設定で、フォントをJpGraph/fonts/以下に配置しなくてもよくなった。


なお、FF_**という変数がでてきたが、これらは同ファイル32行目あたりに以下のように定義されている。

<?php
define("FF_MINCHO",40);
define("FF_PMINCHO",41);
define("FF_GOTHIC",42);
define("FF_PGOTHIC",43);
?>

また、同ファイル348行目あたりには

<?php
$this->font_files= array(
    中略
    /* Japanese fonts */
    FF_MINCHO  =>  array(
        FS_NORMAL =>MINCHO_TTF_FONT,
        FS_BOLD =>'',
        FS_ITALIC =>'',
        FS_BOLDITALIC =>''
    ),
    FF_PMINCHO => array(
    中略
);
?>

と定義されており、その中で出てくる、MINCHO_TTF_FONTなどは同ファイル137行目あたりに以下のように定義されている。

<?php
define('MINCHO_TTF_FONT','ipam.ttf');
define('PMINCHO_TTF_FONT','ipamp.ttf');
define('GOTHIC_TTF_FONT','ipag.ttf');
define('PGOTHIC_TTF_FONT','ipagp.ttf');
?>

SESSION情報を維持したままAjaxな処理を行う方法

新サイトへ移転しました
約3秒後に自動的にリダイレクトします。

やりたいこと

Ajaxな処理をする際にも、SESSIONを維持出来るようにする。

(参考サイト)
ajax版できたよー - スキマハコ

どうするか

jQueryを用いている場合、以下のように記述すると良い。PHP側は特に特別な記述はなく、普通にSESSION変数を使用できる。

  • 変更前(SESSION情報維持できない)
$.ajax({
    url: "hogehoge.php",
    type: "POST",
    data: {
        "foo" : "bar"
    },
    success: function(json_result) {
        // 中略
    },
    error: function() {
        // 中略
    },
    complete: function(() {
        // 中略
    }
});
  • 変更後(SESSION情報維持できる)
$.ajax({
    url: "hogehoge.php",
    type: "POST",
    data: {
        "foo" : "bar"
    },
    beforeSend: function(xhr) {
        xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'));
    },
    success: function(json_result) {
        // 中略
    },
    error: function() {
        // 中略
    },
    complete: function(() {
        // 中略
    }
});

追加した部分が何を意味するか

セキュリティに関することなので、この部分は理解しておきたいのだけど、まだまだ及ばない。

  • CSRFという攻撃がある。
  • CSRF攻撃に対する策として、GET以外のメソッドでデータを送信する際にはトークンが必要である。
  • 「xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'));」の部分でそのトークンを発行している。

上記は間違っている可能性があるので、調べたら、随時追記・修正する。

以下に説明してくれているサイトをメモする。

vimの設定をする方法(MacOS X Yosemie)

新サイトへ移転しました
約3秒後に自動的にリダイレクトします。


MacBookProを購入しました。年初めに高価な買い物をしてしまったので、今年は節約志向でいこうと思います

やりたいこと

vimのシンタックスハイライトをonにするなど、自分好みにカスタマイズする。

手順

  1. terminalを開く
  2. rootディレクトリ~に移動して、そこで.vimrcを作成する(/user/share/vim/vimrcをコピーしても良い*1)
  3. .vimrcに「syntax on」と記述するなどお好みで

上記*1:コピーしたのちに.vimrcに名前を変更しないと、設定が反映されませんでした。

僕の設定は以下な感じ。その昔どちらかのサイトで公開されていたものを利用しています。ありがたいことです。どこのサイトだったかは忘れたので、また見つけたらリンク貼ろうと思います。

" vim の独自拡張機能を使う(viとの互換性をとらない)
set nocompatible
" 文字コードを指定する
set encoding=utf-8
" ファイルエンコードを指定する
set fileencodings=iso-2022-jp,sjis,euc-jp,utf-8
" 自動認識させる改行コードを指定する
set fileformats=unix,dos
" バックアップをとる
" 逆は [ set nobackup ]
set backup
" バックアップを作るディレクトリを指定する
set backupdir=~/backup
" 検索履歴を50個残す
set history=50
" 検索時に大文字小文字を区別しない
set ignorecase
" 検索語に大文字を混ぜると検索時に大文字を区別する
set smartcase
" 検索語にマッチした単語をハイライトする
" 逆は [ set nohlsearch ]
set hlsearch
" インクリメンタルサーチを使う (検索語を入れている途中から随時マッチする文字列の検索を開始)
" 逆は [ set noincsearch ]
set incsearch
" 行番号を表示する
" 逆は [ set nonumber ]
set number
" 改行 ( $ ) やタブ ( ^I ) を可視化する
"set list
" 括弧入力時に対応する括弧を強調する
set showmatch
" 構文ごとに色分け表示する
" 逆は [ syntax off ]
syntax on
" [ syntax on ] の場合のコメント文の色を変更する
highlight Comment ctermfg=LightCyan
" ウィンドウ幅で行を折り返す
" 逆は [ set nowrap ]
set wrap
" タブを表示するときの幅
set tabstop=2
" タブを挿入するときの幅
set shiftwidth=2
" 改行時に入力された行の末尾に合わせて次の行のインデントを増減する
set smartindent

以上な感じです。これであなたも(というか僕が)快適vimライフ!!

ネスト化されたstdClass ObjectからArrayに変換する方法

新サイトへ移転しました
約3秒後に自動的にリダイレクトします。


(追記)
以下の記事を書いた後、以下のブログを発見しました。
http://d.hatena.ne.jp/kasahi/20070806/1186419785

<?php
json_decode(json_obj, true)
?>

というように、第二引数にtrueを入れると、arrayにちゃんと変換されました。

以下はもはや読む必要はないのですが、せっかく書いたので残しておきます。

続きを読む

JavascriptでJSONオブジェクトの長さを取得する方法

新サイトへ移転しました
約3秒後に自動的にリダイレクトします。

やりたいこと

JSONオブジェクトから長さ(要素数、length)を取得する。

方法

以下のように記述する。

var json_obj_length = Object.keys(json_obj).length;

よくやりがちな、json_obj.lengthなどとしてもundefinedと表示されて取得できない。

(参考サイト)
http://joppot.info/2014/02/21/861

JavaScriptで配列に動的に要素を追加する方法

新サイトへ移転しました
約3秒後に自動的にリダイレクトします。


今日は簡単にメモ。

結論から言うと、リストを使います。
ただし、リストとして宣言しても、配列のように扱えるので、かなり柔軟ではないでしょうか。

javaだと、list.get(0)といったように書いた気がするので、普通のjavaよりも楽?な気がした。

var list = new Array();
list.push("追加したい値");

これでよい。最初から値を用意しておきたいときは

var list = new Array(2);
list[0] = "hoge";
list[1] = "huga";

などとする。

jQuery+PHPでAjaxな通信をするための実装メモ

新サイトへ移転しました
約3秒後に自動的にリダイレクトします。

けっこう悩んだので、何をした時にダメで、どうしたらうまく動作したかをメモ。
(参考サイト)
jQuery.ajaxで簡単に非同期通信 - 背負い投げとENTER_FRAME

やりたいこと

あるページで「次へ」ボタンを押したら、そのページで表示されている画像を更新される、というページの作成。

注意点

サーバのデータベースとやりとりをして得た値を使用して要素を更新する処理を行いたい場合は、$.ajax()内successの項に書きましょう。

失敗例

javascript側で、Ajaxでの通信部分を以下のように実装していたが、反応しなかった。数カ所にデバッグ用のalert()を用意して確認したところ、理由がわかった。それは$.ajax()の外の方が先に実行されるからだった。

  • HTML(image_view.html)
<head>
    <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script type="text/javascript" src="question_reply_form.js"></script>
</head>
<body>
  <div id="image_number">1枚目</div>
  <img id="image" src="image1.png" width="800" border="1">
  <button id="next_button">次へ</button>
</body>
  • javascript(image_view.js)
$(document).ready(function() {
  $(".next_button").on("click", function() {
    var image_name = “”;
    $.ajax({
      url = "get_image_name.php",
      type: "POST",
      data: {"next_id" : "2"},    // 本当は動的にidを設定したいが、とりあえず今回は手動で。
      success: function(name) {
        alert("success1 :" + image_name);    // 2番目に実行される(image_name=""の状態)
        image_name = name;
        alert("success2 :" + image_name);    // 3番目に実行される(image_name="image2.png"の状態)
      }
    });
    alert(“image_name = “ + image_name);    // 1番目に実行される(image_name=""の状態)
    var image_tag = $("<img id=‘image' src='" + image_name + "'");
    $("#image").remove();    // 古い画像の削除
    $("#image_number").after(image_tag);    // 新しい画像の追加
  });
});
  • php(image_view.php)
<? php
$id = $_POST["id"];
$image_name = "image2.png";  // データベースから次のidの画像名を取得して格納(コード省略)
echo $image_name;
?>

成功例

変えたのはjavascriptのみなので、そちらのみ示す。

$(document).ready(function() {
  $(".next_button").on("click", function() {
    var image_name = “”;
    $.ajax({
      url = "get_image_name.php",
      type: "POST",
      data: {"next_id" : "2"},    // 本当は動的にidを設定したいが、とりあえず今回は手動で。
      success: function(name) {
        alert("success1 :" + image_name);    // 2番目に実行される(image_name=""の状態)
        image_name = name;
        alert("success2 :" + image_name);    // 3番目に実行される(image_name="image2.png"の状態)
        var image_tag = $("<img id='image' src='" + image_name + "'");    // add
        $("#image").remove();    // 古い画像の削除                        // add
        $("#image_number").after(image_tag);    // 新しい画像の追加       // add
      }
    });
    alert(“image_name = “ + image_name);    // 1番目に実行される(image_name=""の状態)
    // delete : var image_tag = $("<img id=‘image' src='" + image_name + "'");
    // remove : $("#image").remove();    // 古い画像の削除
    // remove : $("#image_number").after(image_tag);    // 新しい画像の追加
  });
});