ホーム < ゲームつくろー! < IKD備忘録

サーバ
MySQLを試してみる


 LAMP構成の「M」にあたるMySQLは、いわゆる「データベース管理」をしてくれるソフトウェアの一つです。「データベース」というのは沢山のデータ、つまり情報や値が集まった物です。でも、ただ単にかき集めただけで整理されていないと、その情報が欲しい時になかなか見つかりません。それでは不便なのでちゃんと管理しましょう、というのがデータベース管理、すなわちMySQLなんです。

 データベース管理ソフトを使うと、大量のデータから欲しいデータを効率よく抽出して取りだす事ができます。PHPはMySQLと連携しやすいようです。では実際にどう使うかを調べます。



@ MySQLがちゃんと入ってる?

 MySQLがUbuntuにちゃんとインストールされているかを調べるには、端末から、

mysql

とコマンドを打ち込みます。すると、

とインストールされているMySQLに関するバージョン情報などが出力されます。その後のカーソルに注目すると「mysql> 」となっていますので、実はもうMySQLが起動されています。MySQLを終了させるには、

quit

とコマンドを入れます。「Bye」と表示が出てMySQLが終了します。



A データベースを作ってみよう

 MySQLの中では沢山のデータが管理されます。その大きなくくりを「データベース」といいます。例えばアイテムの情報についてのデータベースとか、プレイヤーの情報をまとめたデータベースなど、特定の項目についてまとめたものがデータベースです。

 インストールしたてのMySQLの中にはもちろん自分のデータベースが一つも入っていません。そこで、新しいテスト用のデータベースを一つ作ってみましょう。ゲームをするプレイヤーの情報である「player」データベースを作ります。新しいデータベースを作るにはMySQLが起動されている状態から、

create database player

と打ち込みます。Enterを押すと、

ん?特に何の反応も無く次の行にいった感じ?これは実はまだコマンドの続きを受け付けている状態、別の言い方をすれば今打ったコマンドがまだ受理されていない状態です。ここは最初コマンドを打ち込んだ時に「?」となった所でした。MySQLは打ち込んだコマンドの最後に「;」とセミコロンを付ける必要があるんです。先のコマンドはそれが抜けていたので、単に改行が入っただけ、「コマンドまだ終わって無いから、続きをどうぞ」と言われているわけです。ここでセミコロンを入れるとうまくいく…と思ったのですが、

と何やらエラーが出てしまいました。え〜と「データベース'player'に対してユーザ' @localhost'のアクセスが拒否されました」。ん〜と、多分今の自分にMySQLに対して変更とかアクセスする許可が無いってことかなと思います。調べてみます。

 あ、どうやらmysqlを起動する時にユーザ名とパスワードを入れないと駄目なようです。インストールした時に「root」のパスワードを登録しましたが、ここで使うようです。仕切り直して、mysqlにrootさんで入ります:

mysql -u root -p

-uの後にユーザ名を入れます。-pとするとEnterした後にパスワード入力を促されます。ほいほいと入れると…とりあえずmysqlに入れました。改めて、

create database player;

と入れると…:

よ〜し、新しいデータベース「player」が出来たようです。確認するには、

show databases;

