Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/selenium/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
改进PHP循环验证_Php - Fatal编程技术网

改进PHP循环验证

改进PHP循环验证,php,Php,我有一个执行验证的php脚本,我有一个代码块,它设置了4个需要相同验证的字段。我想实现的是,在这个代码块中,我可以设置键名、显示名和字段类型以及下面的设置代码,然后根据为每个字段类型设置的规则自动验证字段 下面是有问题的代码块: // key name => display name $fields = [ 'firstName' => 'First Name', 'lastName' => 'Last Name', 'compa

我有一个执行验证的php脚本,我有一个代码块,它设置了4个需要相同验证的字段。我想实现的是,在这个代码块中,我可以设置键名、显示名和字段类型以及下面的设置代码,然后根据为每个字段类型设置的规则自动验证字段

下面是有问题的代码块:

// key name => display name
$fields = [
        'firstName' => 'First Name',
        'lastName' => 'Last Name',
        'companyName' => 'Company Name',
        'companyAddress' => 'Company Address',
    ];
所以在这个模块中,我想设置键名、显示名和字段类型。目前我只得到了这四个字段。有没有办法实现我的愿望

这是我的全部代码:

function validate($formData)
{
    // Initiate Array
    $validationMSG = array(); // array to hold validation errors

    // what to validate (basics, i.e. required fields)
    // key name => display name
    $fields = [
            'firstName' => 'First Name',
            'lastName' => 'Last Name',
            'companyName' => 'Company Name',
            'companyAddress' => 'Company Address',
        ];

    //simple loop
    foreach($fields as $name => $display){
        if(empty($formData[$name])){
            $validationMSG[$name] = "${display} is required.";
        }
    }        

    //and NOW wee can perform some specific tests:

    $pname_exp = '/^[a-zA-Z0-9\_]{2,20}/';
    if(isset($formData['firstName']) && !preg_match($pname_exp, $formData['firstName'])){
        $validationMSG['firstName'] = 'First Name is not valid.';
    }
    if(isset($formData['lastName']) && !preg_match($pname_exp, $formData['lastName'])){
        $validationMSG['lastName'] = 'Last Name is required.';
    }    

    //removed company name and company address checks, because we are done with them in the loop.

    // Validate state
    if (!isset($formData['state'])) {
        $validationMSG['state'] = 'State is required.';
    }

    // Validate city
    if (!isset($formData['city'])) {
        $validationMSG['city'] = 'City is required.';
    }

    // Validate Zipcode - If Field is Empty
    if (!isset($formData['zipcode'])) {
        $validationMSG['zipcode'] = 'Zipcode is required.';
    }

    // Validate emailAddress
    if (!isset($formData['emailAddress'])) {
        $validationMSG['emailAddress'] = 'Email Address is required.';
    }

    // Check if emailAddress is a valid email address
    elseif (!filter_var($formData['emailAddress'], FILTER_VALIDATE_EMAIL)) {
        $validationMSG['emailAddress'] = 'Email address is not valid.';
    }

    //Validate phoneNumber
    if (!isset($formData['phoneNumber'])) {
        $validationMSG['phoneNumber'] = 'Phone Number is required.';
    }

    //Validate phoneNumber
    elseif (preg_match('/^[0-9-\s]+$/D', $formData['phoneNumber'])) {
        $validationMSG['phoneNumber'] = 'Must be a valid phone number.';
    }


    // Validate message
    if (!isset($formData['message'])) {
        $validationMSG['message'] = 'Message is required.';
    }

    if (!empty($validationMSG)) {
        return $validationMSG;        
    }
    else {
        $captcha = checkCaptcha($formData['g-recaptcha-response']);
        if(!$captcha['isSuccess']){
        $validationMSG['captcha'] = 'ReCaptcha is required.';

        return $validationMSG;
        }

        //End of Validation Function
    }
}
//testing
$input = ['firstName' => 'John'];
$errors = validate($input);
var_dump($errors);

你应该使用这样的方法。这是在循环中编写更好的验证检查的起点:


这里是一种进行验证的方法,同时仍然可以在重构时将格式提升为类型化类(例如,使用名称空间和依赖项注入等)。我将向您展示的是一种获取对象的方法,您可以基于公共命名构造验证消息负载

首先,创建一个名为
userActions()
的常规php函数。这将用于(全局或在需要时作为include)调用和获取这些对象。这将返回一个结束

function userActions(): \Closure { ... }
接下来,您需要封装您的过程。我建议这样做:

$startUserRecord = static function(
    string $firstName, 
    string $lastName, 
    string $companyName, 
    string $companyAddress
) {
    return new class(...func_get_args()) {
        private $payload = [];
        private $firstName; 
        private $lastName;
        private $companyName;
        private $companyAddress;

        public function __construct(
            string $firstName, 
            string $lastName, 
            string $companyName, 
            string $companyAddress
        ) {
            $this->payload = func_get_args();

            $this->firstName = $firstName;
            $this->lastName = $lastName;
            $this->companyName = $companyName;
            $this->companyAddress = $companyAddress;
        }

        public function validate(): array {
            // Here is where you would actually validate this one message.
            // Empty array means no validation messages (errors).
            return [];
        }

        public function payload(): array {
            return $this->payload;
        }
    };
};

