Sophie: HTML2PDF - PHP Schleife für neue Seite unterbrechen

Hallo,

puh, ich beschäftige mich seit ein paar Tagen mit HTML2PDF. Das Tool kann wirklich viel und ist zumindest wenn man keine großen Änderungen haben möchte recht einfach zu nutzen.

Jetzt komme ich allerdings an einen Punkt wo ich selber nicht weiter komme. Fangen wir ganz bei 0 an. Mein Aufbau ist

<page> 
	<page_header> 
	 ...              
	</page_header> 
	<page_footer> 
	  page [[page_cu]]/[[page_nb]]
	</page_footer> 
<?php 
	$i = 1;
	$test_pdf_ausgabe = test_pdf($mysqli);
?>

<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($test_pdf_ausgabe as $array){ ?>
		
		<tr style="height:1.5em; margin-bottom: 16px;">
			<td style="width:80px"><?php echo htmlspecialchars($i) ?></td>
			<td style="width:380px"><?php echo htmlspecialchars($array['Bezeichnung']); ?></td>
			<td style="width:120px"><?php echo htmlspecialchars($array['ArtikelNr']); ?></td>
		</tr>

	<?php $i++; } ?>
	</tbody>

</table>
</page> 

Klappt auch soweit wunderbar. Jetzt kommt für mich das große Problem. Auf der ersten Seite möchte ich gerne nur 5 Einträge ausgaben. Auf ALLEN anderen maximal jeweils 15. Eine weitere Seite legt man in HTML2PDF mit

<page pageset="old">
  Hier der Inhalt von Seite zwei
</page>

Kann mir vielleicht von euch bei der Umsetzung jemand helfen oder mir zumindest Tipps geben, wie ich das ganze angehen könnte? Ich bin irgendwie Ratlos. eine PHP Schleife kann man doch nicht unterbrechen? Bzw. es muss ja zum Teil ganze HTML Teile hinzugefügt werden?

an.

