【问题标题】:Flow: Convert object to array for CSV export流程:将对象转换为数组以进行 CSV 导出
【发布时间】:2016-01-29 15:58:11
【问题描述】:

我想将我的对象“mitglied”导出到 .csv 文件。我的控制器看起来像这样:

public function exportAction() {

    // find all mitglieds
    $records = $this->mitgliedRepository->findTennis();

    // Set path for export-file
    $csvPath = '/var/www/apps/flow/Packages/Application/ITOOP.Atc/Resources/Private/Export/test.csv';

    $fp = fopen($csvPath, 'w');

    foreach ($records as $lines) {
        fputcsv($fp, $lines);
    }

    fclose($fp);
}

当我调用 exportAction 时,我收到一个错误:

#1:警告:fputcsv() 期望参数 2 是数组,对象在 /var/www/apps/flow/Data/Temporary/Development/Cache/Code/Flow_Object_Classes/itoop_atc_Controller_MitgliedController.php 第 494 行中给出

第 494 行是...

fputcsv($fp, $lines);

...所以我想我必须将对象“mitglied”转换为数组。

我的 mitgliedRepository 中的公共函数 findTennis 如下所示:

public function findTennis() {
    $query = $this->createQuery();
    $result = $query->matching($query->equals('abteilung', 'Tennis'))
                    ->setOrderings(array('name' => \TYPO3\Flow\Persistence\QueryInterface::ORDER_ASCENDING))
                    ->execute();

    return $result;
}

我试图设置 toArray();在这样的存储库中:

public function findTennis() {
    $query = $this->createQuery();
    $result = $query->matching($query->equals('abteilung', 'Tennis'))
                    ->setOrderings(array('name' => \TYPO3\Flow\Persistence\QueryInterface::ORDER_ASCENDING))
                    ->execute()
                    ->toArray;
    return $result;
}

然后我收到以下错误:

#1:注意:未定义的属性:TYPO3\Flow\Persistence\Doctrine\QueryResult::$toArray 在 /var/www/apps/flow/Data/Temporary/Development/Cache/Code/Flow_Object_Classes/itoop_atc_Domain_Repository_MitgliedRepository.php 行105

第 105 行当然是

 ->toArray;

有人知道,如何将对象转换为流中的数组吗?

通过以下示例,导出工作正常,所以我认为存储库查询的(格式)是问题所在。

public function exportAction() {
    // Set path for export-file
     $csvPath = '/var/www/apps/flow/Packages/Application/ITOOP.Atc/Resources/Private/Export/test.csv';

 $test = array (
     array('xxx', 'bbb', 'ccc', 'dddd'),
     array('123', '456', '789'),
     array('aaa', 'bbb')
 );


 $fp = fopen($csvPath, 'w');

 foreach ($test as $lines) {
     fputcsv($fp, $lines);
 }

 fclose($fp);

}

请指点我正确的方向。谢谢!

【问题讨论】:

    标签: doctrine-orm flow-framework


    【解决方案1】:

    错误信息解释

    #1:警告:fputcsv() 期望参数 2 是数组,对象在 /var/www/apps/flow/Data/Temporary/Development/Cache/Code/Flow_Object_Classes/itoop_atc_Controller_MitgliedController.php 第 494 行中给出

    fputcsv 期望它的第二个参数是一个数组。该数组将作为 CSV 行写入单个文件,每个数组元素作为列。当迭代你的$records 变量时,你会得到你的域对象类的实例(所以可能是这样的。像ITOOP\Atc\Domain\Model\Mitglied)。这是未定义的行为,因此是警告。

    #1:注意:未定义的属性:TYPO3\Flow\Persistence\Doctrine\QueryResult::$toArray 在 /var/www/apps/flow/Data/Temporary/Development/Cache/Code/Flow_Object_Classes/itoop_atc_Domain_Repository_MitgliedRepository.php 行105

    toArray 是 Doctrine QueryResult 类提供的函数。通常,Doctrine 查询不会获取查询返回的所有对象,而是返回一个iterator,它可以按需获取和映射实体。 toArray 方法一次获取所有记录并返回一个 array 而不是迭代器。发生错误是因为您尝试将toArray 作为属性访问,而不是将其作为方法调用。以下代码是正确的:

    $result = $query->matching($query->equals('abteilung', 'Tennis'))
                    ->setOrderings(array('name' => \TYPO3\Flow\Persistence\QueryInterface::ORDER_ASCENDING))
                    ->execute()
                    ->toArray(); // <- Mind the brackets!
    

    但是,这对您没有任何帮助,因为在您的控制器中,您仍将遍历域实体列​​表(foreach 不关心它是遍历迭代器还是数组;这实际上是重点PHP 中的迭代器)。

    快速而肮脏的解决方案

    在您的控制器中手动转换您的域实体。 只有您知道您的 CSV 导出应该是什么样子,所以这不能自动化。我在想这样的事情:

    foreach ($records as $record) {
        $csvLine = [
            $record->getFirstProperty(),
            $record->getSecondProperty(),
            // and so on...
        ];
        fputcsv($fp, $csvLine);
    }
    

    更好的解决方案

    渲染 CSV 数据是不应该在控制器中解决的问题。基本上,它应该进入一个视图。您可以实现自定义视图类来处理 CSV 输出。

    为此,您需要实现\TYPO3\Flow\Mvc\View\ViewInterface。最简单的方法是继承\TYPO3\Flow\Mvc\View\AbstractView。将您的视图类命名为 &lt;PackageNamespace&gt;\View\&lt;Controller&gt;\Action&lt;Format&gt;(等等。就像 ITOOP\Atc\View\Mitglied\ExportCsv。在视图的 render() 方法中实现您的 CSV 导出逻辑。Flow 将在视图类出现后立即拾取并自动使用它。

    this article 中深入解释了实现自定义视图——虽然它是德语,但根据您的类命名,我怀疑这不会成为问题;)。

    【讨论】:

    • 非常感谢您的详细解释。中间我用任意 DQL 解决了这个问题,就像我在下面的答案中解释的那样。
    【解决方案2】:

    我用任意 DQL 解决了这个问题。正如我所提到的,我认为问题在于我没有得到一个数组作为查询的结果。但是在我的存储库中使用以下查询:

    /**
    * @Flow\Inject
    * @var \Doctrine\Common\Persistence\ObjectManager
    * inject Doctrine's EntityManager to execute arbitrary DQL
    */
    protected $entityManager;    
    
    /**
    * find mitglieder with Abteilung Tennis und return an array
    */
    public function exportTennis() {
        $query = $this->entityManager->createQuery("SELECT mitglied FROM \itoop\atc\Domain\Model\Mitglied mitglied WHERE mitglied.abteilung = 'Tennis'");
        return $query->getResult(\Doctrine\ORM\Query::HYDRATE_ARRAY);
    }
    

    我认为重要的部分是 getResult(\Doctrine\ORM\Query::HYDRATE_ARRAY);

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-03-08
      • 2016-08-03
      • 2018-03-06
      • 2019-05-01
      • 2015-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多