前回はFileMaker API for PHPでレコードの登録をおこなう方法を紹介した。今回はレコード登録時に、各種バリデートやFileMakerスクリプトを起動させる便利なメソッドを中心に取りあげよう。

レコード登録時に押さえておきたいメソッド集

FileMaker API for PHPでのレコード登録時において、押さえておきたいメソッドは次のとおり。

  • setScript: コマンド実行後(-script)に起動するFileMakerスクリプトを指定。FX.phpではPerformFMScriptに相当
  • setPreCommandScript: コマンド実行前(-script.prefind)に起動するFileMakerスクリプトを指定。FX.phpではPerformFMScriptPrefindに相当
  • setPreSortScript: ソート実行前(-script.presort)に起動するFileMakerスクリプトを指定。FX.phpではPerformFMScriptPresortに相当
  • setRecordClass: FileMaker_Recordクラス以外の、自作のクラスなどを使用する場合に使用
  • setResultLayout: レスポンスレイアウト(-lay.response)を指定。FX.phpではSetDBDataの第4引数($responseLayout)に相当
  • validate: 1フィールドまたはコマンド全体に対してバリデートを実行する

それではこれらのメソッドについて、どのような動作をするか調べてみよう。まずはFileMakerスクリプトの起動に関連するメソッドからだ。

setScriptメソッド(Command.php 48-54行より)

    /**
     * Set a script to be run after the result set is generated and sorted.
     *
     * @param string $scriptName The name of the script to run.
     * @param string $scriptParameters Any parameters to pass to the script.
     */
    function setScript($scriptName, $scriptParameters = null)

setPreCommandScriptメソッド(Command.php 59-65行より)

    /**
     * Set a script to be run before performing the find and sorting the result set.
     *
     * @param string $scriptName The name of the script to run.
     * @param string $scriptParameters Any parameters to pass to the script.
     */
    function setPreCommandScript($scriptName, $scriptParameters = null)

setPreSortScriptメソッド(Command.php 70-76行より)

    /**
     * Set a script to be run after performing the find, but before sorting the result set.
     *
     * @param string $scriptName The name of the script to run.
     * @param string $scriptParameters Any parameters to pass to the script.
     */
    function setPreSortScript($scriptName, $scriptParameters = null)

これら3つのメソッドはFileMakerスクリプトを実行するタイミングがそれぞれ違うだけで、PHP側から渡す引数はどれも変わらない。渡す引数は次の2つだ。

  • string $scriptName: 実行したいFileMakerスクリプト名を指定
  • string $scriptParameters: FileMakerスクリプトに渡すスクリプト引数を指定

$scriptParametersにはデフォルト引数が設定されているので省略が可能。スクリプトの動作については別途「FileMakerならではのメリットを出すには - スクリプトを活用せよ」も参考にしてほしい。

setRecordClassメソッド(Command.php 81-92行より)

    /**
     * Set the PHP class that will be instantiated to represent
     * records returned in any result set. The default is to use the
     * provided FileMaker_Record class. Any substitute classes must
     * provide the same API that FileMaker_Record does, either by
     * extending it or re-implementing the necessary methods. The user
     * is responsible for defining any custom class before the API
     * will need to instantiate it.
     *
     * @param string $className
     */
    function setRecordClass($className)
  • string $className: FileMaker_Recordクラスを置換するクラス名を指定

とくに指定がない場合、FileMaker API for PHPはレコード情報が格納されたリザルトセットを受けとる時にFileMaker_Recordクラスを使用する。FileMaker_Recordクラスで用意されている機能以外に自作の関数を使いたい場合、FileMaker_Recordクラスを継承する独自クラスを実装し、setRecordClassでFileMaker_Recordクラスの代わりに使用することが可能だ。

setResultLayoutメソッド(Command.php 37-43行より)

    /**
     * Request the result to be returned in a layout different than
     * the one being queried against.
     *
     * @param string $layout The layout to return results using.
     */
    function setResultLayout($layout)
  • string $layout: レスポンスレイアウトを指定

コマンド発行後、どのレイアウトを使用してリザルトセットを生成するかを指定する。レスポンスレイアウトの重要性については「スピードアップのために徹底チューニング(1) フィールドの配置法」でも言及しているとおり、パフォーマンスアップには見逃せない機能のひとつだ。とくにFileMaker API for PHPではFX.phpと比較するとやり取りする情報量が多い分、パフォーマンスが落ちやすい。細かいところではあるが、きっちり押さえておこう。たとえ小数点以下のスピードの差でも「塵もつもれば山となる」だ。

validateメソッド(Command.php 97-114行より)

    /**
     * Validates either a single field or the whole command against
     * the validation rules that are enforceable on the PHP side -
     * type rules, ranges, four-digit dates, etc. Rules such as unique
     * or existing, or validation by calculation field, cannot be
     * pre-validated.
     *
     * If the optional $fieldName argument is passed, only that field
     * will be validated. Otherwise the command will be validated just
     * as if execute() were called with prevalidation turned on in the
     * API properties. validate() returns TRUE if validation passes,
     * or a FileMaker_Error_Validation object containing details about
     * what failed to validate.
     *
     * @param string $fieldName Only validate this field. If empty, validate the whole record.
     * @return boolean|FileMaker_Error_Validation Result of field validation on $value.
     */
    function validate($fieldName = null)
  • string $fieldName: バリデートをおこないたいフィールド名を指定。省略した場合はクエリ全体に対してバリデートが実行される

