Хобрук: Ваш путь к мастерству в программировании

Поток: преобразование объекта в массив для экспорта в 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/itoop_atc_Controller_MitgliedController.php, строка 494.

строка 494...

fputcsv($fp, $lines);

... поэтому я думаю, что мне нужно преобразовать объект "mitglied" в массив.

Моя публичная функция 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: Примечание: свойство Undefined: 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);

}

Пожалуйста, укажите мне правильное направление. Благодарю вас!


Ответы:


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: Примечание: свойство Undefined: 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 не извлекают все объекты, возвращаемые запросом, а возвращают итератор который извлекает и отображает объекты по запросу. Метод 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).

Быстрое и грязное решение

Преобразуйте свои объекты домена вручную в своем контроллере. Только вы можете знать, как должен выглядеть ваш экспорт 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. Назовите свой класс представления <PackageNamespace>\View\<Controller>\Action<Format> (например, ITOOP\Atc\View\Mitglied\ExportCsv. Реализуйте свою логику экспорта CSV в методе представления render(). Flow автоматически подберет и будет использовать класс представления, как только он появится.

Реализация настраиваемых представлений подробно описана в этой статье. - хотя это на немецком языке, хотя, судя по названию вашего класса, я подозреваю, что это не будет проблемой;).

03.05.2015
  • Большое спасибо за подробное объяснение. Промежуточно я решил проблему с произвольным DQL, как описано в моем следующем ответе. 05.05.2015

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

    05.05.2015
    Новые материалы

    Создание кнопочного меню с использованием HTML, CSS и JavaScript
    Вы будете создавать кнопочное меню, которое имеет состояние наведения, а также позволяет вам выбирать кнопку при нажатии на нее. Финальный проект можно увидеть в этом Codepen . Шаг 1..

    Внедрите OAuth в свои веб-приложения для повышения безопасности
    OAuth — это широко распространенный стандарт авторизации, который позволяет приложениям получать доступ к ресурсам от имени пользователя, не раскрывая его пароль. Это позволяет пользователям..

    Классы в JavaScript
    class является образцом java Script Object. Конструкция «class» позволяет определять классы на основе прототипов с чистым, красивым синтаксисом. // define class Human class Human {..

    Как свинг-трейдеры могут использовать ИИ для больших выигрышей
    По мере того как все больше и больше профессиональных трейдеров и активных розничных трейдеров узнают о возможностях, которые предоставляет искусственный интеллект и машинное обучение для улучшения..

    Как построить любой стол
    Я разработчик программного обеспечения. Я люблю делать вещи и всегда любил. Для меня программирование всегда было способом создавать вещи, используя только компьютер и мое воображение...

    Обзор: Машинное обучение: классификация
    Только что закончил третий курс курса 4 часть специализации по машинному обучению . Как и второй курс, он был посвящен низкоуровневой работе алгоритмов машинного обучения. Что касается..

    Разработка расширений Qlik Sense с qExt
    Использование современных инструментов веб-разработки для разработки крутых расширений Вы когда-нибудь хотели кнопку для установки переменной в приложении Qlik Sense? Когда-нибудь просили..