很抱歉可怕的标题,让我试着解释一下。
我写了一堆小函数,它们返回true或false。
validateName()
validateEmail()
validateAddr()
validateBirtd()
validateUsername()
现在我循环使用CSV文件导入的大量数据,并检查哪些数据有效(返回true或false)。
我是这样做的:
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个entrys使validateEmail()函数失败,而10都失败了validateEmail和validateName()。
我是否有办法对此进行排序,以便我可以告诉用户“这些来电失败的电子邮件验证”和“这些失败的姓名和电子邮件验证”。
我考虑过一次验证一个字段,但是如果一个条目有多个验证错误,我会有重复。
如果有某种逻辑让我不知道我能在哪里做到这一点,那会很酷吗
答案 0 :(得分: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);
}
答案 1 :(得分: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);
}
答案 2 :(得分: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);
}
}