validate実行後、validate成功時にtrue、validate失敗FileMaker_Error_Validationオブジェクトが返る。「計算式での制限」「ユニークな値」「既存値」など、いくつかのバリデートはできないという制約はあるものの、FileMakerへレコードを登録する前にバリデートができるので、FX.phpより柔軟なエラー処理を実装することが可能だ。実際に試してみよう。

ここでのファイル情報、用意したフィールドは次のとおり。

  • レイアウト名: fmapi_validate_test
  • フィールド名: ft_text_notNull, ft_text_unique, ft_num, ft_date

  • ft_text_notNull: テキスト型、空欄負荷

  • ft_text_unique: テキスト型、ユニークな値であること
  • ft_num: 数字型、入力値は数字型であること
  • ft_date: 日付型、日付であること

あたらしく作成したフィールド情報

使用するレイアウト

ソースコードは次のとおり。

fmapi_validate_test.php

<?php

include_once('../FileMaker.php');

$data = new FileMaker('fmapi_test', 'http://localhost:80', 'admin', 'admin');

$newCommand = $data->newAddCommand('fmapi_validate_test');

$newCommand->setField('ft_text_notNull', '');
$newCommand->setField('ft_text_unique', 'test');
$newCommand->setField('ft_num', '1,000');
$newCommand->setField('ft_date', '2009/9/8');

$validate = $newCommand->validate();
echo '<pre>';
if(FileMaker::isError($validate))
{
    // レコード登録前のバリデートエラー処理

    // getErrors()で返る配列の2番目に格納されるエラー番号に対応するメッセージ
    $errorMessages = array
    (
        '',
        '空欄不可/FILEMAKER_RULE_NOTEMPTY',
        '数字のみ入力可/FILEMAKER_RULE_NUMERICONLY',
        '最大文字数超過/FILEMAKER_RULE_MAXCHARACTERS',
        '西暦4桁の日付書式ではない/FILEMAKER_RULE_FOURDIGITYEAR',
        '時刻の書式ではない/FILEMAKER_RULE_TIME_FIELD',
        'タイムスタンプの書式ではない/FILEMAKER_RULE_TIMESTAMP_FIELD',
        '日付の書式ではない/FILEMAKER_RULE_DATE_FIELD',
    );

    foreach($validate->getErrors() as $error)
    {
        echo '<p>FieldName: ' . $error[0]->getName() . '</p>';
        echo '<p>Error: ' . $errorMessages[$error[1]] . '</p>';
        echo '<p>Value: '.$error[2].'</p>';
        echo '<hr>';
    }
}
else
{
    $result = $newCommand->execute();

    if (FileMaker::isError($result))
    {
        // レコード登録時のエラー処理..
        echo 'FileMaker Error Code: ' . $result->getErrorString();
        echo '<p>'. $result->getMessage() . '</p>';
    }
    else
    {
        // 正常処理..
        echo 'done.';
    }
}

?>

4フィールドに対して入力値をセットし、validateを実行している。実際にWebブラウザで表示してみよう。

「ユニーク値であること」の制限をかけたft_text_uniqueは検出できなかったが、ほかの3フィールドはバリデートで検出され、エラー内容が表示された

このように簡単にバリデートをおこなうことが可能となっている。実際にレコードを登録する前にバリデートチェックをおこなうことができるのはFX.phpにもない特徴だ。返り値にクセがあるため習得がややむずかしいが、Ajaxを多用するWebアプリケーションではぜひ押さえておきたいところ。次回はこのvalidateをもう少し深く掘りさげて解説していこう。

一部のソースはなぜか難読化? IDEを活用して効率的に読み進めよう

FileMaker API for PHPを使ったWebアプリケーションを実装する前にソースをひととおり分析しておきたいところだが、なぜかソースの一部(/FileMaker/Implementation/以下のPHPファイル)が読みにくい箇所がある。たとえば今回紹介したvalidateメソッドは/FileMaker/Implementation/FieldImpl.phpに処理のコア部分が記述されているが、かなり読みにくくなっている。

function validate(/FileMaker/Implementation/FieldImpl.phpより一部を抜粋)

 function validate($V2063c160, $Vcb5e100e = null)
 {
 $V1c0c74f6 = true;
if ($Vcb5e100e === null) {
 $V1c0c74f6 = false;
$Vcb5e100e =& new FileMaker_Error_Validation($this->_layout->_impl->_fm);
}
foreach ($this->getValidationRules() as $V981c1e7b) {
 switch ($V981c1e7b) {
 case FILEMAKER_RULE_NOTEMPTY:
 if (empty($V2063c160)) {
 $Vcb5e100e->addError($this, $V981c1e7b, $V2063c160);
}
break;

ファイル間を行ったり来たりしていたり、一見意味のないような変数名を使用していたりと解析が困難となっている。このような場合はしらみつぶしに解析をおこなうより、IDEをはじめとしたツールを活用したほうが得策だ。ソースを解析する場合は参考にしてほしい。