PHPプロ!TIPS+

1. O/Rマッパー - EZPDO

皆さんはPHPのプログラムからデータベースのレコードへアクセスする場合、普段はどうされていますか?やはりSQL文を直接使っている方が多いでしょうか。

オブジェクトリレーショナルマッピング(O/Rマッピング)を使うと、データベースのレコードをオブジェクトのように扱うことができ、SQL文を直接書くことなくアクセスできるようになります。

PHP用のO/Rマッパーとしては、古くはPEARライブラリのDB_DataObject、最近有名なものとしてはsymfonyフレームワークにて採用されているPropelなどがありますが、今回は日本ではあまり馴染みがないと思われるEZPDOをご紹介したいと思います。

EZPDOは、その名前「Easy PHP Data Objects」が示すように、簡単に使えることを目指したO/Rマッパーです。

まずは、

  http://www.ezpdo.net/releases.php

からダウンロードしましょう。執筆時の最新の安定版は1.1.6になります。

無事ダウンロードが終わったら、好きな場所でファイルを展開します。

  $ tar xzvf ezpdo.1.1.6.tar.gz

それでは、早速付属のサンプルプログラムを動かしてみましょう。まず、booksディレクトリへ移動します。

  $ cd ezpdo.1.1.6/examples/books/

今回はMySQLで試してみようと思いますので、config.iniのdefault_dsn編集します。

  $ vi config.ini

  ; The default DSN to the database you want to store your objects
  ; This will be the default DSN for classes that do not have DSN specified
  ; default_dsn = sqlite://books.db
  default_dsn = mysql://ユーザ名:パスワード@ホスト名/ezpdo_ex
  ; default_dsn = pgsql://ezpdo_ex:pdoiseasy@localhost/ezpdo_ex

次に、使用するデータベースを作成します。

  $ mysql -u ユーザ -p パスワード -h ホスト名
  mysql> create database ezpdo_ex;
  mysql> Bye

準備が整いましたので、データベースにレコードを登録するプログラムと登録内容を表示するプログラムを実行してみましょう。

  $ php add.php
  $ php print.php
  $ php find.php

それぞれのソースコードを見てみると、SQL文が書かれていませんが、データベースへアクセスできているようです。

今度は、実際にデータベースを覗いてみましょう。

  mysql> use ezpdo_ex;
  mysql> show tables;
  +--------------------------------+
  | Tables_in_ezpdo_ex             |
  +--------------------------------+
  | ezpdo_Author                   |
  | ezpdo_Book                     |
  | ezpdo__ez_relation_author_book |
  +--------------------------------+

SELECT文で各テーブルの内容を確認すると、ezpdo_Authorとezpdo_Bookへそれぞれのレコードが登録され、ezpdo__ez_relation_author_bookへAuthorとBookのリレーション情報が入っているのが見て取れると思います。

特に設定ファイルなどは見当たりませんが、どうやって実現しているのでしょうか? では、classes/Author.phpを見てみましょう。

  /**
   * Name of the author
   * @var string
   * @orm char(64)
   */
  public $name;

その秘密は、これらのコメント行に書かれている「@orm」というカスタムタグになります。

このタグへデータの型やリレーションの定義を記述し、m:n(Many to Many)のリレーションなどを実現しています。

このようにSQL文を書くことなく簡単にデータベースへアクセスできるEZPDO、機会がありましたら使ってみては如何でしょうか。

2. 重い処理をバックエンドで実行する

PHPのプログラム内に重い処理を実行する部分がある場合、普通はその処理が終わるまでプログラムは先に進みません。でも、処理だけさせておいて、プログラムを先に進めたい場合もあると思います。

今回は、そんな重い処理をバックエンドで実行させる簡単な方法をご紹介します。このやり方はLinux/Unix環境で使えます。

時間がかかるスクリプトの例(test.php)
<?php
/* POSTされた時に、時間がかかる処理が走る。ここでは何もせずに10秒ストップ*/
if ($_POST['submit']) {
  
sleep(10);
  echo 
'finish!';
} else {
?>
<html>
重い処理が走るスクリプト
<form method="post" action="test.php">
<input type="submit" name="submit" value="重い処理を実行">
</form>
</html>
<?php
}
?>

このスクリプトにアクセスしてボタンを押すと、10秒たたないとfinish!の文字が表示されません。

そこで、処理の部分を別プログラムに分けます。

重い処理を行うスクリプト(/path/to/exec.php)
<?php
sleep
(10);
?>

待たされないスクリプト(test2.php)
<?php
if ($_POST['submit']) {
  
exec("/usr/local/bin/php /path/to/exec.php > /dev/null &");
  echo 
"とりあえず finish!";
} else {
?>
<html>
重い処理が走るけれど、待たされないスクリプト
<form method="post" action="test2.php">
<input type="submit" name="submit" value="重い処理を実行">
</form>
<?php
}
?>

exec関数を使って、プログラム内でさらにコマンドラインでPHPのプログラムを実行します。

コマンドの最後に「 > /dev/null &」をつけるのがポイントです。exec関数引数の、/usr/local/bin/phpと、/path/to/exec.phpは環境に応じて正しくパスを指定する必要があります。

処理を実行するスクリプトに引数を渡して使う場合は、次のようにします。

引数を受け取って重い処理を実行するスクリプト(/path/to/exec2.php)
<?php
//引数を2つ入手。$argv配列に順番に入る。
$str1 $argv[1];
$str2 $argv[2];
...


//待たされないスクリプト
<?php
if ($_POST['submit']) {
  
$str1 'hoge';
  
$str2 'fuga';
  
//一応エスケープ処理
  
$q_str1 escapeshellarg($str1);
  
$q_str2 escapeshellarg($str2);

  
$cmd '/usr/local/bin/php '$q_str1 .' '$q_str2 .' > /dev/null &';
  
exec($cmd);
...

これで、ユーザ入力等をバックエンドのプログラムに渡すことも可能です。ユーザ入力を扱う時は、必ず最低限のエスケープ処理を入れるようにしましょう。

バックナンバーについて

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

Tipsꗗy[W 

Pick Up Q&A

Q
array_mergeの再帰処理の動作について
 このエントリーをはてなブックマークに追加 
A
>1個になったとき$leftを返しますが、 >このとき、最終的な$leftはnullになるかと思います。 いいえ、最後は「渡された配列をそのまま」返します。要素が2以上あるときとの違いは(並べ替えずに戻るので...

>>続きを読む

再帰関数は最初の内は混乱しますが、非常に上手く使える場面もいずれ出てきます。これを機会に学んでいけるといいですね。

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