PHPプロ!TIPS+

1. 関数とバイナリセーフ

関数の中にはバイナリデータを正しく扱うことが出来る関数(バイナリセーフ)とそうではない関数があります。これを把握しておかないと、思わぬところでバグを発生させかねません。今回はその中でも正規表現によるマッチングに焦点を当てます。

正規表現によるマッチング関数にpreg_matcheregがあります。前者はPerl互換性、後者はPHPのPOSIX互換性正規表現関数です。これらは入力値をフィルターするときにしばしば用いられます。しかし、eregには落とし穴が存在します。

その落とし穴とは「ereg関数はバイナリセーフではない」ということです。例えば、ユーザ入力をフィルタリングするスクリプトを考えてみましょう。

if (ereg('^[0-9A-Za-z_]+$', $_POST['login_id'])) {
// 正しい入力に対する処理
}

ここでの目的はポストされたlogin_idが半角英数、アンダーバーのみで構成されているか確認することです。一見、何の問題もないように思われます。しかし、$_POST['login_id']にヌルバイト文字(\0)を入れられると、このフィルタリングは意味を持たなくなります。ためしに

$_POST['login_id'] = "abc\0 -** 1 **-";

としてみて下さい。ereg関数はtrueを返し、if内部のスクリプトが実行されたと思います。この原因はereg関数がヌルバイト文字の直前までしかマッチングを行わないことにあります。つまり、バイナリセーフな関数ではないため、ヌルバイト文字で文字列が終了したとみなしてしまいます。このような場合にはeregではなくpreg_matchを用いて下さい。

ただし、これはmb_ereg系には当てはまりません。名前は似ていますが、これらはバイナリセーフな関数です。また、preg系の関数ではその代わりになりえません。

以上の様に、入力値に対してバイナリセーフではない関数を用いる場合には注意が必要です。特に正規表現関数の使い所には気を付けて下さい。

他のバイナリセーフではない関数の一部

ereg_replace(), eregi(), eregi_replace(),
split(), spliti(),
include(), include_once(), require(), require_once()
fopen(), file_get_contents(), readfile(), basename()

2. グラフ生成ライブラリの紹介(1)

Webサイトを構築していると、サイトの運営状況やアクセス数の管理など、さまざまな場面でグラフを使用する必要が出てきます。自分でグラフの描画を行うスクリプトを1から作るのは非常に大変ですが、Web上には公開されているグラフ描画ライブラリが数多く存在します。今回はその中から7つのグラフ生成ツールを紹介したいと思います。ここでは各ライブラリを使用して、最もシンプルな棒グラフの生成方法を紹介します。

前編後編に分けて紹介し、前編ではPEAR::Image_Graph、JpGraph、PHP/SWFCharts、HTML-GRAPHs(PHP)を紹介します。

・PEAR::Image_Graph  http://pear.veggerby.dk/

PEARのグラフ生成ライブラリです。オープンソースのグラフ描画ライブラリ GraPHPite を元に作成されています。PEAR::Image_Graphを使用するには、PEAR::Image_Canvas、PEAR::Image_Colorが必要です。また、オプションとしてPEAR::Number_RomanとPEAR::Number_Wordsが使用可能です。

現在14種類のグラフに対応しており、ほとんどの属性のカスタマイズが可能です。 PHP4・PHP5に対応しています。グラフの生成方法は以下のようになります。

image_graph.php
<?php
require_once 'Image/Graph.php';

$Graph =& Image_Graph::factory('graph'array(400300));
$Plotarea =& $Graph->addNew('plotarea');
$Dataset =& Image_Graph::factory('dataset');

$month_list array("Jan""Feb""Mar""Apr""May""Jun""Jul",
"Aug""Sep""Oct""Nov""Dec");
foreach (
$month_list as $month) {
    
$Dataset->addPoint($monthrand(1,30));
}

$Plot =& $Plotarea->addNew('bar'$Dataset);
$Plot->setFillColor('green@0.1');
$Graph->done();

?>

あとはこのスクリプトをHTMLの<img>タグのsrc属性に指定して読み込むだけです。

・JpGraph  http://www.asial.co.jp/jpgraph/

スウェーデンのAditus社が製作しているグラフ生成ライブラリです。 日本ではアシアル株式会社がローカライズ・販売しています。

20種類以上の形式をサポートし、プロフェッショナル版を購入するとさらに5種 類の形式が使用可能です。商用目的の場合はプロフェッショナル版のライセンスを購入する必要があります。キャッシュ機能を備え、負荷の高いアプリケーションでも使用することができます。PHP4・PHP5に対応しています。グラフの生成方法は以下の通りです。

