流:将对象转换为CSV导出的数组



我想将我的对象"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/itop_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' => TYPO3FlowPersistenceQueryInterface::ORDER_ASCENDING))
->execute();
return $result;
}

我试图设置为Array();在类似的存储库中:

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

但后来我得到了以下错误:

#1:注意:未定义的属性:TYPO3\Flow\Persistence\Doctrine\QueryResult::/var/www/apps/Flow/Data/Temporary/Development/Cache/Code/Flow_Object_Classes/itop_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);

}

请给我指正确的方向。非常感谢。

解释的错误消息

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

fputcsv希望它的第二个参数是数组。该数组将作为CSV行写入单个文件,每个数组元素都作为列。当对$records变量进行迭代时,您会得到域对象类的实例(因此可能类似于ITOOPAtcDomainModelMitglied)。这是未定义的行为,因此是警告。

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

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

$result = $query->matching($query->equals('abteilung', 'Tennis'))
->setOrderings(array('name' => TYPO3FlowPersistenceQueryInterface::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输出。

为此,您需要实现TYPO3FlowMvcViewViewInterface。最简单的方法是对TYPO3FlowMvcViewAbstractView进行子类化。将视图类命名为<PackageNamespace>View<Controller>Action<Format>(与ITOOPAtcViewMitgliedExportCsv类似)。在视图的render()方法中实现CSV导出逻辑。一旦视图类出现,Flow就会自动拾取并使用它。

本文对实现自定义视图进行了深入的解释——虽然是用德语编写的,但根据您的类命名,我怀疑这不会成为问题;)。

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

/**
* @FlowInject
* @var DoctrineCommonPersistenceObjectManager
* 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 itoopatcDomainModelMitglied mitglied WHERE mitglied.abteilung = 'Tennis'");
return $query->getResult(DoctrineORMQuery::HYDRATE_ARRAY);
}

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

最新更新