用PHP进行各种验证

检测到未定义或意外类型的元素,如 $_GET 和 $_POST。

在这里详细解释了处理「$_GET, $_POST」等接收的过程。

a=foo&b[]=bar
$a = filter_input(INPUT_GET, 'a'); // "foo"
$b = filter_input(INPUT_GET, 'b'); // false
$c = filter_input(INPUT_GET, 'c'); // null
$a = (string)filter_input(INPUT_GET, 'a'); // "foo"
$b = (string)filter_input(INPUT_GET, 'b'); // ""
$c = (string)filter_input(INPUT_GET, 'c'); // ""

假设在这之前已经进行了这样的检查,现在只关注值的格式验证。

/* 1. 未定義や想定外の型の検出 */
$email = (string)filter_input(INPUT_POST, 'email');

/* 2. 値の形式に関するバリデーション */
if (false !== filter_var($email, FILTER_VALIDATE_EMAIL)) {
    echo "正しいEメールアドレスです: $email\n";
} else {
    echo "Eメールアドレスの形式が不正です: $email\n";
}

顺便提一下,在这个例子中,如果不需要将无效的电子邮件地址存储在变量$email中的话,

$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);

if (is_string($email)) {
    echo "正しいEメールアドレスです: $email\n";
} else {
    echo "Eメールアドレスの形式が不正です\n";
}

即使把它们作为一个整体来总结也没有问题。

如果未发送,则为null,因此 false !== 的比较是不适当的。

関数フィルタリング対象成功時の返り値失敗時の返り値インデックス
未定義時の返り値filter_var自分で渡す値文字列や整数など
(フィルタによる)falsefilter_input$_GET $_POST などの
インデックス文字列や整数など
(フィルタによる)falsenull

网址

以下是两种实现模式。在很多情况下,选择B就好了。

function is_valid_url($url)
{
    return false !== filter_var($url, FILTER_VALIDATE_URL);
}
function is_valid_url($url)
{
    return false !== filter_var($url, FILTER_VALIDATE_URL) && preg_match('@^https?+://@i', $url);
}
ABhttp://
https://○○mailto:○×その他のスキーム://○×その他のスキーム:××

电子邮件地址

以下介绍了三种实现模式。由于使用不可变的IP地址进行注册可能会导致后续出现各种麻烦,所以我认为选择C是比较明智的。

※ 请务必查看追记部分,因为我们提供了更好的结论。

function is_valid_email($email)
{
    return false !== filter_var($email, FILTER_VALIDATE_EMAIL);
}
function is_valid_email($email)
{
    switch (true) {
        case !is_string($email):
        case false === $pos = strrpos($email, '@'):
        case false === filter_var(substr($email, $pos + 2, -1), FILTER_VALIDATE_IP):
        case false === filter_var(substr_replace($email, '0.0.0.0', $pos + 2, -1), FILTER_VALIDATE_EMAIL):
            return false;

        default:
            return true;
    }
}
function is_valid_email($email)
{
    return false !== filter_var($email, FILTER_VALIDATE_EMAIL) && ']' !== substr($email, -1);
}
ABCローカル部@ドメイン○○○ローカル部@[ IPv4 ]○○×ローカル部@[ IPv6 ]×○×

「只会写 PHP 的渣渣,尝试挑战邮件地址正则表达式的高手」虽然经过了许多讨论,我认为最明智的方法就是善用 PHP 原生的过滤函数来解决。是的,当然,我会排除日本手机运营商的 RFC 忽略实现的情况…

2015年8月11日 添加更新

    • 最近ではメールアドレスの国際化が進み,ローカル部のバリデーションに関してはほぼ無意味になって来ています。しかし現状それを考慮しているWebサービスが少ないということもあって,そういったメールアドレスを使用している人は非常に少ないはずなので,周囲の様子を見ながら対応する…ぐらいでもいいのかもしれません。

 

    ドメインも同様ですが,DNSレコードをチェックすることによってドメインの存在を確認出来ます。

根据这些,以下是对@xRx的代码进行微调的示例。基于C编写。如果将true作为第二个参数传入,将检查DNS记录。

function is_valid_email($email, $check_dns = false)
{
    switch (true) {
        case false === filter_var($email, FILTER_VALIDATE_EMAIL):
        case !preg_match('/@([^@\[]++)\z/', $email, $m):
            return false;

        case !$check_dns:
        case checkdnsrr($m[1], 'MX'):
        case checkdnsrr($m[1], 'A'):
        case checkdnsrr($m[1], 'AAAA'):
            return true;

        default:
            return false;
    }
}

如果您想要支持UTF-8字符串,请使用symfony/Validator而不是egulias/EmailValidator。根据源代码的显示,前者只进行MX记录的检查,而后者似乎在内部使用了前者。但为了这个目的,我们单独进行了修正。

    • egulias/EmailValidator src/Egulias/EmailValidator/EmailValidator.php #L149

 

    symfony/Validator Constraints/EmailValidator.php #L155