です。最後の「s」、複数形の「s」、忘れると慌てます(^-^;:

こう見ると、すでに何らかのデータベースがデフォルトで出来ているんですねぇ。先ほど追加した「player」ももちろんあります。ちなみに、データベースを削除するには、

drop database player;

などdrop databaseコマンドを使うようです。



B playerデータベースにテーブルを設定

 playerデータベースをMySQL内に追加できました。でもこの段階だとデータベース内は空っぽ。しかも、ここに情報(データ)を入れるにも、どんなデータを入れるかわかりません。管理するという事はそこに「ルール」を定める事です。MySQLにデータを入れるには「テーブル」という表を作ります。

 テーブルはExcelの表ととても近しいイメージがあります。例えばこんな表を作りたいなぁ〜と考えます:

id、nameそしてhandlenameの3つの項目があって、それぞれに対応した値が入っています。playerデータベース内にこのような表のデータを追加するには、まず最初に登録先のデータベースを選択します。これには、

use player;

と「use」コマンドを使います。これでデータベースが選択されたので、続けて次のようなコマンドを入力します:

create table Information ( id int, name varchar(128), handlename varchar(128) );

create tableコマンドで新しいテーブルを作る事を宣言します。続けてテーブル名、これは他とかぶらなければ何でもOK。続く括弧の中が上の項目名にあたります。項目名の後に「int」とか「varchar(128)」など型も宣言する必要があります。intは整数型でvarcharは文字列かな。こうしてEnterすると、新しいテーブルがplayerデータベースの中に作られます。確認するには、

show tables in player;

というコマンドを入れます。すると:

とデータベース内にあるテーブルを確認する事ができます。うまくできているみたいですね。

 では続いて、このテーブルに先程のデータを登録していきます。テーブルにデータを登録するにはinsert intoコマンドを使います。例えば先の表の「0, まるぺけ まる男, IKD」という1レコードならば、

insert into Information
(id, name, handlename)
values( 0, 'まるぺけ まる男', 'IKD');

という一文を入力します(セミコロンが3行目にあるので1文です)。insert intoの後にはデータを追加したいテーブル名、その後ろに括弧をつけて項目名の一覧、そしてvaluesに続けて値を記述します。数字はそのままで良いのですが、文字列はシングルクォーテーションで括る必要があります。項目名を逐一指定するのは、特定の項目だけ登録できたり、項目の順序が入力時に入れ替わっている場合などにちゃんと対処できる仕組みになっているためです。同様に3レコード分追加していきます。

 テーブルの中身を確認(抽出)するにはselectコマンドを次のように使います:

select id,name,handlename from Information;

するとこんな感じにテーブルの中身が一覧で表示されます:

おっと、ここで大きなトラブル発生。上の表の「???」の部分は日本語の文字列ですが、これがうまく表示できていないみたいです。これは「文字セット」が日本語対応になっていないためです。現在のテーブルに指定されている文字コードを確認してみましょう。

 データベース内のテーブルの文字コードを確認するには、

show create table [table名];

というコマンドを入力します。すると、

見ずれぇ(笑)。まぁ、それは置いておき、上の真ん中行辺りにある「Information」というのがテーブル名で、その中身が「id, name, handlename」という項目(カラム)で構成されているのが分かります。nameカラムとhandlenameカラムは文字列で、そこに文字コードが見当たりません。これは「テーブルのデフォルト文字コードを使っています」という事を表しています。で、そのテーブルのデフォルト文字コードは、上の赤線で示した部分に表示されています。これを見ると、Informationテーブルのデフォルト文字コードは「latin1」のようです。日本語文字コードとするには「utf8」であって欲しいわけです。

 テーブルの文字コードを変更するには、

alter table [table名] covert to character set [文字コード名];

とします。上の場合はInformationテーブルの文字コードをurf8にしたいので、

alter table Information covert to character set utf8;

とすると…:

赤線部分がlatin1からutf8に変更されました。これで、テーブル側はOK。

 ただ、この段階でテーブルの文字列を表示させてみても「???」という表示は変わりません。先程のコマンドはテーブルの文字コードを変更するだけで「テーブルに登録されている文字列」の文字コード自体をコンバートしてくれないためです。そりゃそうだ(^-^;。そこで、今テーブルに登録されている文字列を改めて登録し直す事にしました。

 まず、今のテーブルをクリアします。テーブルをクリアするには、

truncate table [テーブル名];

とすると無条件で消されます。これはトランザクション(履歴のようなものです)を残さない消し方です。先のInformationテーブルをこの方法でさくっと消して、改めて表の項目を入れ直しました。すると、:

ほっ(^-^)。順番が違うのは、入力間違いしたから、はは(^-^;;。
MySQLを扱う時には、テーブルのカラムの「型」や文字コードは完全に設定しておかないといけないという事ですね。

 さてここからが本番。MySQLにあるテーブルをクライアント側から呼び出すわけです。



C PHPからMySQLにアクセスする

 先程はMySQLにあるテーブルを端末から操作していました。MySQLがサーバだとすると、端末はクライアントに当たるわけです。しかし、実際に端末から直接MySQLを触れる人なんて管理者くらいなもんで、ほとんどは外部の人が何らかの要求を出してMySQLへアクセスします。PHPを使うとそういう事ができる、そんな事を聞きました。でも、まだ「へぇ…」という段階です(^-^;。実際にやってみます。

 LAMP構成を作り、MySQLにデータベース(player)を作り、そこにInformationテーブルを作った、この状態から次に何をするか?PHPファイルを作ります。次のようなコードです:

test.php
<?php
    $link = mysql_connect( "localhost", "root", [パスワード] );

    if ( $link )
        print( "Connected to MySQL !" );
    else
        printf( "Failed..." );

    mysql_close( $link );
?>

Ubuntuでテキストファイルを作る方法は様々だと思いますが、デフォで良いならgeditで十分です。ただし「管理者権限」でgeditを起動する必要があります。そうしないと殆どのフォルダに保存できず面倒な事になります。管理者権限でgeditを開くには、端末から、

sudo gedit

と打ち込むだけです。

 上のコードを記述したら「/var/www」フォルダに保存します。なぜここか?このPHPコードにたどりつく経路を考えてみましょう。このコードを実際に動かすためには、ブラウザでこのファイルを直接指定する必要があります。サーバ内であれば別にどこでも良いのですが、外部からアクセスするとなると当然URLとかIPアドレスで指定する事になります。例えば「http://192.168.0.6/test.php」のように。このURLを解釈するのはapache君です。apache君のルートフォルダパスはデフォルトで/var/wwwとなっていて、先のURLのドメイン部分「http://192.168.0.6/」をこのデフォルトパスに置きかえるんです。そのためtest.phpは/var/wwwに保存する必要があります。

 上のPHPのコードはMySQLに接続して、成否をメッセージとして画面に出して接続を解除するという簡単なコードです。mysql_connect関数が接続関数で、第1引数にアドレス、第2引数にMySQLのユーザ名、第3引数にそのパスワードを渡します。今はPHPコードとMySQLが同じPC内にあるとしているのでアドレスはlocalhostでOKです。ユーザはrootとなっていますが、これはちゃんとアクセス保護をしたユーザにした方が良いそうです。…それはまたいずれ(^-^;。接続するとMySQLへアクセスする事ができますが、欲しい情報を取得したらすぐにmysql_close関数で接続を切った方が良いと思います。

 さて、では実際にブラウザからこのtest.phpを呼び出してみましょう!せっかくなので別のローカルPCからChormeさんでアクセスです:

え〜〜…orz。

 ん?あ、そりゃそうです。apache君が動いていません(^-^;。え〜と、Ubuntuの端末から次のようにapache2の状態を確認します:

sudo /etc/init.d/apache2 status

すると、

あ〜。という事でapache2君を起動です:

sudo /etc/init.d/apache2 start

これで改めて先程のtest.phpを指定してみます:

出たー!接続できたようです。


D テーブルの情報を取得してみる

 では、さらにテーブルに登録してある情報を取得してみます。こんなコードです:

test.php
<?php
    $link = mysql_connect( "localhost", "root", [パスワード] );
    if ( $link )
        print( "Connected to MySQL !" );
    else
        print( "Failed !!" );

    // テーブルの情報を列挙
    mysql_select_db( "player", $link );
    $result = mysql_query( "SELECT * FROM Information", $link );
   
    while( $item = mysql_fetch_array($result) )
        echo( $item['id'].": ".$item['name']." (".$item['handlename'].")" ); mysql_free_result( $result );
   
    mysql_close( $link );
?>

 mysql_select_db関数はmtsql_connect関数で取得したMySQL($link)に登録されているデータベースを選択する関数です。端末上で「use player;」としたのと同じ事です。これでデータベースがplayerになったので、続いてmysql_query関数でデータベースに対して情報取得を要求します。第1引数にSQL文という抽出条件を表すスクリプト文字列を渡すと欲しい情報を返してくれます。上の例は、まず「SELECT」が「抽出して下さい」という命令、続く「*」は全項目が対象であるワイルドカードで、FROM [テーブル名]が抽出対象テーブルです。つまり上のSQL文は「Informationテーブルの全項目(id, name, handlename)の全レコードを下さい」と言っているわけです。

 各レコードを取りだすにはmysql_fetch_array関数を使います。この関数は第1引数にqueryした結果を受け取り、そこからレコードを1つずつハッシュとして返してくれます。呼び出す度に次のレコードを返し、無くなったらFalse(Nullかな?)が返ります。上の$itemはハッシュ変数になるため、続くecho関数(文字列を出力する関数)にあるように$item['id']のように項目名を指定すると、それに対応した値が取り出せます。PHPで文字列を連結する時には「+」ではなくて「.(コンマ)」です。これ、JavaScriptとかC++のstringなどで癖付いている人ははまるんですよねぇ〜(自分…)。

 さて、このコードをChrome君で呼び出してみましょう:

え〜〜微妙〜orz。
確かにidとかnameとかhandlenameといった項目は出ているっぽいのですが、日本語部分がことごとく文字化けです。FireFoxでも見てみます:

同じだぁ…。これはブラウザに文字コードの情報がちゃんと渡されていないのが原因のようです。考えてみたら作成したPHPって文字コードについて何も情報を提供していません。Chromeは文字コード設定が無いとデフォルト(Shift-JIS?)で開いてしまうためこうなったと考えられます。そこで先程のコードに「UTF8で送信してね〜」というコードを付け加えます:

test.php
<?php
    header("Content-type: text/html; charset=UTF-8");

    $link = mysql_connect( "localhost", "root", [パスワード] );
    if ( $link )
        print( "Connected to MySQL !" );
    else
        print( "Failed !!" );

    // テーブルの情報を列挙
    mysql_query( "SET NAMES utf8" );
    mysql_select_db( "player", $link );
    $result = mysql_query( "SELECT * FROM Information", $link );
   
    while( $item = mysql_fetch_array($result) )
        echo( $item['id'].": ".$item['name']." (".$item['handlename'].")" ); mysql_free_result( $result );
   
    mysql_close( $link );
?>

headr関数はHTMLのheaderに相当する文言を送信してくれます。上ので重要なのが「charset=UTF-8」の部分。これが無いとブラウザが判断する適当な文字コードで表示されてしまうわけです。中ほどにあるmysql_query( "SET NAMES utf8" )は、クライアントにUTF8で送信して下さいね〜という命令です。これらを施すと:

やりました〜〜。ちゃんと登録した順にテーブルの情報が取れています。文字コードを適切に設定して送信するのがMySQLには大切なんですね。



E ポイントまとめ

 ここまで右往左往したものの、PHPを通してブラウザ上にMySQL内の情報を表示させる事ができました。全体のポイントをまとめます:

・ MySQLのテーブルを作る時には文字コードを確実に決める!これ絶対!UTF8がお勧め。
・ apacheがデフォルト設定なら、phpファイルは/var/wwwフォルダ以下に保存。
・ php内でheaderをちゃんと送信。charaset=UTF-8で文字コードを指定する事。
・ mysql_query( "SET NAMES utf8" )でクライアントにUTF8で送信する指定を。

 これでLAMP構成を最低限ですが一回り出来ました。では、実際にゲームっぽい事をやり始める事にします!