简体   繁体   English

流:将对象转换为数组以进行CSV导出

[英]Flow: Convert object to array for CSV export

I want to export my object "mitglied" to a .csv-file. 我想将我的对象“ mitglied”导出到一个.csv文件。 My controller looks like that: 我的控制器如下所示:

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);
}

When I call the exportAction, I get a an error: 当我调用exportAction时,出现错误:

#1: Warning: fputcsv() expects parameter 2 to be array, object given in /var/www/apps/flow/Data/Temporary/Development/Cache/Code/Flow_Object_Classes/itoop_atc_Controller_MitgliedController.php line 494 #1:警告:fputcsv()期望参数2为数组,对象位于/var/www/apps/flow/Data/Temporary/Development/Cache/Code/Flow_Object_Classes/itoop_atc_Controller_MitgliedController.php行中

line 494 is... 494行是...

fputcsv($fp, $lines);

...so I think I have to convert the object "mitglied" to an array. ...所以我认为我必须将“ mitglied”对象转换为数组。

My the public function findTennis in my mitgliedRepository looks like that: 我的mitgliedRepository中的public函数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;
}

I tried to set toArray(); 我试图设置toArray(); in the repository like the that: 在这样的存储库中:

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;
}

But then I get the following error: 但是然后我得到以下错误:

#1: Notice: Undefined property: TYPO3\\Flow\\Persistence\\Doctrine\\QueryResult::$toArray in /var/www/apps/flow/Data/Temporary/Development/Cache/Code/Flow_Object_Classes/itoop_atc_Domain_Repository_MitgliedRepository.php line 105 #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行中

line 105 of course is 第105行当然是

 ->toArray;

Does anybody know, how to convert an object to an array in flow? 有人知道如何在流中将对象转换为数组吗?

With the following example the export works, so I think the (formatting of the) repository query is the problem. 在下面的示例中,导出有效,因此我认为存储库查询(的格式)是问题所在。

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);

} }

Please point me to the right direction. 请指出正确的方向。 Thank you! 谢谢!

The error messages explained 错误消息说明

#1: Warning: fputcsv() expects parameter 2 to be array, object given in /var/www/apps/flow/Data/Temporary/Development/Cache/Code/Flow_Object_Classes/itoop_atc_Controller_MitgliedController.php line 494 #1:警告:fputcsv()期望参数2为数组,对象位于/var/www/apps/flow/Data/Temporary/Development/Cache/Code/Flow_Object_Classes/itoop_atc_Controller_MitgliedController.php行中

fputcsv expects it's 2nd parameter to be an array. fputcsv期望它的第二个参数是一个数组。 That array will be written as a CSV line into single file, with each array element as column. 该数组将作为CSV行写入到单个文件中,每个数组元素作为一列。 When iterating over your $records variable, you get instances of your domain object class (so probably sth. like ITOOP\\Atc\\Domain\\Model\\Mitglied ). $records变量上进行迭代时,您将获得域对象类的实例(例如ITOOP\\Atc\\Domain\\Model\\Mitglied )。 That's undefined behaviour, thus the warning. 那是不确定的行为,因此是警告。

#1: Notice: Undefined property: TYPO3\\Flow\\Persistence\\Doctrine\\QueryResult::$toArray in /var/www/apps/flow/Data/Temporary/Development/Cache/Code/Flow_Object_Classes/itoop_atc_Domain_Repository_MitgliedRepository.php line 105 #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行中

toArray is a function that is offered by Doctrine QueryResult class. toArray是Doctrine QueryResult类提供的功能。 Typically, Doctrine queries do not fetch all objects returned by the query, but return an iterator that fetches and maps entities on-demand. 通常,Doctrine查询不会获取查询返回的所有对象,而是返回一个迭代器 ,该迭代器按需获取和映射实体。 The toArray method fetches all records at once and returns an array instead of the iterator. toArray方法一次获取所有记录,并返回一个数组,而不是迭代器。 Your error occurs, because you try to access toArray as a property, and not calling it as a method . 发生错误是因为您尝试将toArray 作为属性访问,而不是将其作为method调用 The following code would be correct: 以下代码将是正确的:

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

However, this will not help you anything, because in your controller, you will still be iterating over a list of domain entities ( foreach does not care if its iterating over an iterator or an array; that's actually the point of iterators in PHP). 但是,这将无济于事,因为在控制器中,您仍将在域实体列表上进行迭代( foreach并不关心其是否在迭代器或数组上进行迭代;这实际上是PHP中迭代器的重点)。

Quick&Dirty solution 快速与肮脏的解决方案

Convert your domain entities by hand in your controller. 手动在您的控制器中转换您的域实体。 Only you can know how your CSV export should look like , so this cannot be automated. 只有您知道CSV导出的外观 ,因此无法自动进行。 I'm thinking something like this: 我在想这样的事情:

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

Better solution 更好的解决方案

Rendering CSV data is not a concern that should be addressed in the controller . 呈现CSV数据不是控制器应该解决的问题 Basically, it should go into a view. 基本上,它应该进入视图。 You can implement a custom view class for handling the CSV output. 您可以实现用于处理CSV输出的自定义视图类。

For that, you need to implement the \\TYPO3\\Flow\\Mvc\\View\\ViewInterface . 为此,您需要实现\\TYPO3\\Flow\\Mvc\\View\\ViewInterface The easiest way to do this is to subclass \\TYPO3\\Flow\\Mvc\\View\\AbstractView . 最简单的方法是将\\TYPO3\\Flow\\Mvc\\View\\AbstractView子类化。 Name your view class <PackageNamespace>\\View\\<Controller>\\Action<Format> (so sth. like ITOOP\\Atc\\View\\Mitglied\\ExportCsv . Implement your CSV export logic in the view's render() method. Flow will pick up and use the view class automatically as soon as it's present. 将您的视图类命名为<PackageNamespace>\\View\\<Controller>\\Action<Format> (诸如此类,例如ITOOP\\Atc\\View\\Mitglied\\ExportCsv 。在视图的render()方法中实现CSV导出逻辑。流程将开始)并在存在时自动使用视图类。

Implementing custom views is explained in depth in this article -- it's in German though, although based on your class naming I suspect that won't be a problem ;). 本文将详细解释实现自定义视图的方法-尽管它是德语版本,但是基于您的类命名,我怀疑这不会有问题;)。

I solved the problem with arbitrary DQL. 我用任意DQL解决了这个问题。 As I mentioned I think the problem was that I didn't got an array as result by the query. 正如我提到的那样,我认为问题在于查询没有得到数组。 But with the following query in my repository I do: 但是,在我的存储库中使用以下查询时,我会这样做:

/**
* @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);
}

The important part I think is getResult(\\Doctrine\\ORM\\Query::HYDRATE_ARRAY); 我认为重要的部分是getResult(\\ Doctrine \\ ORM \\ Query :: HYDRATE_ARRAY);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM