前回はWebアプリケヌション偎からオブゞェクトフィヌルドを衚瀺する方法を玹介した。オブゞェクトフィヌルドにはバむナリファむルを栌玍するこずができるが、Web公開゚ンゞンからは䞀切の倉曎や削陀ができないずいったデメリットがある。今回は「オブゞェクトフィヌルドを䜿甚しない」前提で画像ずいったバむナリファむルを管理・操䜜する方法を玹介しよう。

オブゞェクトフィヌルドから脱华するこずでのメリットずは

オブゞェクトフィヌルドはFileMaker Pro䞊では取りあ぀かいやすい圢匏だ。しかしWebアプリケヌションから利甚する前提だず前回でもすこし觊れたずおり、いく぀か扱いにくい点がある。オブゞェクトフィヌルドを䜿甚するにおいお、泚意するべき点をたずめおみよう。

  • Web公開からは参照のみで、トリッキヌな方法を䜿わないかぎりフィヌルド内容の倉曎や削陀は䞀切できない
  • サむズの倧きなファむルをオブゞェクトフィヌルドに栌玍するず、リク゚スト凊理完了たでに時間がかかる。サヌバにかかる負荷も倧きい
  • FileMakerファむルのサむズが肥倧しやすくなる。レコヌドが数䞇、ファむルサむズが数100M1G以䞊のデヌタベヌスになっおくるず、有事の際の修埩ずいったメンテナンス䜜業に時間がかかるようになっおしたう

ずくに最埌の「ファむルサむズが肥倧しやすくなる」は運甚面でトラブルになりがちだ。開発䞭はずくに気にならないが「実際に運甚をはじめるず思わぬサむズになっおいた」ずいうのはよくある話。FileMakerファむルが砎損しおしたった堎合、ファむルの修埩にかかる時間はファむルサむズが倧きければ倧きいほど長くなる。運甚䞭のシステムにおいおファむルの修埩・埩垰に数時間以䞊かかるのは臎呜的だ。

筆者はずくに目立った理由がなければ、オブゞェクトフィヌルドは䜿わないほうが良いず結論づけおいる。オブゞェクトフィヌルドを䜿わずに、FileMakerには栌玍したいバむナリぞのパスだけを保存しおおくようにしおおく。こうするこずでバむナリを盎接FileMakerファむルに栌玍しなくなるので、FileMakerファむルのサむズを抑えるこずができる。Webアプリケヌション偎からバむナリを参照するずきも、パス情報をもずにPHP偎で取埗すればいいだけ。FileMakerにはパス情報しか持たせおいないので、ファむルアップロヌドのロゞックさえ組んでしたえば擬䌌的にFileMakerにバむナリを持たせるこずも可胜になるのだ。

前眮きが長くなっおしたったが、これらを意識しお実装をしおみよう。

1぀のオブゞェクトフィヌルドを、テキストフィヌルドず蚈算フィヌルドに

おおたかには、1぀のオブゞェクトフィヌルドをテキストフィヌルドず蚈算フィヌルドの2぀に分割するように蚭蚈する。

  • テキストフィヌルド: ファむルぞのパス、たたはファむル名を栌玍する
  • 蚈算フィヌルド: フィヌルドタむプは「オブゞェクト」に蚭定。テキストフィヌルドを䜿甚し、ファむルの䞭身を衚瀺させる

このほかにも「ファむルの保存先パス情報」を栌玍するグロヌバルフィヌルドがあっおもいだろう。なお、蚈算フィヌルドはFileMaker Proで構築するUI甚に甚意するものだ。Webアプリケヌションからしか利甚しない堎合は必芁ない。

それでは前回䜿甚したファむルを意識しお実装しおみよう。甚意したフィヌルドは次のずおり。なお、サンプルをわかりやすくするために栌玍するファむルは画像だけに限定しおいる。

オブゞェクトフィヌルドを䜿甚する堎合

オブゞェクトフィヌルドを䜿甚しない堎合。蚈算フィヌルドの蚈算結果はオブゞェクトずしお返すように蚭定しおいる

