FileMaker API for PHPでレコードの登録をおこなう方法を2回にわたり紹介した。今回は前回の最後に少しとりあげた事前検証処理(validate)について、もう少し深く掘りさげて取りあげよう。

validate()使用前に気をつけておくこと

まずはFileMaker_Command::validate()で検証できる・できない入力値の制限について確認しておこう。

validate()で事前検証が可能な入力値の制限

  • 空欄不可
  • タイプ: 数字
  • 最大文字数
  • タイプ: 西暦4桁の日付
  • タイプ: 時刻
  • 日付フィールド
  • 時刻フィールド
  • タイムスタンプフィールド

validate()で事前検証が不可能な入力値の制限

  • ユニークな値
  • 既存値
  • 下限値, 上限値
  • 値一覧名
  • 計算式で制限

「フィールドオプション」ダイアログの"入力値の制限"タブ。赤色の打消線で表示した項目は、validate()による事前検証がおこなえない

事前検証が不可能な入力値の制限はvalidate()ではどうやっても捕捉不可能だ。実際に登録・編集をおこなって初めて返ってくるエラーを使用して処理をおこなうか、ほかの手段を考えよう。

事前検証が不可能な入力値の制限で、検証をおこなう代案

  • ユニークな値: 登録・編集処理前に該当フィールドに対してaddFindCriterion()後、exccute()。FileMaker::isError()がfalse(エラーなし)ならば、ユニークではないと判定
  • 既存値: 登録・編集処理前に該当フィールドに対してaddFindCriterion()後、exccute()。FileMaker::isError()がtrueかつ、getCode()が401(レコードが見つからない)ならば、既存値ではないと判定
  • 下限値, 上限値: 別途PHP側で定義し、独自エラー処理
  • 値一覧名: listValueLists()で値一覧を取得し、入力された値が値一覧内にて定義されているかを検証する
  • 計算式で制限: 別途PHP側で定義し、独自エラー処理

ほかに気をつけておきたいこととして、フィールドオプションの入力値の制限で設定する「タイプ: 西暦4桁の日付」「タイプ: 時刻」と、「日付フィールド」「時刻フィールド」は別扱いのバリデーションエラーとしてあつかわれることが挙げられる。

検証後に返るFileMaker_Error_Validationオブジェクトとは