由于我从未使用过Symfony组件,所以跳过了示例的介绍。

2015年8月11日添加说明

自PHP7.1.0开始,已添加原生支持验证包含UTF-8字符串的电子邮件地址。从这个版本开始,这似乎是最合适的选择。

function is_valid_email($email, $check_dns = false)
{
    switch (true) {
        case false === filter_var($email, FILTER_VALIDATE_EMAIL, FILTER_FLAG_EMAIL_UNICODE):
        case !preg_match('/@([^@\[]++)\z/', $email, $m):
            return false;

        case !$check_dns:
        case checkdnsrr($m[1], 'MX'):
        case checkdnsrr($m[1], 'A'):
        case checkdnsrr($m[1], 'AAAA'):
            return true;

        default:
            return false;
    }
}

请注意,域名部分必须使用Punycode编码格式。例如,Gigazine的「Gmail能够与包含非英文字母的邮件地址进行收发邮件」这一文章中提到了武@メール.グーグル作为例子,但它必须被编码为武@xn--4dkua4c.xn--qcka1pmc。

郵遞區號和地址

    1. 从日本邮政的网站上下载全国范围的CSV数据。

 

    将其导入到MySQL或SQLite中并使用。

由于有一种可以在一次判断中处理数据的方法,因此可以说使用SQL比去尝试写复杂的正则表达式更合适。

手机号码

我将根据总务省的网站数据自行创建适合目的的功能。请注意,虽然可以使用正则表达式一次性完成,但正则表达式太长往往会导致失败,请谨慎使用。如有需要,可以导入到MySQL或SQLite中进行使用。

function is_valid_phone_number($number)
{
    return is_string($number) && preg_match('/\A\d{2,4}+-\d{2,4}+-\d{4}\z/', $number);
}

如果要认真去做的话,会相当麻烦。

I am not sure what specific context or sentence structure you would like for the word “整数” in Chinese. Here are a few options:

1. 整数 – (noun) whole number
2. 一个整数 – (noun phrase) a whole number
3. 以整数表示 (yǐ – (verb phrase) expressed as a whole number

将所有内容强制转为整数型

将整数转换为强制转化 hé

$id = (int)$id;
/**
 *  "1"    => 10進数の "1"   => 1
 *  "01"   => 10進数の "01"  => 1
 *  "010"  => 10進数の "010" => 10 
 *  "0x1A" => 10進数の "0"   => 0 
 */
$id = min(max((int)$id, 0), 9);

整数值函数

$id = intval($id); // 10がデフォルト
/**
 *  "1"    => 10進数の "1"   => 1
 *  "01"   => 10進数の "01"  => 1
 *  "010"  => 10進数の "010" => 10 
 *  "0x1A" => 10進数の "0"   => 0 
 */
$id = intval($id, 2);
/**
 *  "1"    => 2進数の "1"   => 1
 *  "01"   => 2進数の "01"  => 1
 *  "010"  => 2進数の "010" => 2
 *  "0x1A" => 2進数の "0"   => 0
 */
$id = intval($id, 36);
/**
 *  "1"    => 36進数の "1"    => 1
 *  "01"   => 36進数の "01"   => 1
 *  "010"  => 36進数の "010"  => 36
 *  "0x1A" => 36進数の "0X1A" => 42814
 */
$id = intval($id, 8);
/**
 *  "1"    => 8進数の "1"  => 1
 *  "01"   => 8進数の "1"  => 1
 *  "010"  => 8進数の "10" => 8
 *  "0x1A" => 8進数の ""   => 0
 */
$id = intval($id, 16);
/**
 *  "1"    => 16進数の "1"   => 1
 *  "01"   => 16進数の "01"  => 1
 *  "010"  => 16進数の "010" => 16
 *  "0x1A" => 16進数の "1A"  => 26
 */
$id = intval($id, 0); // 0は自動判定を意味する
/**
 *  "1"    => 10進数の "1"  => 1
 *  "01"   => 8進数の  "1"  => 1
 *  "010"  => 8進数の  "10" => 8
 *  "0x1A" => 16進数の "1A" => 26
 */

如果是正确的,则将其转换为整数型,如果是错误的,则为 false。

过滤函数 filter_var

$id = filter_var($id, FILTER_VALIDATE_INT);
/**
 *  "1"    => 10進数の "1" => 1
 *  "01"   => false
 *  "010"  => false
 *  "0x1A" => false
 */
$options = ['min_range' => 0, 'max_range' => 9];
$id = filter_var($id, FILTER_VALIDATE_INT, compact('options'));
$id = filter_var($id, FILTER_VALIDATE_INT, FILTER_FLAG_ALLOW_OCTAL | FILTER_FLAG_ALLOW_HEX);
/**
 *  "1"    => 10進数の "1"  => 1
 *  "01"   => 8進数の  "1"  => 1
 *  "010"  => 8進数の  "10" => 8
 *  "0x1A" => 16進数の "1A" => 26
 */
广告
将在 10 秒后关闭
bannerAds