akzeptierte Antworten

  1. Tach!

    Auf der ersten Seite möchte ich gerne nur 5 Einträge ausgaben. Auf ALLEN anderen maximal jeweils 15. Kann mir vielleicht von euch bei der Umsetzung jemand helfen oder mir zumindest Tipps geben, wie ich das ganze angehen könnte?

    • Also solange noch Einträge im Array vorhanden sind:
      • Kopf ausgeben
      • Die Anzahl ist, wenn Seite 1 dann 5, ansonsten 15.
      • Schneide $Anzahl Elemente aus dem Array und ruf die Ausgabeschleife auf.
      • Fuß ausgeben

    eine PHP Schleife kann man doch nicht unterbrechen?

    Doch, break und continue existeren. Braucht es aber nach obigem Plan nicht.

    dedlfix.

    1. Hallo @dedlfix,

      leider verstehe ich überhaupt nicht, was du mir sagen willst. Ich bin gerade kein Stück schlauer bzw. ich habe eher noch viel mehr ???? vor meinen Augen.

      1. Tach!

        leider verstehe ich überhaupt nicht, was du mir sagen willst.

        Du fragtest, wie man die Sache angehen kann. Ich habe einen eigenen Plan aufgezeigt, wie ich die Sache lösen würde. Das war ein komplettes (neues) Konzept und keine Ergänzung zu deinem Lösungsansatz. Du versucht, aus der Schleife heraus zu steuern. Du müsstest dann jeweils die alte Seite beenden und eine neue anfangen. Aber Anfang und Ende hast du auch noch außen drumherum. Diese Dopplung muss nicht sein. Mein Plan hingegen hat die Steuerung, welche Datensätze auszugeben sind, außerhalb der Schleife. Auch das Ausgeben von Kopf und Fuß ist ohne Code-Wiederholung gelöst. Ich habe zwei Schleifen geschachtelt. Die eine läuft solange noch Datensätze übrig sind und erzeugt jeweils eine Seite. Die innere Schleife (die Datensatzschleife) gibt die Datensätze der Seite aus.

        Am Anfang ist das Array vollständig. Im ersten Durchlauf werden daraus 5 Datensätze ausgeschnitten und mit diesen die Datensatzschleife durchlaufen. Zum Manipulieren von Arrays gibt es eine umfangreiche Funktionssammlung. array_splice() ist für diesen Fall geeignet. Der nächste Durchlauf findet statt, wenn im ersten Array noch Datensätze übrig sind, ansonsten ist Schluss. Von diesem Rest werden 15 Stück ausgeschnitten und die Datensatzschleife aufgerufen. Und so weiter und so fort.

        dedlfix.

        1. Hallo @dedlfix,

          das ist leider nicht das was ich benötige. Wie oben bereits geschrieben benötige ich für die weiteren Seite folgenden Code

          <page pageset="old"></page>
          

          Auf der ersten Seite benötige ich nur

          <page></page>
          

          Außerdem macht es keinen Sinn auf den weiteren Seiten die Anschrift die in

          <page_header> </page_header> 
          

          zu wiederholen.

          1. Tach!

            Auf der ersten Seite benötige ich nur [...]

            Außerdem macht es keinen Sinn auf den weiteren Seiten die Anschrift [...] zu wiederholen.

            Das kann man mit if-else steuern.

            dedlfix.

            1. Hallo @dedlfix

              warum kann man es nicht so hinnehmen wie ich es gerne hätte? Wenn ich mehrere Seiten haben möchte wie es in der Dokumentation steht, dann ist das so. Ich muss später den Code pflegen.

              Und

               page [[page_cu]]/[[page_nb]]
              

              funktioniert nur, wenn man es mit mehreren Seiten macht.

              1. Tach!

                warum kann man es nicht so hinnehmen wie ich es gerne hätte?

                Weil ich eine Realisierung auf desem Weg für umständlicher halte als meinen Vorschlag. Zudem hast du danach gefragt.

                Kann mir vielleicht von euch bei der Umsetzung jemand helfen oder mir zumindest Tipps geben, wie ich das ganze angehen könnte?

                Ich hab "das ganze" auf das Ganze bezogen interpretiert.

                Ich muss später den Code pflegen.

                Du darfst den auch gern ignorieren, wenn du ihn nicht magst. Wie man Schleifen steuert, habe ich ja erwähnt.

                dedlfix.

                1. Hallo,

                  ist OK, ich frage in einem anderen Forum nach.
                  Ist wohl zu viel verlangt eine vernünftige Antwort zu erwarten.

                  1. Hallo Sophie,

                    Ist wohl zu viel verlangt eine vernünftige Antwort zu erwarten.

                    Du hast eine vernünftige Antwort bekommen. Ich halte break und continue für wenig robust, vor allem da du vorher schon weist, an welchen Stellen du Unterbrechungen haben möchtest.

                    Bis demnächst
                    Matthias

                    --
                    Rosen sind rot.
                    1. Hallo @Matthias Apsel

                      wo habe ich bitte eine vernüftige Antwort erhalten? Ich habe bereits im zweiten Posting geschrieben dass ich nichts verstehe! @dedlfix hat gerade weiter geschrieben ging null darauf ein dass ich nichts verstanden habe.

                      1. Liebe Sophie,

                        wo habe ich bitte eine vernüftige Antwort erhalten? Ich habe bereits im zweiten Posting geschrieben dass ich nichts verstehe!

                        bei allem Respekt, aber dedlfix' Antwort war wirklich vernünftig. Dass Du das aus Deinem momentanen Kenntnisstand heraus noch nicht beurteilen kannst, ist keine Schande. Dass Du aber fest darauf bestehst, dass nur der von Dir gewählte Ansatz vernünftig sei, und dass die Lösung, die wir Dir liefern sollen, grundsätzlich diesen Ansatz "reparieren" soll, ist weder guter Stil, noch zeugt es von Lernbereitschaft.

                        Zugegeben, es fällt schwer, sich von einem einmal eingeschlagenen Lösungsweg zu verabschieden, nachdem man damit sehr viel Zeit verbracht hat und schon Teilerfolge sehen kann. Aber wenn erfahrene Experten wie dedlfix aufzeigen, dass es anders (wirklich!) besser(!) geht, dann solltest Du nicht emotional, sondern lernwillig reagieren! Immerhin haben wir in diesem Forum das Motto "die Energie des Verstehens".

                        @dedlfix hat gerade weiter geschrieben ging null darauf ein dass ich nichts verstanden habe.

                        Er erwartet nicht, dass Du ihm dankst. Aber dass Du im Falle von Lernwilligkeit versuchst, seinen Ansatz zu studieren und zu verstehen, das darf er mit Recht erwarten. Und da er es wirklich besser weiß, ist es sein gutes Recht, Deinen Ansatz nicht weiter zu verfolgen, da er weniger gut geeignet ist, als sein neuer.

                        Du musst das alles jetzt nicht akzeptieren und darfst gerne in anderen Foren um Rat fragen, aber die beste Antwort hast Du von dedlfix schon bekommen.

                        Liebe Grüße,

                        Felix Riesterer.

                        1. Hallo @Felix Riesterer

                          Du musst das alles jetzt nicht akzeptieren und darfst gerne in anderen Foren um Rat fragen, aber die beste Antwort hast Du von dedlfix schon bekommen.

                          sorry die Antwort ist doch falsch. In der Doku von HTML2PDF steht doch, dass man für die weiteren Seiten

                          <page pageset="old"></page pageset="old">
                          

                          benötigt. Ihr geht auf dieses überhaupt nicht ein. Hauptsache euer Kopf wird durchgesetzt scheiß egal was ein Entwickler von einer Funktion schreibt. Das ist einfach nicht OK und möchte ich auch nicht haben.

                          1. Liebe Sophie,

                            sorry die Antwort ist doch falsch.

                            warum?

                            In der Doku von HTML2PDF steht doch, dass man für die weiteren Seiten

                            <page pageset="old"></page pageset="old">
                            

                            benötigt.

                            Hat das irgendjemand bestritten?

                            Ihr geht auf dieses überhaupt nicht ein.

                            Dieses Detail ist nicht das, was Dein Problem verursacht oder löst. Es ist ein Detail, das es beim Zusammenstellen des Codes zu berücksichtigen gilt. Wo und wie und wann man diesen Code-Schnipsel einfügt, das ist das, was dedlfix auf andere Weise zu erreichen sucht. Und das siehst Du nicht.

                            Hauptsache euer Kopf wird durchgesetzt scheiß egal was ein Entwickler von einer Funktion schreibt. Das ist einfach nicht OK und möchte ich auch nicht haben.

                            Ich kann mir sehr gut vorstellen, dass sich die bisherige Entwicklung dieser Diskussion genau so für Dich anfühlen muss. Aber glaube mir, es ist mehr dahinter.

                            Liebe Grüße,

                            Felix Riesterer.

                          2. Hi,

                            sorry die Antwort ist doch falsch. In der Doku von HTML2PDF steht doch, dass man für die weiteren Seiten

                            <page pageset="old"></page pageset="old">
                            

                            benötigt.

                            Mit Sicherheit nicht! Schließende Tags haben keine Attribute!

                            cu,
                            Andreas a/k/a MudGuard

                      2. Tach!

                        @dedlfix hat gerade weiter geschrieben ging null darauf ein dass ich nichts verstanden habe.

                        Weißt du, ich bin kein Hellseher, ich kann deine Gedankengänge also nicht sehr gut erraten, und auch deinen Wissensstand kenne ich kaum bis gar nicht. Mir nützt es dann gar nicht weiter, wenn du lediglich "nichts verstanden" schreibst. Ich weiß dann nämlich nicht, wo ich ansetzen muss. Hab ich aus deiner Sicht zu viele Fachbegriffe verwendet? Ist mein Konzept für dich undurchsichtig? Ist meine Antwort stilistisch unverständlich? Ist es irgendwas ganz anderes?

                        Ich kann dann nur meinen Gedankengang wiederholen, vielleicht anders formulieren und etwas ausführlicher darlegen, aber ob du es dann verstehst, kann ich nicht wissen. Du musst dann schon konkreter werden, wo das Problem beim Verstehen liegt.

                        dedlfix.

                  2. 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

                    1. Hallo @Rolf b

                      vielen lieben Dank für deine Hilfe und den Code. Aber ich bleibe bei meiner Aussage, ich benötige mehrere

                      <page></page>
                      

                      bzw. für die fortlaufenden Seiten benötige ich

                      <page pageset="old"></page pageset="old">
                      

                      da wird von euch beiden überhaupt nicht drauf eingegangen. Ich frage mich warum dann die ganze Diskussion? Das macht mich einfach nur richtig aggressiv

                      1. Ja, darauf bin ich nicht eingegangen. Weil ich dieses Detail übersehen habe. Und weil ich alles, was ich von HTML2PDF weiß, aus deinem Eingangsposting erfahren habe? Insofern kann ich die Details zur Ansteuerung von HTML2PDF nur deiner eigenen Kompetenz überlassen.

                        Aber ich habe Dich ja darauf hingewiesen, wie man in write_page eine Steuerung für "erste Seite" und "Folgeseite" realisieren kann. Entweder übergibst Du die Seitennummer, oder einen Schalter für "erste Seite". Hier mal mit $ersteSeite gezeigt. In der Hauptfunktion kannst Du $ersteSeite als eigene Variable führen und analog $len behandeln, oder Du nutzt aus, dass $len für die erste Seite den Wert 5 hat und schreibst einfach write_page($len==5, $i, array_slice(...));. Ich setze jetzt einfach mal voraus, dass Du PHP soweit verstanden hast, dass ich Dir nicht erklären muss, was diese Zeile tut. Wenn doch, frag ruhig. Ich weiß nicht, wieviel PHP Du kannst.

                        Mit $ersteSeite als Parameter für die Funktion kannst Du nun unterscheiden, wie Du die Seite aufbauen musst.

                        function write_page($ersteSeite, $zeilennr, $zeilen) {
                          if ($ersteSeite) {
                        ?>
                          <page pageset="new">
                            ... hier HTML für Erste Seite
                        <?php
                          }
                          else {
                        ?>
                          <page pageset="old">
                            ... hier HTML für Folgeseiten 
                        <?php
                          }
                        ?>
                          <page_footer>...</page_footer>
                          ... weiteres HTML für Elemente vor der Tabelle (falls nötig)
                          <table>
                             ... hier die Seitenüberschrift und Datenzeilen
                          </table>
                        </page>
                        }
                        

                        Wenn Du tatsächlich das pageset="old" Attribut auch ans </page> Tag hängen musst - was ich jetzt mal nicht annehmen würde - dann musst Du da, wo </page> steht, auch einen if ($ersteSeite) machen.

                        Wo Du page_header und page_footer anordnen musst, kann ich Dir nicht sagen. Ich weiß z.B. nicht, ob pageset="old" dafür sorgt, ob Header und Footer von der Seite mit pageset="new" übernommen werden. Ob also page_header und page_footer in den IF hinein müssen oder hinter den IF gehören, musst Du selbst herausfinden.

                        Rolf

                        1. Hallo @Rolf b,

                          Aber ich habe Dich ja darauf hingewiesen, wie man in write_page eine Steuerung für "erste Seite" und "Folgeseite" realisieren kann. Entweder übergibst Du die Seitennummer, oder einen Schalter für "erste Seite". Hier mal mit $ersteSeite gezeigt. In der Hauptfunktion kannst Du $ersteSeite als eigene Variable führen und analog $len behandeln, oder Du nutzt aus, dass $len für die erste Seite den Wert 5 hat und schreibst einfach write_page($len==5, $i, array_slice(...));. Ich setze jetzt einfach mal voraus, dass Du PHP soweit verstanden hast, dass ich Dir nicht erklären muss, was diese Zeile tut. Wenn doch, frag ruhig. Ich weiß nicht, wieviel PHP Du kannst.

                          danke nochmals für deine Hilfe. Ich dachte ich könnte es so umsetzten, weil du ja geschrieben hast gleich wie $len

                          <?php 
                            $test_pdf_ausgabe = test_pdf($mysqli);
                            $zeilen = count($test_pdf_ausgabe);
                            $i = 0;
                            $len = 5;
                            $ersteSeite = 5;
                          
                            while ($i < $zeilen) {
                               write_page($i+1, array_slice($test_pdf_ausgabe, $i, $len, $ersteSeite));
                               $i += $len;
                               $len = 15;
                               $i += $ersteSeite;
                               $ersteSeite = 15;
                            }
                          ?>
                          

                          Wenn du vielleicht nochmals Zeit hast, könntest du mir es dann nochmals erklären? Oder benötige ich dafür eine komplett neue while-Schleife?

                          1. Hallo Sophie,

                            zwei Dinge sind da anzumerken:

                            (1) Ich hatte mit $ersteSeite als booleschen Wert vorgestellt, den du ANALOG zu $len füllen solltest. Nicht identisch wie $len, und zu $i addieren musst Du es auch nicht. Es geht ausschließlich darum, dass write_page() beim ersten Durchlauf für $ersteSeite den Wert true erhält, und für die Folgedurchläufe den Wert false.

                            (2) Du bist auf die Schachtelung der Funktionsaufrufe hineingefallen. write_page hatte in meinem ersten Vorschlag zwei Parameter: Die Startzeilennummer und die Tabelle mit den auszugebenden Zeilen. Den zweiten Parameter habe ich mittels array_slice bestimmt.

                            Du hast $ersteSeite jetzt als vierten Parameter an array_slice übergeben, das versteht diese Funktion aber nicht (bzw. sie versteht da was, aber nicht das, was Du willst. Siehst Du in der PHP Doku...). Ich verteile den Aufruf mal auf mehrere Zeilen, dann siehst Du den Unterschied:

                               // Meine Ursprungsfassung:
                               write_page(
                                    $i+1,
                                    array_slice($test_pdf_ausgabe, $i, $len)
                               );
                            
                               // Deine erweiterte Fassung:
                               write_page(
                                    $i+1,
                                    array_slice($test_pdf_ausgabe, $i, $len, $ersteSeite)
                               );
                            
                               // Was Du aber brauchst:
                               write_page(
                                    $i+1,
                                    array_slice($test_pdf_ausgabe, $i, $len),
                                    $ersteSeite
                               );
                            

                            Du musst da genau auf die Klammern achten, damit der Parameter an die richtige Funktion geht.

                            Und: Wenn Du es so machst, dass $ersteSeite hinten dran hängt, musst Du natürlich auch die Definition von write_page entsprechend machen. Mein Vorschlag war, $ersteSeite als ersten Parameter zu übergeben. Du wolltest ihn lieber hinten haben - ist ok - dann musst Du für die Funktion schreiben:

                            function write_page($zeilennr, $zeilen, $ersteSeite) {
                            ...
                            }
                            

                            weil Parameter ja per Position zugeordnet werden.

                            Es muss also so aussehen:

                            <?php 
                              $test_pdf_ausgabe = test_pdf($mysqli);
                              $zeilen = count($test_pdf_ausgabe);
                              $i = 0;
                              $len = 5;
                              $ersteSeite = true;
                            
                              while ($i < $zeilen) {
                                 write_page($i+1, array_slice($test_pdf_ausgabe, $i, $len), $ersteSeite);
                                 $i += $len;
                                 $len = 15;
                                 $ersteSeite = false;
                              }
                            ?>
                            

                            Man kann das verkürzen, dann wird es aber etwas abstrakter. $len==5 ist ein boolescher Ausdruck. Er vergleicht $len mit 5 und liefert true oder false zurück. Also eigentlich genau das, was Du für $ersteSeite brauchst. Das folgende Stück Code tut das Gleiche wie das vorige, braucht aber keine Variable für $ersteSeite. Der Wert wird mit einem Ausdruck bestimmt:

                            <?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), $len==5);
                                 $i += $len;
                                 $ersteSeite = false;
                              }
                            ?>
                            

                            Nimm die Variante, die Du verstehst.

                            Rolf

                            1. Hallo @Rolf b

                              danke nochmals für deine Erklärung. Allerdings wenn ich deinen Code jetzt nutze werden pro Seite einfach alle Einträge ausgelesen. Es klappt einfach nicht 😕

                              Ich habe es so versucht

                              <?php 
                                $test_pdf_ausgabe = test_pdf($mysqli);
                                $zeilen = count($test_pdf_ausgabe);
                                $i = 0;
                                $len = 5;
                                $ersteSeite = true;
                              
                                while ($i < $zeilen) {
                                   write_page($i+1, array_slice($test_pdf_ausgabe, $i, $len), $ersteSeite);
                                   $i += $len;
                                   $len = 15;
                                   $ersteSeite = false;
                                }
                              ?>
                              
                              <?php 
                              function write_page($zeilennr, $zeilen, $ersteSeite) {
                              ?>
                              <page backtop="1%" backbottom="1%" backleft="5%" backright="5%"> 
                              
                              	<page_footer> 
                              	 <?php if ($ersteSeite == false) {
                              	 	echo "hallo";
                              	 } ?>
                              	</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 } ?>
                              
                              1. Hallo @Rolf b

                                es ist einfach zu viel heute. Ich habe den Fehler gefunden.

                                <page_footer> 
                                	 <?php if ($ersteSeite == true) {
                                	 	echo "hallo";
                                	 } ?>
                                	</page_footer> 
                                

                                Wie können das Menschen nur jeden Tag 8 Stunden machen?

                                1. Du schreibst:

                                  Allerdings wenn ich deinen Code jetzt nutze werden pro Seite einfach alle Einträge ausgelesen.

                                  Und dann sagst Du: Fehler gefunden - true statt false...

                                  <page_footer> 
                                  	 <?php if ($ersteSeite == true) {
                                  	 	echo "hallo";
                                  	 } ?>
                                  	</page_footer> 
                                  

                                  Versteh ich nun nicht, das eine hat mit dem anderen nichts zu tun. Welche Zeilen auf die Seite kommen, wird in der Hauptfunktion durch den array_slice-Aufruf bestimmt.

                                  Naja, Hauptsache ist, wenn es jetzt funktioniert UND wenn Du weißt, wie und warum es funktioniert.

                                  Übrigens seh ich gerade: ich habe Dir ein potenzielles Verwirrstück eingebrockt: In der Hauptfunktion bezeichnet $zeilen die Anzahl der Zeilen, die aus der Datenbank kommen, und in write_page bezeichnet es die auszugebenden Datenzeilen. Ist technisch natürlich kein Problem, aber ggf. bringt es Dich durcheinander. Vielleicht ist es besser, wenn Du - nur in der Hauptfunktion - $zeilen in $anzZeilen umbenennst. Sind 2 Stellen, die Zeile mit dem count() und die while-Zeile.

                                  Wie können das Menschen nur jeden Tag 8 Stunden machen?

                                  Och, ich mach das auch schonmal 10 Stunden, und am Wochenende sitz ich vor dem Forum und erkläre den Leuten PHP und MYSQL.

                                  Rolf

                                2. Moin Sophie!

                                  Wie können das Menschen nur jeden Tag 8 Stunden machen?

                                  Sie haben bereits mehr Übung darin als du (nicht abwertend gemeint, das kommt mit der Zeit) und können sich daher hauptsächlich mit der Lösung des Problems beschäftigen und müssen sich nicht parallel die Grundlagen der Programmierung allgemein und speziell die Eigenschaften einer Sprache oder eines Werkzeugs aneignen. Das ist dann weniger ermüdend, als wenn man zig Nebenschauplätze hat.

                                  Natürlich hat man ab und an immer wieder nervige Probleme, die man nicht auf Anhieb lösen kann, aber meist hilft einem dann die bereits auf anderen (Teil-)Gebieten gewonnene Erfahrung bei der Fehlersuche, ein Forum, Kollegen, Mitmenschen mit einem unverstellten Blick oder eine kleine Pause mit einem Kaffee ☕️.

                                  Dran bleiben!
                                  Julius

                      2. Tach!

                        vielen lieben Dank für deine Hilfe und den Code. Aber ich bleibe bei meiner Aussage, ich benötige mehrere

                        <page></page>
                        

                        bzw. für die fortlaufenden Seiten benötige ich

                        <page pageset="old"></page pageset="old">
                        

                        da wird von euch beiden überhaupt nicht drauf eingegangen.

                        Das ist eine Fallunterscheidung. Wenn große Teile gleich sind, aber an einer Stelle ein Unterschied ist, dann kann man den mit if-else oder bei noch mehr Unterschieden auch mit switch separat behandeln.

                        Wenn man das "ist das Seite 1?" für die if-Bedingung nicht aus den Daten selbst ermitteln kann, kann man sich dazu auch eine boolesche Variable setzen, die man mit true initialisiert und nach dem ersten Durchlauf auf false stellt, woraufhin man im weiteren Verlauf nicht mehr die Sonderbehandlung der Seite 1 sondern die andere durchläuft.

                        dedlfix.

                    2. Hallo @Rolf b

                      deine zweite Version funktioniert. Danke dafür. Allerdings verstehe ich nicht wie ich es schaffen kann dass auf der ersten Seite ein anderer Header ist. Der Footer kann von mir aus überall gleich bleiben. Da steht meine E-Mail Adresse und die [[page_cu]]/[[page_nb]]

                      Könntest du mir das vielleicht nochmals mit dem abweichenden Header erklären?

                      Und sorry dass ich gerade vielleicht etwas unfreundlich war. Aber es ist einfach nervend wenn man seit heute Morgen kurz nach 5 Uhr an dieser Seite sitzt man etwas umsetzten möchte und man bekommt immer wieder etwas anderes gesagt. Hauptsache immer schön kompliziert und ja nicht dass was der Ersteller geschrieben hat bzw. vor hat.

                      1. Nein, nicht kompliziert. Strukturiert 😉, ohne Struktur wird es kompliziert.

                        Genervte Tage hatten wir alle schon. Und gerade dann ist es wichtig, keine bösen Postings zu schreiben. Denn wir sehen nicht, dass über Dir bereits die Luft flimmert.

                        Guck mal, was ich oben mit Zeitstempel 17:48 geschrieben habe, das ist parallel zu deinem Beitrag von 17:39 entstanden. Hilft Dir das?

                        Rolf

                        1. Hallo @Rolf b

                          vielen Dank für deine weitere Erklärung. Die Schau ich mir gleich genauer an. Ich habe noch folgendes versucht:

                          <page_footer> 
                          	 <?php 
                              	$seite ="[[page_cu]]";
                              	var_dump($seite);
                              	if ($seite == 1) { ?>
                              		page [[page_cu]]/[[page_nb]]
                              	<?php } ?>	  
                          	</page_footer> 
                          

                          Im IF Bereich sage ich doch, wenn $seite = 1 ist, dann führe diesen Code aus, richtig? Tut sich nichts. in var_dump steht string(11) "1" warum wird also der Code im IF Bereich nicht ausgeführt? Kannst du dir das erklären?

                          Ach so, wenn ich

                          echo $seite;
                          

                          ausführe, steht die jeweils richtige Zahl drin.

                          1. Hallo Sophie,

                            Im IF Bereich sage ich doch, wenn $seite = 1 ist, dann führe diesen Code aus, richtig? Tut sich nichts. in var_dump steht string(11) "1" warum wird also der Code im IF Bereich nicht ausgeführt? Kannst du dir das erklären?

                            1 ist etwas anderes als "1".

                            Bis demnächst
                            Matthias

                            --
                            Rosen sind rot.
                            1. Hallo @Matthias Apsel

                              ich habe beide Versionen ausprobiert. Bei keiner habe ich eine Ausgabe erhalten.

                              1. $seite ="[[page_cu]]"

                                weist die Zeichenkette [[page_cu]] an die Variable $seite zu, nicht den Wert, den page_cu zur Zeit der PDF-Konvertierung hat.

                                Du musst daran denken, dass Du HTML2PDF zweistufig arbeitest. Erst erzeugst Du HTML, dann jagst Du das Tool drüber und bekommst ein PDF. Erst beim Ausführen des Tools wird aus [[page_cu]] die Seitenzahl.

                                Dein var_dump() hat [[page_cu]] ins HTML geschrieben (zähl mal: da steht string(11)). Und dann ist HTML2PDF drübergelaufen und hat deinen mit var_dump geschriebenen String in eine Zahl umgewandelt.

                                Wenn Du etwas bauen willst, dass auf Seite 1 anders aussieht als auf den Folgeseiten, musst Du das anders steuern. Z.B. mit dem $ersteSeite Parameter, oder mit einem eigenen Seitenzähler.

                                Rolf

                                1. Hallo @Rolf b

                                  kann ich innerhalb von

                                  function write_page($zeilennr, $zeilen, $ersteSeite)
                                  

                                  auf keine Variablen zurückgreifen, die außerhalb festgelegt wurden?

                                  Ich erhalte diese Meldung

                                  Notice: Undefined variable: titel in

                                  Nehme ich deine Funktion wieder weg, wird der Titel ausgegeben.

                                  1. Hallo,

                                    ich habe es jetzt so getestet und es funktionier

                                    <?php 
                                    function write_page($zeilennr, $zeilen, $ersteSeite) {
                                    
                                    	global $id, $titel;
                                    ?>
                                    

                                    ABER das ist für mich ein enormer Mehraufwand, denn ich muss ALLE Variablen unten in die Funktion nochmals schreiben? Das sind derzeit um die 50 Stück :/

                                    1. Hello,

                                      ABER das ist für mich ein enormer Mehraufwand, denn ich muss ALLE Variablen unten in die Funktion nochmals schreiben? Das sind derzeit um die 50 Stück :/

                                      Das stimmt leider. Aber dageben gibt es in PHP verschiedene Strategien:

                                      • Arbeiten mit Arrays
                                      • Objektorientiert programmieren

                                      Liebe Grüße
                                      Tom S.

                                      --
                                      Es gibt nichts Gutes, außer man tut es
                                      Andersdenkende waren noch nie beliebt, aber meistens diejenigen, die die Freiheit vorangebracht haben.
                                  2. Hello,

                                    kann ich innerhalb von

                                    function write_page($zeilennr, $zeilen, $ersteSeite)
                                    

                                    auf keine Variablen zurückgreifen, die außerhalb festgelegt wurden?

                                    Ich erhalte diese Meldung

                                    Notice: Undefined variable: titel in

                                    Doch, das tust Du ja auch mit $zeilennr, $zeilen, $ersteSeite. Da übergibst Du der Funktion beim AUFRUF den WERT dieser Variablen, den sie im AUFRUFZEITPUNKT haben. Die Funktion kann die Variablen also nicht verändern, sondern nur die übergebene Kopie lesen.

                                    Für Konstrukte, wie Du sie hier bauen willst, könnte man sehr gut ein Array für die Übergabe der Werte benutzen:

                                    $_page['title'] = 'Der Titel der Seite'; 
                                    $_page['rows'] = $_rows;  ## ein weiteres Array mit den nächsten Zeilen...  
                                    $_page['zeilennr'] = 1;
                                    ... 
                                    
                                    function write_page($_data)
                                    {
                                        if(isset($_data['title'])) { echo '<h1>' . htmlspecialchars('title') . "</h1>\r\n"; 
                                        if(isset($_data['rows']) and is_array($_data['rows']))
                                        {    
                                            echo  ... 
                                            ...
                                            foreach($_data['rows'] as $key => $row)
                                            {
                                                echo '<li>' . htmlspecialchars($row) . "</li>\r\n"; 
                                            }
                                            ...  
                                        }
                                    }
                                    
                                    ### usw.
                                    
                                    WARNHINWEIS: Dies ist nur als weitere Anregung gedacht, nicht als fertige Lösung!  
                                    

                                    Liebe Grüße
                                    Tom S.

                                    --
                                    Es gibt nichts Gutes, außer man tut es
                                    Andersdenkende waren noch nie beliebt, aber meistens diejenigen, die die Freiheit vorangebracht haben.
                                  3. Hallo @Rolf b ,

                                    ich dachte ich könnte die letzte Seite so herausfinden

                                    php
                                    $test_pdf_ausgabe = test_pdf($mysqli);
                                    $zeilen = count($test_pdf_ausgabe);
                                    $i = 0;
                                    $len = 5;
                                    $ersteSeite = true;
                                    $letzteSeite = false;
                                    
                                    while ($i < $zeilen) {
                                      write_page($i+1, array_slice($test_pdf_ausgabe, $i, $len), $ersteSeite, $letzteSeite);
                                      $i += $len;
                                      $len = 15;
                                      $ersteSeite = false;
                                      $letzteSeite = true;
                                    }
                                    
                                    

                                    Klappt aber nicht so wirklich. Ich denke das hat was mit der Schleife zu tun. Wie kann ich herausfinden ob ich wirklich auf der letzten Seite bin? Denn ich möchte ein extra Feld NUR auf der letzten Seite angezeigt haben.

                                    1. Bei $ersteSeite konnte man relativ einfach mit einer booleschen Variable hantieren, die man auf true setzt und nach dem ersten Durchlauf auf false. Mit der letzten Seite ist das nicht ganz so leicht. Was Du gebaut hast, ist eine Art "$folgeSeite" Schalter, der ab der 2. Seite auf true steht.

                                      Du bist auf der letzten Seite, wenn bei der nächsten Schleifen-Runde die while-Bedingung nicht mehr erfüllt sein wird. Du musst also das NÄCHSTE $i mit der Anzahl der Zeilen vergleichen.

                                      Das nächste $i berechnet sich als $i+$len. Eine Variable $letzteSeite brauchst Du nicht, du kannst den Vergleich direkt da durchführen wo du jetzt $letzteSeite übergibst. Die Details auszuknobeln überlasse ich Dir, das schaffst Du.

                                      Dass Du noch jede Menge mehr Variablen hast, die Du ins Template einbauen musst, ok, das ist jetzt eine neue Information. Du kannst das so machen, wie TS angedeutet hat - du kannst Dir aber auch überlegen, ob Du den bisherigen Ansatz und seinen Vorschlag mischst. MEIN Geschmack wäre es, technische und fachliche Parameter zu trennen. D.h. die Parameter für Zeilennummer, Erste und letzte Seite würde ich auf jeden Fall separat halten. Entweder als einzelne Parameter, oder du gruppierst sie zu einem $steuerung Array. Es gibt viele Wege, die Dich zur Druckerei führen. (Siehe bei Tolkien: Die Straße schreitet fort und fort...).

                                      Bei größeren Datenmengen in Arrays musst Du noch im Hinterkopf haben, dass PHP ein Array als Wert übergibt, d.h. eine Kopie macht. Das kostet Zeit und Speicher. Die Kopie sparst Du Dir, wenn Du die Arrays als Referenzparameter definierst. Das macht man, indem man im Funktionskopf ein & vor den Paramter schreibt, z.B. so: function dingsFunc(&$refParm) { ... }.

                                      Vorteil: Du sparst Laufzeit und Speicher Nachteil 1: Wenn Du jetzt etwas an den Inhalten des übergebenen Arrays änderst, sind die Änderungen auch außerhalb der Funktion sichtbar. Das kann in Deinem Sinne sein, oder auch nicht. Du musst es nur wissen und entsprechend programmieren. Nachteil 2: Ein Funktionsergebnis (wie das von array_slice) direkt an einen Referenzparameter zu übergeben funktioniert zwar, aber PHP haut Dir eine Notice um die Ohren, im Sinne von "Lass das besser". Dem stimme ich zu, du solltest bei Einsatz eines $data Arrays auf jeden Fall die auszugebenden Zeilen in einem Array-Eintrag $data['rows'] speichern und nur das $data Array als Referenz übergeben.

                                      Von Objektorientierung will ich jetzt lieber nicht anfangen, auch wenn man damit die Lösung deutlich schicker hinbekäme. Wenn Du Dich mit OOP noch nicht beschäftigt hast, wird das jetzt zu viel.

                                      Rolf

                                      1. Tach!

                                        Bei größeren Datenmengen in Arrays musst Du noch im Hinterkopf haben, dass PHP ein Array als Wert übergibt, d.h. eine Kopie macht. Das kostet Zeit und Speicher.

                                        Rolf, bitte beachte das Copy-on-write-Prinzip von PHP. Siehe References explained (der Link zum PDF dort). Referenzen sollten in PHP nur dann verwendet werden, wenn sie technisch notwendig sind, nicht um Speicher sparen zu wollen, der am Ende gar nicht gespart wird (oder nicht in dem erhofften Maße).

                                        dedlfix.

                                        1. Ooops - vielen Dank. Das sind die Details, wo der fehlende Teil meines PHP-Halbwissens erkennbar wird...

                                          Rolf

                                      2. Danke für deine Antwort. Ich komm überhaupt nicht mehr weiter. Ich lass das wohl von jemanden umsetzten. Ich sitze seit 2 Tagen dran, hab unzählige laufende Varianten zerstört usw...

                            2. Hallo Matthias,

                              1 ist etwas anderes als "1".

                              wenn man in PHP auf nicht exakte Gleichheit vergleicht (== vs. ===), dann schon:

                              var_dump('1'==1);  // bool(true)
                              var_dump('1'===1); // bool(false)
                              

                              Gruß
                              Julius

                              1. Was anderes ist es trotzdem, auch wenn PHPs type juggling dafür sorgt, dass eine Wertgleichheit festgestellt wird.
                                Und im konkreten Fall war's ja auch noch was GANZ anderes. :)

                                Rolf

                                1. Hallo Rolf,

                                  Was anderes ist es trotzdem, auch wenn PHPs type juggling dafür sorgt, dass eine Wertgleichheit festgestellt wird.

                                  dann halt so: "1" und 1 sind nicht identisch, aber je nach dem zum Feststellen der Gleichheit benutzten Operator, ist das entweder relevant (===) oder eben nicht (==). 😉

                                  Und im konkreten Fall war's ja auch noch was GANZ anderes. :)

                                  Davon mal abgesehen 😀

                                  Gruß
                                  Julius

  2. Hallo,

    ich habe auf GitHub ein Beispiel gefunden, was eigentlich recht gut funktioniert: https://github.com/spipu/html2pdf/blob/master/examples/res/exemple07a.php

    Mein Problem ist, ich weiß nicht wie ich dieses auf meinen Anwenden könnte. Ich habe es mir schon herunter geladen und bisschen dran rum gespielt. Egal wie viele Einträge ich mir ausgeben lasse, es wird immer brav umgebrochen. Was mache ich also falsch?

    1. Hast Du das richtige Beispiel verlinkt? Weil - das was ich da als exemple07 finde, produziert immer genau zwei Seiten und gibt auf beiden Seiten jeweils eine vollständige Liste der Produkte aus. Das hat mit dem hier im Thread diskutierten Thema wenig zu tun.

      Rolf