Inici
Coders.cat

Navegació principal

  • Inici
  • Pallol

Menú del compte d'usuari

  • Entra

Fil d'ariadna

  • Inici
  • Generar i descarregar un csv de forma eficient a Drupal

Cerca

Etiquetes

  • php (6)
  • drupal (4)
  • devuan (2)
  • pallol (2)
  • javascript (2)
  • sistemes (1)
  • bash (1)
  • git (1)
  • css (1)
  • composer (1)
  • dart (1)
  • prism (1)
  • dust (1)
  • nuxt (1)
  • go (1)
  • vue (1)
  • java (1)
  • fail2ban (1)
  • perl (1)
  • ufw (1)
  • python (1)
  • apache (1)
  • ruby (1)
  • nodejs (1)
  • sql (1)
  • pdf (1)
  • tcpdf (1)
Icone de csv cap a php
Per aposai | 9:02 PM CEST, dl. maig 19, 2025

Generar i descarregar un csv de forma eficient a Drupal

Hi ha diverses estratègies per fer-ho, però sovint els programadors es fan alguna funció per agafar les dades de la base de dades, una altra per generar el csv, i potser alguna altra per servir-lo al client.

Al principi tot va bé, però donat que el volum de dades acostuma a créixer amb el temps arriba un moment que se'ls hi omple la memòria o els hi salten els timeouts, etc. I ens demanen als de sistemes que augmentem els recursos quan tot és culpa d'una mala estratègia.

Una solució és partir la tasca, generar el fitxer en bach i després oferir el resultat per descarregar.

Però i si hi hagués una solució millor? I si al mateix temps que llegim la base de dades anem generant el csv al mateix temps que ho servim al client?

Provem-ho amb la ajuda dels generators:

Ens creem un generator per llegir la bbdd:

public function getInvoices(string $startDate, string $endDate): Iterator {
  $results = $this->connection->select('invoices', 'i')
    ->fields('i')
    ->condition('date', [$startDate, $endDate], 'BETWEEN')
    ->execute();

  while (($record = $results->fetchObject())) {
    yield $record;
  }
}

Tot seguit al nostre controller, escrivim el csv directament a la sortida:

public function __invoke($from, $to): Response {
  $headers = [
    'Content-Disposition' => sprintf('attachment; filename="invoices-%s-%s.csv"', $from, $to),
    'Content-Type' => 'text/csv',
    'Cache-Control' => 'max-age=0',
  ];

  $invoices = $this->invoices->getInvoices($from, $to);

  return new StreamedResponse(function () use ($invoices) {
      $output = fopen('php://output', 'w');

      $fields = [
        'date',
        'quantity',
        'net',
        'discount',
        'invoice_number',
        'invoice_item',
      ];

      // Afegim BOM UTF-8 per compatibilitat amb Excel
      fwrite($output, chr(0xEF) . chr(0xBB) . chr(0xBF));
      fputcsv($output, $fields, ';');

      foreach ($invoices as $invoice) {
        $row = array_map(fn($field) => $invoice->{$field}, $fields);
        fputcsv($output, $row, ';');
      }

      fclose($output);
    }, Response::HTTP_OK, $headers);
}

I voilà, el csv se'ns comença a descarregar instantàniament i el servidor quasi ni s'entera.

 

 

drupal
php
  • Inicia sessió o registra't per fer comentaris

Comentaris

Footer menu

  • Contacte

© 2025 WTFPL – Do What the Fuck You Want to Public License.