validate()に失敗(登録する値が入力値の制限にひっかかり、エラーが発生した場合は、FileMaker_Error_Validationオブジェクトが返る。このオブジェクトにはおおくの情報がふくまれているが、大別するとおもに次の情報が格納されている。

  • FileMaker_Implementation Object: FileMaker Serverに接続するための情報が格納
  • FileMaker_Field_Implementation Object: レイアウトに配置されているフィールドの詳細な情報が格納。入力値の制限(_validationRules)はこのオブジェクト内に格納されている
  • FileMaker_Command_Add_Implementation Object: 検証に使用したフィールドと値を格納

この中から各種メソッドを使用し、必要な情報を取りだしていくことになる。用意されているメソッドは次のとおり。

FileMaker_Error_Validationクラスに用意されているメソッド

  • addError()
  • getErrors()
  • isValidationError()
  • numErrors()

FileMaker_Errorクラスから継承するメソッド

  • FileMaker_Error()
  • getErrorString()
  • getMessage()
  • isValidationError()

addError()はおもに内部で使用されているメソッドだ。独自でvalidate()の追加検証を実装する場合をのぞけば、とくに使う必要はない。isValidationError()はオブジェクト判定用のメソッドだが、validate()実行後の返り値の都合上、FileMaker::isError()を使用するほうが融通がききやすい。よって、ここではおもにgetErrors()とnumErrors()の2メソッドを中心に取りあげよう。

getErrorsメソッド (Validation.php 70-88行目より)

    /**
     * Returns an array of arrays describing the validation errors
     * that occurred. Each entry in the outer array represents an
     * individual validation failure. Each failure is represented by a
     * three-element array with the following members:
     *
     * 0 => The field object for the field that had the validation problem.
     * 1 => The validation rule that failed for that field (a FILEMAKER_RULE_* constant).
     * 2 => The invalid value.
     *
     * Multiple validation rules can fail on a single field. If the
     * optional $fieldName parameter is set, then only failures for
     * that individual field will be returned.
     *
     * @param string $fieldName Get errors only for this field name.
     *
     * @return array Validation error details.
     */
    function getErrors($fieldName = null)
  • string $fieldName: エラー情報を取得したいフィールド名を指定。省略した場合はすべてのフィールドに関するエラー情報を取得する

検証後のエラー情報を取得する。返り値は配列として返り、それぞれ次の情報が格納される。

  • [0] => FileMaker_Field_Implementation Objectオブジェクト(フィールドに関する詳細情報)が格納される
  • [1] => 入力値の制限に抵触した項目が対応する数値として格納
  • [2] => 入力値の制限に抵触した入力値が格納

配列1番目はFileMaker_Field_Implementationオブジェクトそのもののため、getName()やdescribeLocalValidationRules()といったFileMaker_Fieldクラスのメソッドをそのまま使用することが可能だ。配列2番目の対応する数値は次のとおり。

  1. 空欄不可/FILEMAKER_RULE_NOTEMPTY
  2. タイプ: 数字ではない/FILEMAKER_RULE_NUMERICONLY
  3. 最大文字数超過/FILEMAKER_RULE_MAXCHARACTERS
  4. 西暦4桁の日付書式ではない/FILEMAKER_RULE_FOURDIGITYEAR
  5. タイプ: 時刻ではない/FILEMAKER_RULE_TIMEOFDAY
  6. タイムスタンプの書式ではない/FILEMAKER_RULE_TIMESTAMP_FIELD
  7. 日付の書式ではない/FILEMAKER_RULE_DATE_FIELD
  8. 時刻の書式ではない/FILEMAKER_RULE_TIME_FIELD

配列3番目には実際の入力値が格納される。ひとつのフィールドに複数の入力値の制限を設定している場合は、入力値の制限に抵触する分だけエラー情報が返る。

numErrorsメソッド (Validation.php 60-65行目より)

    /**
     * Return the number of validation rules that failed.
     *
     * @return integer Number of failures.
     */
    function numErrors()

検証結果中、「入力値の制限」に抵触した数を返す。引数はなし、戻り値はinteger型。

ここまで紹介した2メソッドを使って、実際に試してみよう。ここでのファイル情報、用意したフィールドは次のとおり。

  • レイアウト名: fmapi_validate_test_2
  • フィールド名: ft_num_notNull, ft_num_typeNum, ft_num_maxLen4, ft_date_typeDate, ft_date_typeTime, ft_timestamp, ft_date, ft_time, ft_num_typeNum_maxLen4

今回作成したフィールド情報。それぞれ左にオプション、右にコメントを表示している。ft_num_typeNum_maxLen4には入力値の制限を2つ設定した

今回作成したフィールドのみを配置している「fmapi_validate_test_2」レイアウト

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

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_2');

$newCommand->setField('ft_num_notNull', ''); // 空欄のためエラー
$newCommand->setField('ft_num_typeNum', '1,000'); // 「,」が入っている=数字タイプではないためエラー
$newCommand->setField('ft_num_maxLen4', '39800'); // 最大文字数の「4文字」を超えているためエラー
$newCommand->setField('ft_date_typeDate', '9/16'); // 西暦未入力のためエラー
$newCommand->setField('ft_date_typeTime', '12:60:00'); // 「分」が不正な時刻書式のためエラー
$newCommand->setField('ft_timestamp', '2009/9/16 12:00:00'); // タイムスタンプの書式(MM/DD/YYYY HH:ii:ss)ではないためエラー
$newCommand->setField('ft_date', '2009/9/16'); // 日付の書式(MM/DD/YYYY)ではないためエラー
$newCommand->setField('ft_time', '12:60:00'); // 「分」が不正な時刻書式のためエラー
$newCommand->setField('ft_num_typeNum_maxLen4', '10,000'); // 「,」が入っている=数字タイプではない、「4文字」を超えているためエラー

$validate = $newCommand->validate();

if(FileMaker::isError($validate))
{
    // レコード登録前のバリデートエラー処理

    echo 'バリデーションエラー数: ' . $validate->numErrors();

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

    ?>
    <table border="1">
        <tr>
            <th>フィールド名</th>
            <th>エラー内容</th>
            <th>入力値</th>
        </tr>
    <?php
    foreach($validate->getErrors() as $error)
    {
        ?>
        <tr>
            <td><?php echo $error[0]->getName(); ?>&nbsp;</td>
            <td><?php echo $error[1] . ' - ' . $errorMessages[$error[1]]; ?>&nbsp;</td>
            <td><?php echo $error[2]; ?>&nbsp;</td>
        </tr>
        <?php
    }
    ?>
    </table>
    <?php
}
else
{
    $result = $newCommand->execute();

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

?>

作成した全フィールドにたいして、入力値の制限に抵触する値をセットし、validateを実行した。結果はテーブルで表示する。これを実際にWebブラウザで表示してみよう。

バリデーションエラーの数と、入力値の制限に抵触したフィールドと内容、入力値がテーブルで表示された。入力値の制限を2つセットした「ft_num_typeNum_maxLen4」は、2つともエラーを捕捉できていることが確認できる

冒頭でもすこし述べたとおり、フィールドオプションの入力値の制限で設定する「タイプ」と、フィールドの「タイプ」は別扱いされるので注意されたい。単純な登録処理や編集・検索処理と比較すると重ための処理な分、最初に覚えておくべきこともおおいバリデート処理。だが苦労に見合うだけの価値がある機能であることは確かだ。しっかり覚えておこう。