找到你要的答案

Q:Flow: Convert object to array for CSV export

Q:流程:对象转换为CSV导出阵列

I want to export my object "mitglied" to a .csv-file. 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:

#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

line 494 is...

fputcsv($fp, $lines);

...so I think I have to convert the object "mitglied" to an array.

My the public function findTennis in my mitgliedRepository looks like that:

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

line 105 of course is

 ->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!

我想我出口对象是会员沙漠”到一个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 /应用程序/流程/数据/临时/发展/缓存/代码/ flow_object_classes / itoop_atc_controller_mitgliedcontroller.php线494

第494行是…

fputcsv($fp, $lines);

…所以我想我要转换的对象”是会员沙漠”到一个数组。

我的公共职能findtennis我mitgliedrepository看起来像:

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 \流\坚持\原则\结果::$ toArray在/var/www /应用程序/流程/数据/临时/发展/缓存/代码/ 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);

}

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

answer1: 回答1:

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

fputcsv expects it's 2nd parameter to be an array. That array will be written as a CSV line into single file, with each array element as column. When iterating over your $records variable, you get instances of your domain object class (so probably sth. like 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

toArray is a function that is offered by Doctrine QueryResult class. Typically, Doctrine queries do not fetch all objects returned by the query, but return an iterator that fetches and maps entities on-demand. The toArray method fetches all records at once and returns an array instead of the iterator. Your error occurs, because you try to access toArray as a property, and not calling it as a 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).

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. 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. Basically, it should go into a view. You can implement a custom view class for handling the CSV output.

For that, you need to implement the \TYPO3\Flow\Mvc\View\ViewInterface. The easiest way to do this is to subclass \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.

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

The error messages explained

# 1:警告:fputcsv()预计参数2是数组,对象在/var/www /应用程序/流程/数据/临时/发展/缓存/代码/ flow_object_classes / itoop_atc_controller_mitgliedcontroller.php线494

fputcsv预计的第二参数是一个数组。该阵列将写为CSV线为单文件,每个数组元素为柱。当遍历你的$记录变量,你得到你的域对象类的实例(所以可能某事喜欢itoop \ \ \ \是会员沙漠ATC域模型)。这是未定义的行为,因此警告。

# 1:注意:定义属性:Typo3 \流\坚持\原则\结果::$ toArray在/var/www /应用程序/流程/数据/临时/发展/缓存/代码/ flow_object_classes / itoop_atc_domain_repository_mitgliedrepository.php线105

toArray是一个函数的原则进行课。通常,主义查询不取全部由查询返回的对象,但返回一个迭代器和地图实体按需取。toArray方法获取一次所有记录并返回一个数组的迭代器。你的错误,因为你试图访问的toArray作为属性,而不称其为一种方法。下面的代码是正确的:

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

然而,这不会帮助你什么,因为在你的控制器,你仍然会在一列域实体(foreach迭代不在乎遍历迭代器或数组;这实际上是迭代器在PHP中的点)。

Quick&Dirty solution

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

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

Better solution

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

为此,你需要实现\网页\流\ MVC视图查看界面。做这个最简单的方法是子类\网页\流MVC视图abstractview。命名您的视图类<;packagenamespace >;\查看\ <;控制器& gt;动作& lt;格式>;(做某事喜欢itoop \ \ \ \ exportcsv ATC的观点是会员沙漠。在视图()方法实现你的CSV出口逻辑。流会自动拾取并自动使用视图类。

在这篇文章中深入地实现自定义视图-这是在德国,虽然,但根据您的类命名我怀疑不会是一个问题。

answer2: 回答2:

I solved the problem with arbitrary 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);

这个问题我解决了任意数据查询语言。正如我提到的,我认为问题是,我没有得到一个数组查询结果。但在我的库中有以下查询:

/**
* @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(\原则\ ORM \查询::hydrate_array);

doctrine2  flow-framework