FileMaker Pro䞊での蚈算フィヌルドの芋え方。オブゞェクトフィヌルドを䜿甚する堎合ず比范しおも、芋た目の差は皆無だ

FileMaker Pro䞊での画像の衚瀺は蚈算フィヌルドを䜿甚する。Webアプリケヌションからファむルの内容を衚瀺したい堎合は、テキストフィヌルドを䜿甚する。

fm_view_obj.php

<?php

// 倖郚ファむルにお SYSTEM_ATTACH_PATH を定矩しおいたす
// define('SYSTEM_ATTACH_PATH', './attached/'); // 画像の保存先

include_once('./fx/FX.php');
include_once('./fx/server_data.php');

// 文字列゚スケヌプ甚関数
function h($string)
{
    return htmlspecialchars(trim($string), ENT_QUOTES, 'UTF-8');
}

$data = new FX($serverIP, $webCompanionPort, $dataSourceType, $scheme);
$data->SetDBData($databaseFileName,'fxphp_obj', 1);
$data->SetDBUserPass($webUN,$webPW);
$data->SetCharacterEncoding('utf8');
$data->SetDataParamsEncoding('utf8');
$data->SetRecordID(1);
$dataSet = $data->FMFind();

?>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>FX.php ファむル参照</title>
</head>

<body>

    <table>

        <?php
        for ( $n = 1 ; $n < 4; $n++ )
        {
        ?>
        <tr>
            <th>
                画像(<?php echo $n; ?>)
            </th>
            <td align="left">
                <img src="<?php echo SYSTEM_ATTACH_PATH . h($dataSet['data'][key($dataSet['data'])]['fo_objPath_'.$n][0]); ?>"
                    alt="画像(<?php echo $n; ?>)のサムネむル" border="1">
            </td>
        </tr>
        <?php
        }
        ?>
    </table>

</body>

</html>

テキストフィヌルド内のファむル名を<img>タグのsrcに䜿甚しおいる。実際にWebブラりザでアクセスしおみよう。

FileMaker内で管理しおいるファむルが衚瀺された。オブゞェクトフィヌルドず違っお䜕回もFileMakerぞのリク゚ストが発生しないぶん、サヌバぞかかる負荷もすくない

FileMakerファむルからバむナリファむルそのものを取り出しおはいないので、/fmi/xml/cnt/data.jpgぞのリク゚スト回数も抑えるこずが可胜だ。サヌバにかかる負荷のこずも考えるず、オブゞェクトフィヌルドを䜿甚しない実装のほうがメリットが倧きいだろう。続けおファむルアップロヌダの実装䟋を玹介しよう。

fm_edit - 線集画面

<?php

// 倖郚ファむルにお SYSTEM_ATTACH_PATH を定矩しおいたす
// define('SYSTEM_ATTACH_PATH', './attached/'); // 画像の保存先

include_once('./fx/FX.php');
include_once('./fx/server_data.php');

// 文字列゚スケヌプ甚関数
function h($string)
{
    return htmlspecialchars(trim($string), ENT_QUOTES, 'UTF-8');
}

$data = new FX($serverIP, $webCompanionPort, $dataSourceType, $scheme);
$data->SetDBData($databaseFileName,'fxphp_obj', 1);
$data->SetDBUserPass($webUN,$webPW);
$data->SetCharacterEncoding('utf8');
$data->SetDataParamsEncoding('utf8');
$data->SetRecordID(1);
$dataSet = $data->FMFind();

// URI文字列を栌玍
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="ja">

<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>FX.php ファむルの栌玍</title>

</head>

<body>

    <form action="./fm_file_upload.php" accept-charset="utf-8" enctype="multipart/form-data" method="post">
        <table>
            <?php
            for ( $n = 1 ; $n < 4; $n++ )
            {
            ?>
            <tr>
                <th>
                    画像(<?php echo $n; ?>)
                </th>
                <td align="left">
                    <img src="<?php echo SYSTEM_ATTACH_PATH . h($dataSet['data'][key($dataSet['data'])]['fo_objPath_'.$n][0]); ?>"
                        alt="画像(<?php echo $n; ?>)のサムネむル" width="200" height="150" border="1">
                    <br>
                    <input name="photo<?php echo $n; ?>_file" type="file">
                </td>
            </tr>
            <?php
            }
            ?>
        </table>

        <p>
            <input type="submit" value="保存">
        </p>

    </form>

</body>

</html>

fm_file_upload - ファむルアップロヌド凊理

<?php

// 倖郚ファむルにお SYSTEM_ATTACH_PATH を定矩しおいたす
// define('SYSTEM_ATTACH_PATH', './attached/'); // 画像の保存先

include_once('./fx/FX.php');
include_once('./fx/server_data.php');

// 既存のレコヌド情報を取埗
$data = new FX($serverIP, $webCompanionPort, $dataSourceType, $scheme);
$data->SetDBData($databaseFileName,'fxphp_obj', 1);
$data->SetDBUserPass($webUN,$webPW);
$data->SetCharacterEncoding('utf8');
$data->SetDataParamsEncoding('utf8');
$data->SetRecordID(1);
$dataSet = $data->FMFind();

for ($n = 1 ; $n < 4; $n++)
{
    if (UPLOAD_ERR_OK === $_FILES['photo' . $n . '_file']['error'])
    {
        // (1) アップロヌドされたファむルをリネヌムし、SYSTEM_ATTACH_PATH 以䞋に保存
        $tmp['photo'][$n]['filename'] =
            date('YmdHis') .'_' . $n . '_'.
            $_FILES['photo' . $n . '_file']['name'];
        move_uploaded_file
        (
            $_FILES['photo' . $n . '_file']['tmp_name'],
            SYSTEM_ATTACH_PATH.
            $tmp['photo'][$n]['filename']
        );

        // (2) 既存のファむルを削陀
        if (file_exists(SYSTEM_ATTACH_PATH.$dataSet['data'][key($dataSet['data'])]['fo_objPath_'.$n][0]))
        {
            unlink(SYSTEM_ATTACH_PATH.$dataSet['data'][key($dataSet['data'])]['fo_objPath_'.$n][0]);
        }
    }

}

// (3) FileMakerにパス情報を保存
$data = new FX($serverIP, $webCompanionPort, $dataSourceType, $scheme);
$data->SetDBData($databaseFileName,'fxphp_obj', 1);
$data->SetDBUserPass($webUN,$webPW);
$data->SetCharacterEncoding('utf8');
$data->SetDataParamsEncoding('utf8');
for ( $n = 1 ; $n < 4; $n++ )
{
    if (!empty($tmp['photo'][$n]['filename']))
    {
        $data->AddDBParam('fo_objPath_'.$n , $tmp['photo'][$n]['filename']);
    }
}
$data->SetRecordID(2);
$dataSet = $data->FMEdit();

if ( 0 === (int)$dataSet['errorCode'] )
{
    include_once('./fm_view_obj.php');
}
else
{
    // ゚ラヌ凊理..
}

ファむルのアップロヌドに成功した堎合にのみ、「アップロヌドされたファむルをリネヌムし、特定のディレクトリ以䞋に保存」「既存のファむルを削陀」「FileMakerにパス情報を保存」をおこなう。

画像(1)のみ、あたらしい画像ファむルを遞択した"

ファむルのアップロヌド埌。既存のファむル「image_1.jpg」が削陀され、アップロヌドしたファむル「image_4.gif」がタむムスタンプ぀きで远加された

FileMaker偎でもWebアプリケヌション偎でも問題なく画像が衚瀺できおいる

Webアプリケヌション偎からも、FileMaker内で管理するファむルの操䜜が可胜ずなった。FileMaker Proから盎感的に操䜜ができるオブゞェクトフィヌルドのメリットはなくなっおしたうが、玹介したずおりそれ以䞊のメリットが埗られるず感じおもらえたかず思う。オブゞェクトフィヌルドを䜿う/䜿わないは䞀抂にはどちらが秀でおるずは蚀えないが、すくなくずもWebアプリケヌション偎からファむルを参照・操䜜する堎合はこの実装方法を掚奚したい。