SV::file() / SV::custom() / RespectRules - JSON Schema 非対応型
これらの型はサーバー側検証を行いますが、JSON Schema に変換できません。 SV::file() は NativeFileValidator を使用します(依存なし)。SV::custom() は任意の callable を受け取ります(依存なし)。RespectRules::rule() はオプションの Respect/Validation ライブラリを使用します。 toJsonSchema() の出力では properties に含まれず、x-unmapped-fields にフィールド名が記録されます。
クライアントの validateObject はこれらのフィールドを自動的にスキップし、サーバー側に委譲します。
SV::file(accept)
ファイルアップロードの MIME タイプを検証します。
SV::file(array $accept = [])| パラメータ | 型 | 説明 |
|---|---|---|
$accept | string[] | 許容する MIME タイプの配列 |
用途: <input type="file"> のファイル種別を制限する。
// 画像のみ
SV::file(['image/jpeg', 'image/png', 'image/webp'])
// PDF のみ、任意入力
SV::file(['application/pdf'])->optional()
// 種別不問(存在チェックのみ)
SV::file()サーバー側での使い方
$schema = SV::object([
'name' => SV::string()->min(1),
'avatar' => SV::file(['image/jpeg', 'image/png'])->optional(),
]);
// ファイルの検証は validateFiles() を使う
$result = $schema->toValidator()
->validate($_POST)
->validateFiles($_FILES)
->getResult();JSON Schema 出力
avatar は properties に含まれず x-unmapped-fields に記録される。
{
"type": "object",
"properties": {
"name": { "type": "string", "minLength": 1 }
},
"required": ["name"],
"x-unmapped-fields": ["avatar"]
}SV::custom(callable, message)
依存なしのエスケープハッチ。任意の callable 述語で検証ロジックを指定できる。組み込み型では表現できない制約に使う。
SV::custom(callable $predicate, string $message = 'Validation failed')| パラメータ | 型 | 説明 |
|---|---|---|
$predicate | callable | フィールド値を受け取り bool を返す callable |
$message | string | 検証失敗時のエラーメッセージ(デフォルト: 'Validation failed') |
JSON Schema では表現できないため x-unmapped-fields に記録されます。
用途: 電話番号検証、カスタム業務ルール、任意の PHP ライブラリとの連携 -- Respect/Validation を依存に含めずに利用可能。
// シンプルなインライン述語
SV::custom(
fn(mixed $value): bool => is_string($value) && strlen($value) === 8 && ctype_digit($value),
'8桁の数字を入力してください'
)->optional()
// 外部ライブラリのラップ
SV::custom(
fn(mixed $value): bool => SomeLibrary::validate($value),
'無効な値です'
)外部ライブラリとの連携
use libphonenumber\PhoneNumberUtil;
use libphonenumber\NumberParseException;
$phoneUtil = PhoneNumberUtil::getInstance();
$schema = SV::object([
'tel' => SV::custom(
function ($value) use ($phoneUtil) {
try {
$number = $phoneUtil->parse($value, 'JP');
return $phoneUtil->isValidNumberForRegion($number, 'JP');
} catch (NumberParseException) {
return false;
}
},
'有効な日本の電話番号を入力してください'
)->optional(),
]);詳細は 高度な利用例 を参照。
JSON Schema 出力
{
"type": "object",
"properties": {},
"x-unmapped-fields": ["tel"]
}RespectRules::postalCode(countryCode)
国別の郵便番号を検証する。Respect/Validation の postalCode() ルールを使用する。
RespectRules::postalCode(string $countryCode)| パラメータ | 型 | 説明 |
|---|---|---|
$countryCode | string | ISO 3166-1 alpha-2 国コード(例: 'JP', 'US', 'DE') |
JSON Schema では表現できないため x-unmapped-fields に記録されます。
RespectRules::postalCode('JP')->optional() // 日本の郵便番号(任意入力)
RespectRules::postalCode('US') // 米国の ZIP コードRespectRules::creditCard(...brands)
クレジットカード番号を Luhn アルゴリズムで検証します。
RespectRules::creditCard(string ...$brands)| パラメータ | 型 | 説明 |
|---|---|---|
...$brands | string | 受け入れるカードブランド(省略時は全ブランド対応)。例: 'Visa', 'Mastercard' |
JSON Schema では表現できないため x-unmapped-fields に記録されます。
RespectRules::creditCard() // 全ブランド
RespectRules::creditCard('Visa', 'Mastercard') // Visa / Mastercard のみRespectRules::iban()
IBAN(国際銀行口座番号)を検証する。
RespectRules::iban()JSON Schema では表現できないため x-unmapped-fields に記録されます。
RespectRules::iban()->optional()RespectRules::rule(rule)
Respect/Validation のルールを直接指定するエスケープハッチです。組み込み型では表現できない制約に使います。オプションの respect/validation パッケージが必要です。
RespectRules::rule(Respect\Validation\Validator $rule)| パラメータ | 型 | 説明 |
|---|---|---|
$rule | Respect\Validation\Validator | Respect のバリデーターインスタンス |
用途: libphonenumber を使った電話番号検証、IBAN 検証、カスタム業務ルールなど、JSON Schema では表現できない制約。
use Respect\Validation\Validator as v;
// Respect 組み込みのクレジットカード検証
RespectRules::rule(v::creditCard())
// callback でカスタムロジックを注入
RespectRules::rule(v::callback(function ($value) {
return strlen($value) === 8 && ctype_digit($value);
}))->optional()外部ライブラリとの連携
use libphonenumber\PhoneNumberUtil;
use libphonenumber\NumberParseException;
$phoneUtil = PhoneNumberUtil::getInstance();
$schema = SV::object([
'tel' => RespectRules::rule(
v::callback(function ($value) use ($phoneUtil) {
try {
$number = $phoneUtil->parse($value, 'JP');
return $phoneUtil->isValidNumberForRegion($number, 'JP');
} catch (NumberParseException) {
return false;
}
})
)->optional(),
]);詳細は 高度な利用例 を参照。
JSON Schema 出力
{
"type": "object",
"properties": {},
"x-unmapped-fields": ["tel"]
}x-unmapped-fields の扱い
クライアント側で x-unmapped-fields を追加検証するには、クライアントの Constraint または Zod の .superRefine() を使う。
// client: 手動で追加検証
const result = validateObject(data, schema)
const unmapped = schema['x-unmapped-fields'] ?? []
if (unmapped.includes('tel')) {
const ok = /^0\d{9,10}$/.test(data.tel ?? '')
// result を拡張して tel の検証結果を追加
}// Zod: superRefine で追加
const zodSchema = buildZodSchema(schema).extend({
tel: z.string().optional().superRefine((val, ctx) => {
if (!val) return
if (!/^0\d{9,10}$/.test(val)) {
ctx.addIssue({ code: 'custom', message: '有効な電話番号を入力してください' })
}
}),
})