jpgraph.php
<?php
include ("jpgraph/src/jpgraph.php");
include (
"jpgraph/src/jpgraph_bar.php");

$month_list $gDateLocale->GetShortMonth();

for( 
$i=0$i<12$i++) {
    
$datay[] = rand(1,30);
}

$graph = new Graph(300,200,'auto');
$graph->SetScale("textlin");
$graph->xaxis->SetTickLabels($month_list);

$plot = new BarPlot($datay);
$graph->Add($plot);
$graph->Stroke();

?>

あとはImage_Graphと同様に<img>タグのsrc属性に指定して読み込みます。

・PHP/SWF Charts  http://www.maani.us/charts/index.php

PHPでスクリプトを記述し、FLASH形式でグラフを出力するという変り種のグラフ生成ライブラリです。FLASHを使用しているだけあって、非常に見栄えが良く、視覚効果に富んだグラフを簡単に生成することができます。

開発者はライセンスを購入する必要はありませんが、サイトの運営者はライセンスを購入するか、グラフのリンク先をPHP/SWF ChartsのWebサイトに設定しておく必要があります(デフォルトで設定されています)。グラフの生成方法は以下のようになります。

phpswfcharts.php
<?php
include "charts/charts.php";
    
$chart 'chart_data' ] = array (
    array ( 
"",         "Jan""Feb""Mar""Apr""May""Jun""Jul",
"Aug""Sep""Oct""Nov""Dec" ),
    array ( 
"example",  1,2,3,4,5,6,7,8,9,10,11,12)
);

SendChartData $chart );

?>

次にこのスクリプトを表示するPHPスクリプトから読み込みます。

<?php
include "charts/charts.php";
echo 
InsertChart "charts/charts.swf""charts/charts_library",
"phpswfcharts.php" );
?>

FLASHを表示する<object>タグ自体をInsertChart関数で出力するためこのような 実装方法になります。表示する値と各タイトルを一つの配列内に収めなければならない点はちょっと面倒な気もします。

・HTML-GRAPHs(PHP)  http://www.gerd-tentler.de/tools/phpgraphs/

画像ではなくHTMLでグラフを出力するライブラリです。ライブラリ自体が1ファイルだけで構成されており、非常にシンプルなのでそれほど凝ったグラフは生成できないようですが、とりあえず素早くグラフを作成したいという時は重宝するでしょう。

付属のreadme.txt、ライブラリ本体のgraphs.inc.phpには簡単な設定方法が記載されているので、これ見ながらサンプルスクリプトをいじればなんとなく作れてしまいます。 現在棒グラフとフェーダーグラフのみが作成できます。

基本的にフリーで使用することができますが、開発は寄付で賄われているため、商用利用の場合は6ユーロ以上の寄付をしてほしいとのことです。グラフの作成方法は以下のようになります。

html_graphs.php
<?php
include_once("Html_Graphs/graphs.inc.php");
$graph = new BAR_GRAPH("vBar");

foreach (
range(1,12) as $value) {
    
$data[] = rand(1,30);
}

$month_list array("Jan""Feb""Mar""Apr""May""Jun""Jul",
"Aug""Sep""Oct""Nov""Dec");

$graph->values $data;
$graph->labels $month_list;
echo 
$graph->create();
?>

最後の$graph->create()でHTMLが出力されるため、<img>タグなどには含めずそのまま出力する必要があります。

3. グラフ生成ライブラリの紹介(2)

後編では、Chart Usage(WebFX)、CSS FOR BAR GRAPHS(Apples To Oranges)、Artichowを紹介します。

・Chart Usage(WebFX)  http://webfx.eae.net/dhtml/chart/usage.html

最初は、JavaScriptのみを使用してグラフを生成してしまうライブラリです。 全ての処理をクライアント側で行うため、グラフを表示するだけならサーバー側のスクリプトは必要はありません。あらかじめ必要なjsファイル、CSSファイルを読み込んでおき、グラフを出力したい場所にid付きの<div>タグを設置しておきます。

以下の例では id="chart" の<div>タグ内にグラフが表示されます。現在このライブラリは、Apache Software License 2.0 に基づいて自由に使用することができます。 基本的な作成方法は以下のようになります。

<script type="text/javascript" src="chart/includes/excanvas.js"></script>
<script type="text/javascript" src="chart/includes/chart.js"></script>
<script type="text/javascript"
src="chart/includes/canvaschartpainter.js"></script>
<link rel="stylesheet" type="text/css"
href="chart/includes/canvaschart.css" />

<div id="chart" class="chart" style="width: 400px; height: 200px;"></div>

