ColdFusion-開発効率を求められる今だから知りたい高性能Webアプリケーションサーバー

第4回ColdFusionでグラフを描く

第3回目の記事ではColdFusion 8付属のサンプルデータベースにクエリーを発行し、それをHTMLのテーブルに表示する例をご紹介しました。

まず、ColdFusionではデータソースという単位でデータベースへの接続を管理していることを学びました。そのため、CFMLテンプレート上にデータベースへの接続情報(アカウント情報など)を記述する必要が無く、データベースへの接続アカウント漏洩のリスクを減らせることが分かりました。また、データソースはColdFusion Administrator上で集中管理されているため、ColdFusion Administrator上で設定内容を変更すれば、そのデータソースを使っているクエリーの発行先を一括で変更できることが分かりました。データベースサーバーのIPアドレスやアカウント情報が変更になった際も面倒無く移行できることでしょう。

また、ご存じの通りCFMLはHTMLと非常に親和性が高いため、PHPのSmartyやPerlのTemplate Toolkitなど、どのテンプレートエンジンよりもHTMLと相性良く共存させることができ、テンプレートのメンテナンスのしやすさに貢献していることが分かりました。

そして、cfdumpタグを学びました。cfdumpタグでは、ColdFusion上のあらゆるオブジェクト(配列、構造体、オブジェクト、クエリーなど)を整形した形で表示してくれるため、オブジェクトの中身が分からず困った場合は、とりあえずcfdumpしてみると良いでしょう。

今回は、ColdFusionでグラフを描画する例をご紹介します。

ColdFusionではグラフ描画もタグベース

PerlやPHPなどでグラフを描画しようと思った場合、一般的にはGDなどの画像操作プログラムを導入し、その上でラッパーライブラリー経由でGDを操作し、グラフを描画します。その際、多数のメソッドを呼び出したり、グラフのデータを配列に格納するなど、おおよそ直感的とは言い難い操作が伴います。そのため、PerlやPHPなどでのグラフ描画は面倒なものとなっています。

それに対して、ColdFusionではクエリー操作をカプセル化しているcfqueryタグと同様に、cfchartタグにグラフ描画機能がカプセル化されています。あたかもHTMLのtableタグを用いて表を描画するのと同じような感覚で、棒グラフや円グラフを描画することができます。もちろんGDなどの外部プログラムをインストールする必要はありません。

簡単なグラフを描画してみる

それでは簡単なグラフを描画してみましょう。

まず手始めに、以下のような静的なデータの折れ線グラフを描画してみましょう。

1月2月3月4月5月
売上20,000円18,000円25,000円23,000円30,000円
費用8,000円10,000円14,000円13,000円16,000円

