MicroEngineメールフォームで条件付き必須項目

たまに使わせてもらうPHPメールフォーム MicroEngineメールフォーム で、フォーム項目を条件付きで必須にしたくなったので、てきとうにカスタマイズした記録。

パターン1:ラジオボタンで、

性別


「その他」にチェックした時だけテキストボックスを入力必須にしたい。

パターン2:複数チェックできるチェックボックスで、

ペット


「その他」にチェックした時だけテキストボックスを入力必須にしたい。

設定ファイル item.ini で必須項目に設定する required = 1 を拡張して、require_if = ~ を使えるように改造する。

[gender]
type = radio
label = "性別"

[gender_other]
type = text
label = "性別(その他)"
require_if = gender eq その他

[pets]
type = checkbox
label = "ペット"
multiple = 1

[pets_other]
type = text
label = "ペット(その他)"
require_if = pets has その他

改造するファイルは Me_MailForm.php 。

バージョン0.3.4 の場合は、744行目に以下コードを挿入。

// 条件付き必須項目チェック
// ・他の項目xxxが特定の値yyyを持つ時だけ必須
//   require_if = xxx eq yyy
// ・他のチェックボックス項目xxxの中の特定のチェックyyyがついた時だけ必須
//   require_if = xxx has yyy
if (preg_match('/^(\S+)\s+(\S+)\s+(.+)$/', $item['require_if'], $matches)) {
    list( , $target, $op, $condValue) = $matches;
    $target_item = $this->form_item[$target];
    if ($target_item) {
        $this_error = false;
        switch ($op) {
        case 'eq':
            if ($target_item['value'] === $condValue && strlen($item['value']) === 0) {
                $this_error = true;
            }
            break;
        case 'has':
            switch ($target_item['type']) {
            case 'checkbox':
                if (is_array($target_item['value']) &&
                    in_array($condValue, $target_item['value'], true) &&
                    strlen($item['value']) === 0) {
                    $this_error = true;
                }
                break;
            }
            break;
        }
        if ($this_error) {
            if ($item['type'] === 'select' || $item['type'] === 'radio') {
                $item['error'] = $this->config['message']['required_option'];
                $item['error'] = str_replace('{label}', $item['label'], $item['error']);
            } else if ($item['type'] === 'checkbox') {
                $item['error'] = $this->config['message']['required_check'];
                $item['error'] = str_replace('{label}', $item['label'], $item['error']);
            } else {
                $item['error'] = $this->config['message']['required'];
                $item['error'] = str_replace('{label}', $item['label'], $item['error']);
            }
            $this->is_error = true;
            continue;
        }
    }
}

バージョン1.0.1の場合は、514行目に以下を挿入。

// 条件付き必須項目チェック
// ・他の項目xxxが特定の値yyyを持つ時だけ必須
//   require_if = xxx eq yyy
// ・他のチェックボックス項目xxxの中の特定のチェックyyyがついた時だけ必須
//   require_if = xxx has yyy
if (preg_match('/^(\S+)\s+(\S+)\s+(.+)$/', $item['require_if'], $matches)) {
    list( , $target, $op, $condValue) = $matches;
    $target_item = $this->form_item[$target];
    if ($target_item) {
        $this_error = false;
        switch ($op) {
            case 'eq':
                if ($target_item['value'] === $condValue && strlen($item['value']) === 0) {
                    $this_error = true;
                }
                break;
            case 'has':
                switch ($target_item['type']) {
                    case 'checkbox':
                        if (is_array($target_item['value']) &&
                            in_array($condValue, $target_item['value'], true) &&
                            strlen($item['value']) === 0) {
                            $this_error = true;
                        }
                        break;
                }
                break;
        }
        if ($this_error) {
            if ($item['type'] === 'select' || $item['type'] === 'radio') {
                $this->set_error_message($item, 'msg_required_option', array('{label}'=>$item['label']));
            } else if ($item['type'] === 'checkbox') {
                $this->set_error_message($item, 'msg_required_check', array('{label}'=>$item['label']));
            } else {
                $this->set_error_message($item, 'msg_required', array('{label}'=>$item['label']));
            }
            $this->is_error = true;
            continue;
        }
    }
}