// Other ones go here, too.
$saveUserProfile = static function() { ... };
$resetUserLogin = static function() { ... };
将它们关联到一起,这样我们就可以在我们的
userActivities()
闭包中使用它们了:

$activities= [
    'startUserRecord' => $startUserRecord,
    'saveUserProfile ' => $saveUserProfile,
    'resetUserLogin ' => $resetUserLogin,
];
现在,我将其命名为
startUserRecord
,因为我需要创建一个命令名;给它取一个你想要的名字,但是我推荐动词+主语+上下文结构

静态检查适用于“string,integer”和其他低级类型检查,或者您现有的基于类的构造(例如,
Email
value对象)。如您所见,值的验证发生在
validate()
方法中

接下来,创建将返回的闭包,该闭包实际上允许您搜索并仅获取所需的命令对象:

return static function(/* autoset as $get */) use($activities) {
    $get = func_get_args();

    $find = static function($name) use(&$get) {
        return in_array($name, $get);
    };

    $filtered = array_filter($activities, $find, ARRAY_FILTER_USE_KEY);
    $found = [];

    // Keep in the same order.
    foreach($get as $name) {
        $found[] = $filtered[$name];
    }

    return $found;
};
注意闭包上的
use()
语句

这被放在
userActivities()
函数声明中。现在,您可以调用并设置它,并通常使用您拥有的:

$fields = [
    'firstName' => 'First Name',
    'lastName' => 'Last Name',
    'companyName' => 'Company Name',
    'companyAddress' => 'Company Address',
];

$userActivities = userActions();

[$startUserRecord] = $userActivities('startUserRecord');

$activity = $startUserRecord(...array_values($fields));

if ($errors = $activity->validate()) {
    throw new InvalidCommand($errors);
}

// Do something with $activity->payload().
注:

  • 我没有修改有效载荷。您可以添加一个作用于有效负载的调节器/消毒剂方法,或者以某种形式返回对象的属性
  • 我们正在使用
    [$startUserRecord]
    行进行解构。这允许您返回多个条目并将它们加载到它们自己的变量名中。例如:

    [$saveUserProfile,$resetUserLogin] = $userActivites('saveUserProfile','resetUserLogin');
    
  • $startUserRecord(…数组_值($fields))
    这称为扩展或splat操作(调用中的splat操作符:
    ),并使每个数组项按顺序成为自己的独立参数。我在这里通过
    array\u values()
    实现了这一点,但是最好是传入一个实际的数组,而不使用键,以便在所有情况下都保持顺序

以下是它们的组合:

这只是一个起点。改变它,做你需要做的,这会让你知道你能完成什么


例如,您可以将初始值设定项移动到
with()
方法,并“自动加载”在
userActivities()
函数中共享的小型基于闭包的验证器,例如声明的
$validateEmail()
$validatePhone()
闭包,然后
使用($validateEmail,…)
并在该闭包中
新建类($validateEmail,…)
在活动的上下文中共享这些内容。

您所说的字段类型是什么意思?您能提供一个示例吗?我建议根据活动将数组转换为值对象,并实现一个公共接口(
StartUserRecord implements Transport
),并在验证类型的属性上使用注释(
@Assert\NotBlank
@Assert\NotNull
,或自定义类型)。然后,您的
validate(Transport$message)
函数运行验证并返回消息。请参阅Symfony Validator以获取示例:@weegee例如,firstName和lastName需要相同类型的验证,但phoneNumber需要不同类型的验证,与emailAddress相同,emailAddress甚至需要其他类型的验证。我想在代码块中指定那些“类型”。比如字符串、int和电子邮件?您可以使用类型声明:
公共函数setName(string$name)
,或者在7.4属性类型中:
公共字符串$name这是使用类的好处。电子邮件和电话号码是约束而不是类型,因此您可能需要像
Email
这样的自定义类,或者使用通用或自定义电子邮件约束(请参阅我提供的Symfony链接)。您实际上必须验证验证,这意味着所有构造都是完整的。这是源代码验证的一个起点,随着时间的推移,它可能会变得笨拙,尽管正如您所建议的,这是一个不错的起点。“不过,我会很快从它那里重构出来。”贾雷德法里什同意了!但是这种方法比@jucyva目前所做的要好得多。@JaredFarrish你能给我一个你的方法/建议的样本吗?@Rehmat你为什么要离开源代码验证点?我没有使用像laravel或symfony这样的框架。@jucyva你能再解释一下
源代码验证吗?我没有建议你使用任何框架。这是纯粹的PHP。在今天之前,我已经考虑了一段时间了,所以这里有另一个重构,它有更多的健全性检查和一些很好的特性:基本思想是使用间接和匿名类(包括invocable闭包)进行原型化,这迫使您进行设置,而不仅仅是解决方案驱动的(而不是问题驱动的),通常是程序性的,结果。分离出一个抽象类,因此更容易理解:感谢providin