Rolf b: HTML2PDF - PHP Schleife für neue Seite unterbrechen

Beitrag lesen

Sophie,

niemand will Dich ärgern. Du hast das Thema "Wartbarkeit" angesprochen. Und genau darum geht es. Dass Du Dedlfixens Konzeptvorschlag dann erstmal nicht durchschaut hast, daran sollten wir jetzt noch arbeiten.

Erstmal schauen wir uns eine Lösung an, die dein Grundgerüst unverändert lässt: Du kannst an der Stelle, wo Du $i inkrementierst, Code für den Seitenwechsel einbauen. Du musst das tun, wenn $i die Werte 5, 20, 35, 50, etc annimmt, oder anders formuliert, wenn ($i+10)%15==0 gilt. Du musst also statt dem hier:

<?php $i++; } ?>

folgendes tun:

<?php 
 if (($i+10)%15 == 0) {
?>
   </table>
  </page>
  <page>
   <page_header>...</page_header>
   <page_footer>...</page_footer>
   <table>
   <thead>...</thead>
   <tbody>
<?php 
 }
 $i++;
} ?>

Das kann man machen, das wird funktionieren, aber es ist unstrukturiert und hat mit mit aktuellen Programmier-Grundsätzen wie "Separation of Concerns" nichts mehr zu tun. Vor allem steht da dann exakt das, was Du außerhalb der Schleife auch schonmal geschrieben hast. Oder anders gesagt: Du hast große Teile deines Seitentemplates doppelt. Das kann man natürlich durch Auslagern in Funktionen mildern, es geht aber einfacher. Und genau dazu wollte Dedlfix Dich bewegen.

Wichtig zu verstehen ist, dass Du ein zweistufiges Problem hast. Stufe 1 ist der Seitenumbruch, Stufe 2 ist die Seitenaufbereitung aus einer Menge von Zeilen. Diese beiden Stufen sollte man nicht in einem Klumpen zu lösen versuchen.

Deine Hauptfunktion sollte in etwa so aussehen. Sie holt sich die auszugebende Tabelle und gibt sie seitenweise aus. Die Steuerung, ob die Seite 5 oder 15 Zeilen hat, übernimmt sie auch (was schon fast zu viel ist im Sinne von Clean Code, aber ich will's nicht übertreiben mit der Zerlegung). Weil ich jetzt eine Schleife über die Seiten habe, brauche ich mir die Seitenlänge nicht über die Zeilennummer rückzurechnen.

<?php 
	$test_pdf_ausgabe = test_pdf($mysqli);
  $zeilen = count($test_pdf_ausgabe);
  $i = 0;
  $len = 5;

  while ($i < $zeilen) {
     write_page($i+1, array_slice($test_pdf_ausgabe, $i, $len));
     $i += $len;
     $len = 15;
  }
?>

Die Funktion write_page macht den Rest. Ich übergebe ihr die Nummer ersten Zeile im Ausschnitt (weil Du die ausgeben willst) und die Zeilen für diese Seite. Das +1 bei der Zeilennummer ist drin, weil array_slice bei 0 anfängt und ich mich deshalb entscheiden muss, ob $i den Offset ins Array oder die Nummer für die Ausgabe darstellt. Ich habe mich für den Offset entschieden.

<?php 
function write_page($zeilennr, $zeilen) {
?>
<page> 
	<page_header> 
	 ...              
	</page_header> 
	<page_footer> 
	  page [[page_cu]]/[[page_nb]]
	</page_footer> 
  <table width="100%" id="tblArtikel"">
  	<thead class="thead">
      <tr style="height:2em; vertical-align:top;">
		    <td style="width:80px; padding-bottom: 10px;"><strong>Pos.</strong></td>
		    <td style="width:380px; padding-bottom: 10px;"><strong>Artikel</strong></td>
		    <td style="width:120px; padding-bottom: 10px;"><strong>Artikel Nr.</strong></td>
		  </tr>
    </thead>
    <tbody>
<?php foreach($zeilen as $zeile) { ?>
  		<tr style="height:1.5em; margin-bottom: 16px;">
	  		<td style="width:80px"><?= $zeilennr ?></td>
		  	<td style="width:380px"><?= htmlspecialchars($zeile['Bezeichnung']); ?></td>
  			<td style="width:120px"><?= htmlspecialchars($zeile['ArtikelNr']); ?></td>
	  	</tr>
<?php $zeilennr++; } ?>
    </tbody>
  </table>   
</page>
<?php } ?>

So, das ist jetzt ungetestet ins Forum getippert, keine Ahnung ob ein blöder Tibbfäler drin ist. Den htmlspecialchars für die Zeilennummer hab ich weggelassen, das ist unnötig, und statt <?php echo... habe ich die Kurzform <?= verwendet. Ansonsten ist die Seitendarstellung Dein Code.

Dedlfix hatte einen leicht anderen Plan - er wollte die Ausgabe des Seitenrahmens (also <page>, Header, Footer, ggf. auch <thead>) separat halten. Ich find's so aber eigentlich ganz schick, du hast auf diese Weise ein Seiten-Template schön beieinander.

Wenn Du auf Seite 1 einen anderen page_header ausgeben willst wie auf den restlichen Seiten, dann solltest Du entweder noch einen Seitenzähler in der Hauptfunktion führen und der write_page Funktion übergeben, oder einen Schalter "$erste_seite" verwenden, den Du der write_page Funktion mitgibst. Dann kommt man allerdings wieder in den Bereich, wo write_page zu groß wird; du solltest sie dann in drei Teile zerlegen: Ausgabe Header 1. Seite, Ausgabe Header 2.-N. Seite, Ausgabe der Datentabelle. Deine Entscheidung, ob und wie Du das machst.

Rolf