【问题标题】:Error in PHP GeneratorPHP 生成器中的错误
【发布时间】:2017-02-15 08:39:37
【问题描述】:

如果发生错误,最好的方法是通知谁使用我的生成器函数,而不是像这段代码那样编写奇怪的返回或引发异常

function csv_file_generator($csvFilename, $delimiter = ";", $enclousure = '"') {
    if(($csvHandler = fopen($csvFilename, 'rb')) === false) {
        return;
    }

    while (($row = fgetcsv($csvHandler, 0, $delimiter, $enclousure)) !== false) {
        yield $row;
    }

    if (feof($csvHandler) === false) {
        return;
    }

    if (fclose($csvHandler) === false) {
        return;
    }

    return; /* Exit Generator */
}

【问题讨论】:

  • 也许你应该只给函数打开文件指针而不是在函数中打开文件。你对exceptions有什么意见??因为那是the best way to inform who use 并且知情的人(开发人员)知道该怎么做。
  • 同意@JustOnUnderMillions。生成器不应该负责打开文件,而只是遍历文件
  • 关于这种情况的事情:文件不存在,无效的 csv 格式,编码错误......你想如何捕捉所有可能的错误?
  • 所以就像@RiggsFolly 所说的要更好地编写这段代码,我必须只在生成器中保留while循环并将所有其余的che函数包装在另一个函数中
  • 一个类怎么样,它将方法中的子操作(打开,验证,关闭)和像getGenerator()这样的方法分开while(),然后在__construct($csvFilename, $delimiter = ";", $enclousure = '"')打开文件,在__destruct() 中关闭文件。

标签: php csv foreach generator


【解决方案1】:
<?php
class CsvFileGenerator {
    protected $fp;
    protected $delimiter;
    protected $enclousure;
    public function __construct($filename, $delimiter = ";", $enclousure = '"'){
        $this->delimiter=$delimiter;
        $this->enclousure=$enclousure;
        if(!file_exists($filename)){
            throw new Exception("file [$filename] dont exists");
        }
        if(!is_readable($filename)){
            throw new Exception("file [$filename] is not readable");
        }
        $this->fp =  fopen($filename, 'rb');
        if($this->fp === false){
            throw new Exception("cant open [$filename]");
        }
    }
    public function getGenerator(){
        while (($row = fgetcsv($this->fp, 0, $this->delimiter, $this->enclousure)) !== false) {
            yield $row;
        }
    }
    public function __destruct() {
        if($this->fp){
            fclose($this->fp);
        }
    }
}

foreach( (new CsvFileGenerator('mycsvfile.csv'))->getGenerator() as $line){
    #do some
}

去罗马的一种方式。 :-)

【讨论】:

    【解决方案2】:

    回调呢?

    function gen($i, $on_close = null, $on_error = null) {
        while ($i--) {
            yield $i;
    
            if ($i === 5 && is_callable($on_close)) {
                $on_close();
            }
        }
    }
    
    $closed = false;
    $gen = gen(10, function () use (&$closed) {
        $closed = true;
    });
    
    foreach ($gen as $x) {
        if ($closed) {
            break;
        }
    
        echo $x, PHP_EOL;
    }
    

    我承认它不漂亮。另一种选择可能是返回特殊类的实例,让您的主代码知道有问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-18
      • 2016-08-05
      • 2018-03-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多