1

对不起,糟糕的标题,让我试着在下面解释一下。

我写了一堆返回真或假的小函数。

validateName()
validateEmail()
validateAddr()
validateBirtd()
validateUsername()

现在我正在循环使用 CSV 文件导入的大量数据,并检查哪些数据有效或无效(返回真或假)。

我这样做:

if (validateName($data[0]) == true AND validateEmail($data[1]) == true AND validateAddr($data[3]) == true AND validateBirtd($data[5]) == true AND validateUsername($data[6])==true) {
 // create array to import etc etc
}else{
 // create other array with data who failed validation, to show user later..etc etc
}

我的问题是 - 有没有更聪明的方法来做到这一点?是否可以为每个失败的验证创建一个列表?假设 3 个条目未通过 validateEmail() 函数,10 个条目均未通过 validateEmail 和 validateName()。

我是否有办法对此进行排序,以便我可以告诉用户“这些条目未通过电子邮件验证”和“这些条目未通过名称和电子邮件验证”。

我考虑过一次验证一个字段,但是如果一个条目有多个验证错误,这样我就会有重复项。

如果有某种我不知道在哪里可以做到这一点的逻辑会很酷

4

3 回答 3

5

你可以创建一个函数。

function validate($data) {
  $errors = array();
  $fields = array('Name', 'Email', 'Addr', 'Birtd', 'UserName');
  foreach ($fields as $i => $field) {
    $func = 'validate'.$field;
    if (!$func($data[$i])) {
      $errors[] = $field;
    }
  }
  return $errors;
}

$errors = validate($data);
if (empty($errors)) {
  // create array to import etc etc
} else {
  // errors
  echo 'There are errors with ' . implode(',', $errors);
}
于 2012-11-26T02:30:27.330 回答
2

您可以使用Iterators同时获取 CSV 内容和过滤。您还可以为每个 CSV 索引添加不同的回调

例子

$csv = new CSVFilter(new CSVIterator("log.txt"));
$csv->addFilter(0, "validateName"); //<------------ Means validate Index at 0
$csv->addFilter(1, "validateEmail");
$csv->addFilter(2, "validateAddr");
$csv->addFilter(3, "validateBirtd");
$csv->addFilter(4, "validateName");
$csv->addFilter(5, "validateUsername");

foreach ( $csv as $data ) {
    var_dump($data);
}

//To get Errors 
var_dump($csv->getErrors());

CSV 过滤器

class CSVFilter extends FilterIterator {
    protected $filter = array();
    protected $errors = array();

    public function __construct(Iterator $iterator) {
        parent::__construct($iterator);
    }

    public function addFilter($index, Callable $callable) {
        $this->filter[$index] = $callable;
        $this->errors[$callable] = 0;
    }

    public function getErrors() {
        return $this->errors;
    }

    public function accept() {
        $line = $this->getInnerIterator()->current();
        $x = true;
        foreach ($this->filter  as $key => $var ) {
            if (isset($line[$key])) {
                $func = $this->filter[$key];
                $func($var) or $this->errors[$func] ++ and $x = false;
            }
        }
        return $x;
    }
}

CSVIterator

class CSVIterator implements \Iterator {
    protected $fileHandle;
    protected $line;
    protected $i;

    public function __construct($fileName) {
        if (! $this->fileHandle = fopen($fileName, 'r')) {
            throw new \RuntimeException('Couldn\'t open file "' . $fileName . '"');
        }
    }

    public function rewind() {
        fseek($this->fileHandle, 0);
        $this->line = fgetcsv($this->fileHandle);
        $this->i = 0;
    }

    public function valid() {
        return false !== $this->line;
    }

    public function current() {
        return array_map("trim", $this->line);
    }

    public function key() {
        return $this->i;
    }

    public function next() {
        if (false !== $this->line) {
            $this->line = fgetcsv($this->fileHandle);
            $this->i ++;
        }
    }

    public function __destruct() {
        fclose($this->fileHandle);
    }
}

简单随机函数

function validateName($var) {
    return mt_rand(0, 5);
}

function validateEmail($var) {
    return mt_rand(0, 5);
}

function validateAddr($var) {
    return mt_rand(0, 5);
}

function validateBirtd($var) {
    return mt_rand(0, 5);
}

function validateUsername($var) {
    return mt_rand(0, 5);
}
于 2012-11-26T02:53:50.583 回答
1

如果你的东西更封装一些,你可以试试这个。它允许您为可能要验证的每个 CSV 文件编写不同的验证器。此外,您可以在任一类中编写允许您在每一行上执行附加任务的方法。我只是发现它比拥有一堆全局命名的函数更干净、更容易维护。

注意:我显然使用了一些非常基本的验证器示例和异常。这里的想法是我提供了一个布局供您遵循;您可以根据需要自定义任何特定行为。

用法

$c = new UserCsvValidator('user_data.csv');

try {
    $c->validate();
}
catch (Exception $e) {
    echo $e->getMessage();
}

执行; 父类

<?php

class CsvValidator {

    private $filename;
    private $fh;
    protected $fields = array();

    public function validate__construct($filename, ) {

        $this->filename = $filename;

        // open file
        if ( ($this->fh = fopen($this->filename, 'r')) === false) {
            throw new Exception("could not open file: {$this->filename}");
        }
    }

    public function validate() {
        while( ($row=fgetcsv($this->fh)) !== false) {

            // create hash
            if ( ($hash = array_combine($this->fields, $row)) === false) {
                throw new Exception("invalid row" . print_r($row, true));
            }

            // validate
            foreach ($hash as $field => $value) {

                // determine method call
                $method = "validate_{$field}";
                if (!method_exists($this, $method)) {
                    throw new Exception("validation method not defined: {$method}");
                }

                // validate the field
                if (call_user_func(array($this, $method), $value) === false) {
                    throw new Exception("invalid value for {$field}: {$value}");
                }
            }
        }
    }
}

执行; 子类

<?php

class UserCsvValidator extends CsvValidator {

    protected $fields = array('name', 'email', 'address', 'birth_date', 'username');

    // example functions for each field
    protected function validate_name($value) {
        return !empty($value);
    }

    protected function validate_email($value) {
        return strpos($value, '@') !== false;
    }

    protected function validate_address($value) {
        return !empty($value);
    }

    protected function validate_birth_date($value) {
        return date('Y-m-d', strtotime($value)) == $value;
    }

    protected function validate_username($value) {
        return !empty($value);
    }
}
于 2012-11-26T02:46:34.607 回答