<script type="text/javascript">
function draw() {
    var c = new Chart(document.getElementById('chart'));
    var data = new Array(1,2,3,4,5,6,7,8,9,10,11,12);
    c.setDefaultType(CHART_BAR);
    c.setGridDensity(12, 5);
    c.setBarWidth(10);
    c.setBarDistance(0);
    c.setShowLegend(false);
    c.setHorizontalLabels(['', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']);
    c.add('', 'blue', data);
    c.draw();
}
draw();
</script>

HTML-GRAPHs(PHP)やWebFXは画像を出力する形式ではないので、JavaScriptと組み合わせれば凝った仕掛けが導入できるかも知れません。

・CSS FOR BAR GRAPHS(Apples To Oranges) http: //applestooranges.com/blog/post/css-for-bar-graphs/

次はライブラリではなく、CSSを使ったテクニックでグラフを描画する方法です。CSSを使用しているため、スクリプトファイルは何も用意する必要がありません。とは言いながら、実はグラフの背景画像、プロットの元画像が必要になります。このままではそれほど多くの場面で活用できそうにはありませんが、とりあえずグラフが表示したいという場面では役に立つかもしれません。CSSのテクニックの一つとして頭に入れておくとよいでしょう。コードは以下の通りです。

<style>
    #vertgraph {
        width: 378px;
        height: 207px;
        position: relative;
        background: url("css_graph/g_backbar.gif") no-repeat;
    }
    #vertgraph ul {
        width: 378px;
        height: 207px;
        margin: 0;
        padding: 0;
    }
    #vertgraph ul li {
        position: absolute;
        width: 28px;
        height: 160px;
        bottom: 34px;
        padding: 0 !important;
        margin: 0 !important;
        background: url("css_graph/g_colorbar3.jpg") no-repeat !important;
        text-align: center;
        font-weight: bold;
        color: white;
        line-height: 2.5em;
    }

    #vertgraph li.critical { left: 24px; background-position: 0px bottom
!important; }
    #vertgraph li.high { left: 101px; background-position: -28px bottom
!important; }
    #vertgraph li.medium { left: 176px; background-position: -56px
bottom !important; }
    #vertgraph li.low { left: 251px; background-position: -84px bottom
!important; }
    #vertgraph li.info { left: 327px; background-position: -112px bottom
!important; }
</style>
<div id="vertgraph">
 <ul>
  <li class="critical" style="height: 150px;">22</li>
  <li class="high" style="height: 80px;">7</li>
  <li class="medium" style="height: 50px;">3</li>
  <li class="low" style="height: 90px;">8</li>
  <li class="info" style="height: 40px;">2</li>
 </ul>
</div>

・Artichow  http://www.artichow.org/

フランス製のグラフ生成ライブラリです。フランス語が読めないので詳細についてはほとんどわかりません。PHP4・PHP5に対応し、10種類ほどのグラフ形式が描画できるようです。examples/内にサンプルスクリプトがたくさん入っているので、ドキュメントが読めない方はこちらを参考にしましょう。

スクリプト内を見ると中身のないメソッドも多く、まだ開発段階という印象を受 けますが、ライセンス形態は public domain となっています。 スクリプトは以下のように記述します。

<?php
require_once "Artichow/BarPlot.class.php";

$graph = new Graph(400400);
$graph->setAntiAliasing(TRUE);

$values array(19215103322316313215);
$month_list array("Jan""Feb""Mar""Apr""May""Jun""Jul",
"Aug""Sep""Oct""Nov""Dec");

$plot = new BarPlot($values);
$plot->setBarColor(    new Color(5050180));
$plot->xAxis->setLabelText($month_list);

$graph->add($plot);
$graph->draw();
?>

これを<img>タグから呼び出すことになります。

ここで紹介したもの以外にも多くのグラフ作成ライブラリがあります。これらを試して自分好みのライブラリを見つけてみてはいかがでしょうか。

※なお、上記の各ライブラリで実際に表示した サンプルがこちらhttp://www.phppro.jp/phptips/sample/graph/です。

バックナンバーについて

TIPS-MLは、毎週金曜日に更新され、新しい記事が掲載されます。

Tipsꗗy[W 

Pick Up Q&A

Q
PHPのHTML埋め込み記述について
 このエントリーをはてなブックマークに追加 
A
$_POST["data"] == "男" ? $val = "checked" : $val = "" ; の意味は以下と同じです。 if($_POST["data"] == "男"){ $val = "checked; } e...

>>続きを読む

kende様のご指摘通り、三項演算子を使用する際には、コードの複雑度などを考慮する必要がありますね。書きやすさと共に可読性も追求したいところですね。

▲解説者:岡本(アシアル株式会社 教育コーディネーター兼 システムエンジニア)