コードは以下のようになります。{cf_root}フォルダ({cf_root}はColdFusionをインストールしたディレクトリです。Windowsでは『C:\ColdFusion8』になります)内にある『wwwroot』の中に『gihyo』という名前のフォルダを作り、その中に『4』というフォルダを作ってください。⁠4』のフォルダの中に以下のような中身のファイルをcfchart1.cfmとして保存してください(ファイルのパスは{cf_root}/wwwroot/gihyo/4/cfchart1.cfmになります⁠⁠。なお保存時の文字コードはUTF-8としてください。

<cfprocessingdirective pageEncoding="UTF-8" />
<cfcontent type="text/html; charset=UTF-8">
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<title>売上と費用</title>
<cfchart format="flash" chartheight="200" chartwidth="440" font="arialunicodeMS" yAxisTitle="円" scaleTo="35000" showLegend="true">
    <cfchartseries type="line" seriesLabel="売上">
        <cfchartdata item="1月" value="20000">
        <cfchartdata item="2月" value="18000">
        <cfchartdata item="3月" value="25000">
        <cfchartdata item="4月" value="23000">
        <cfchartdata item="5月" value="30000">
    </cfchartseries>
    <cfchartseries type="line" seriesLabel="費用">
        <cfchartdata item="1月" value="8000">
        <cfchartdata item="2月" value="10000">
        <cfchartdata item="3月" value="14000">
        <cfchartdata item="4月" value="13000">
        <cfchartdata item="5月" value="16000">
    </cfchartseries>
</cfchart>
図1 cfchart1.cfmの実行結果
図1 cfchart1.cfmの実行結果

コードの解説をします。

まず、cfchartタグでグラフのエリアを作成します。cfchartタグのformat属性でチャートの画像の出力形式を指定します。⁠flash」の場合Adobe Flash形式、⁠jpeg」ならばJPEGファイル、⁠png」ならばPNGファイルで出力されます。グラフエリアの高さをchartheight属性で、グラフエリアの幅をchartwidth属性で、ピクセル単位で指定します。font属性でチャートに使用するフォントを指定します。グラフ上で日本語を使いたい場合、⁠arialunicodeMS」の指定が必須となります。yAxisTitle属性でグラフのY軸の名前を設定します。scaleTo属性でY軸の最大値を設定します。指定しない場合、データの最大値(今回の場合、売上の30,000円)が自動的にグラフの最大値となります。最後に、showLegent属性にtrueを設定し、凡例を表示するように設定します。

次に、cfchartseriesタグでグラフの項目を作成します。今回の場合「売上」「費用」の2つの折れ線を描く必要があるため、cfchartseriesタグが2つ出てきています。type属性に「line」を指定し、折れ線グラフを描くようにしています。そして、項目名をseriesLabel属性で指定しています。

最後に、折れ線に描くデータをcfchartdataタグで指定しています。item属性で何月かを指定し(X軸の項目名を設定し⁠⁠、value属性でその月の売上または費用を設定しています。

コードをご覧頂いて分かるとおり、HTMLのテーブルをtableタグ、trタグ、tdタグを使って構築するのと同じような感覚でグラフを描画できることが分かると思います(今回の場合、おおよそcfchartタグがtableタグに、cfchartseriesタグがtrタグに、cfchartdataタグがtdタグに相当しています⁠⁠。

今回はcfchartタグのformat属性に「flash」を指定したためAdobe Flash形式のグラフになりましたが、⁠png」を指定すればPNG形式で出力されます。Flash Playerがインストールされていない環境などを考慮する場合は「png」「jpeg」を指定しても良いでしょう。

クエリーのデータを描画する

ColdFusionでは、もちろんクエリーなどの動的なデータも描画することができます。前回の連載で使用したcfartgalleryデータソースのartテーブルに保存されているデータを描画してみることにしましょう。artテーブルの情報は以下の通りです。

列名備考
artIDintプライマリーキー
artistIDintartistテーブルのプライマリーキー値
artNamevarchar商品名
descriptionclob商品の説明
isSoldint商品が売れたかどうか
largeImagevarchar商品の画像へのパス
mediaIDintmediaテーブルのプライマリーキー値
priceint商品の価格

今回は『mediaID』ごとにいくつ在庫があるかをグラフにしてみることにします(isSoldが0の場合、売却が決まっていない在庫になります⁠⁠。以下のコードをcfchart2.cfmとして保存し、実行してみましょう。

<cfprocessingdirective pageEncoding="UTF-8" />
<cfcontent type="text/html; charset=UTF-8">
<!DOCTYPE html PUBLIC "-//W3C/DTD HTML 4.01 Transitional//EN">
<cfquery datasource="cfartgallery" name="qry">
  SELECT
    COUNT(art.artID) AS num, art.mediaID
  FROM
    art
  WHERE
    isSold = 0
  GROUP BY
    mediaID
</cfquery>
<title>メディアIDごとの在庫数</title>
<cfchart format="flash" chartheight="200" chartwidth="440" font="arialunicodeMS" xAxisTitle="メディアID " yAxisTitle="個">
  <cfchartseries type="bar" seriesLabel="在庫" >
    <cfloop query="qry">
      <cfchartdata item="#qry.mediaID#" value="#qry.num#">
    </cfloop>
  </cfchartseries>
</cfchart>
図2 cfchart2.cfmの実行結果
図2 cfchart2.cfmの実行結果

cfloopタグでクエリー(qry)に含まれているデータの個数だけcfchartdataタグを繰り返すようにしています。また、cfchartdataタグのitem属性とvalue属性にはクエリーのデータを渡したいため、シャープマークで囲っていることに注意してください。⁠#qry.mediaID#』『クエリーqryの列名「mediaID」のデータを取り出す』という意味になります。シャープマークで囲わない場合、⁠qry.mediaID」という文字列を渡す』という意味になります。

なお、クエリーのデータをそのまま使う場合、cfchartseriesタグのquery属性に描画対象のデータを含むクエリーオブジェクトを渡し、itemColumn属性でX軸の項目名にするクエリーの列名、valueColumn属性でY軸の値にするクエリーの列名を指定することができます。以下のコードは本質的にcfchart2.cfmと同等です。

<cfprocessingdirective pageEncoding="UTF-8" />
<cfcontent type="text/html; charset=UTF-8">
<!DOCTYPE html PUBLIC "-//W3C/DTD HTML 4.01 Transitional//EN">
<cfquery datasource="cfartgallery" name="qry">
  SELECT
    COUNT(art.artID) AS num, art.mediaID
  FROM
    art
  WHERE
    isSold=0
  GROUP BY
    mediaID
</cfquery>
<title>メディアIDごとの在庫数</title>
<cfchart format="flash" chartheight="200" chartwidth="440" font="arialunicodeMS" xAxisTitle="メディアID " yAxisTitle="個">
  <cfchartseries type="bar" query="qry" itemColumn="mediaID" valueColumn="num" seriesLabel="在庫" ></cfchartseries>
</cfchart>

また、売却済み(isSold=1)のものと購入可能なもの(isSold=0)をグラフ化することもできます。上のコードを元にクエリーをもう一つ発行し、cfchartseriesタグを追加するだけです。以下の例をchchart3.cfmとして保存し、実行してみましょう。

<cfprocessingdirective pageEncoding="UTF-8" />
<cfcontent type="text/html; charset=UTF-8">
<!DOCTYPE html PUBLIC "-//W3C/DTD HTML 4.01 Transitional//EN">
<cfquery datasource="cfartgallery" name="qrySold">
  SELECT
    COUNT(art.artID) AS num, art.mediaID
  FROM
    art
  WHERE
    isSold = 1
  GROUP BY
    mediaID
</cfquery>
<cfquery datasource="cfartgallery" name="qryNotSold">
  SELECT
    COUNT(art.artID) AS num, art.mediaID
  FROM
    art
  WHERE
    isSold = 0
  GROUP BY
    mediaID
</cfquery>
<title>メディアIDごとの在庫状況</title>
<cfchart format="flash" showLegend="true" chartheight="200" chartwidth="440" font="arialunicodeMS" xAxisTitle="メディアID" yAxisTitle="個">
  <cfchartseries type="bar" query="qrySold" itemColumn="mediaID" valueColumn="num" seriesLabel="売約済み" />
  <cfchartseries type="bar" query="qryNotSold" itemColumn="mediaID" valueColumn="num" seriesLabel="購入可能" />
</cfchart>
図3 cfchart3.cfmの実行結果
図3 cfchart3.cfmの実行結果

attributeCollectionでタグに属性をまとめて渡す

cfchartタグやcfchartseriesタグには指定できる属性が多数あります。それらをいちいち指定するのが面倒くさい場合、構造体(他の言語の連想配列に相当します)「属性名=属性値」を設定し、その構造体をattributeCollection属性として渡すことで、個別に属性を指定するのと同じ事ができます。なお、attributeCollection属性はcfchartタグだけでなく、cfqueryタグなど大抵のCFMLタグに渡すことができます。

<cfprocessingdirective pageEncoding="UTF-8" />
<cfcontent type="text/html; charset=UTF-8">
<!DOCTYPE html PUBLIC "-//W3C/DTD HTML 4.01 Transitional//EN">
<cfquery datasource="cfartgallery" name="qry">
  SELECT
    COUNT(art.artID) AS num, art.mediaID
  FROM
    art
  GROUP BY
    mediaID
</cfquery>
<title>メディアIDごとの在庫数</title>
<cfset attrCollection = {format="flash", chartheight=200, chartwidth=400, font="arialunicodeMS", xAxisTitle="メディアID", yAxisTitle="個"}>
<cfchart attributeCollection="#attrCollection#">
  <cfchartseries type="bar" query="qry" itemColumn="mediaID" valueColumn="num"></cfchartseries>
</cfchart>

なお、上の例でattrCollection構造体を作成するのに使用したシンタックスはColdFusion 8から導入されたものです。ColdFusion 8以前で同様のことを使用とした場合、以下のようなCFMLになります。

<cfset attrCollection = StructNew()>
<cfset attrCollection.format = "flash">
<cfset attrCollection.chartheight = 200>
<cfset attrCollection.chartwidth = 400>
<cfset attrCollection.font = "arialunicodeMS">
<cfset attrCollection.xAxisTitle = "mediaID">
<cfset attrCollection.yAxisTitle = "個">

まとめと次回予告

今回はColdFusionでグラフを描画する方法を学びました。他の言語でグラフを描画するにはメソッドを多数呼び出したり、データを配列に入れるなどの繁雑な作業が必要ですが、ColdFusionではcfchartタグ、cfchartseriesタグ、cfchartdataタグを使用し、HTMLのテーブルを作成するのと同じような感覚でグラフを描画できることが分かりました。

また、ColdFusion 8から、多数の属性を渡す必要があるタグについては、⁠属性名=属性値」を持った構造体をattributeCollection属性に渡すことで、多数の属性を指定する手間を省くことができることが分かりました。

次回は、HTMLのフォームなどから渡された値をColdFusionで処理する方法を学びます。

おすすめ記事

記事・ニュース一覧