der henry: dynamische Webseite mit php

Hallo,

ich möchte mit PHP eine Webseite dynamisch erstellen. Hier ein Teil meines Codes. Mir geht es um die Syntax bzw. die Art wie man dieses Problem lösen kann. Ich kenne "php-Code" in der Webseite, oder php-Variablen, oder eine php-if Anweisung. Jedoch nicht die Kombination 😅

Die Variable $switch wird im php-script gesetzt. Wenn diese true ist, soll der html-Code (table usw.) angezeigt werden und zugleich/im Anhang die for-Schleife aktiviert und die Ausgabe der for-Schleife angezeigt werden. Die erste Zeile (<tr>)ist statisch, alle anderen Zeilen sollen dynamisch angezeigt werden. Aktuell zeigt er mir die for-Schleife (Quellcode) auf der Webseite an

	<?php if ($switch): ?>
				<table cellspacing="2" border="2" cellpadding="3" align="center" frame="box">
				<tr bgcolor=<?= $valuerangeArray[0]->bgcolor ?>>
					<td>
						<INPUT type='radio' id=<?= $valuerangeArray[0]->varname ?> value="0" align="left" checked>
					</td>
					<td class='beschriftung_radio_button' align="left"><?= $valuerangeArray[0]->text ?></td>
				</tr>
				<?php>
						for ($i=1;$i < count($valuerangeArray); $i++)
						{
							echo "<tr bgcolor=\"$valuerangeArray[0]->bgcolor\">";
							echo "<td>";
							echo "<INPUT type=\"radio\" id=\"$valuerangeArray[$i]->varname\" value=\"0\" align=\"left\">";
							echo "</td>";
							echo "<td class=\"beschriftung_radio_button\" align=\"left\">$valuerangeArray[$i]->text</td>";
							echo "</tr>";
						}
				?>       
				echo "</table>";      
			<?php endif; ?>

Wie kann ich dies lösen?

  1. Hi,

      		<?php>
    

    da ist ein > zu viel.

    cu,
    Andreas a/k/a MudGuard

    1. Hallo MudGuard,

      da ist noch mehr zu viel. Dafür fehlt anderes.

      • den input-Elementen fehlt das zwingend erforderliche Label. Es ist zwar theoretisch da, aber nicht zugänglich.

      • align für input - gab es das überhaupt einmal? Aber auch auf dem td wäre es missbilligt und sollte per CSS (text-align) festgelegt werden.

      • bgcolor für tr – diese Eigenschaft ist missbilligt. Statt dessen soll man
        style="background-color: <?= $valuerangeArray[0]->bgcolor ?>"
        schreiben. Sofern es denn sinnvoll ist, die Farben individuell pro Row oder Zelle zu vergeben. Aber das kann man aus dem gezeigten Code schlecht beurteilen und es hängt von der Variabilität der Farben ab, ob man es mit Klassen versuchen sollte.

      • cellspacing="2" border="2" cellpadding="3" align="center" frame="box" für das table-Element: Muss alles weg, ist alles HTML 3 Relikt oder so, das gehört ins CSS. Man gebe der Table eine Klasse und ordne dann im CSS für Tables mit dieser Klasse zu:

        • align="center" zentriert die ganze Tabelle, das sollte sich als margin-inline:auto für das table-Element abbilden lassen
        • cellspacing="2" ist border-spacing: 2px auf dem table-Element
        • cellpadding="3" möchte padding: 3px auf den th/td Elementen sein
        • frame="box" und border="2" wird als "border: 2px solid gray" auf dem table-Element und als "border: 1px solid black" auf de td Elementen festgelegt (Farbe nach Belieben - bei Chrome ist die border-color für Tables per Default gray)
      • Das Innere der For-Schleife sollte besser wieder HTML-Template sein. So wie auch für das table Element. Dito für </table>.

      • Mich deucht, das tr vor der Schleife und die tr in der Schleife unterscheiden sich lediglich im checked Attribut. Um Redundanz zu vermeiden, würde ich dieses tr in die Schleife ziehen und auf $i==0 testen. Hier bietet sich der Auswahloperator ?: an (auch ternärer Operator genannt).

      • Ich würde der Übersichtlichkeit wegen auch versuchen, das Innere des if ($switch) Blocks in eine Funktion auszulagern.

      if ($switch) {
         renderValueRanges($valuerangeArray);
      }
      
      ...
      
      function renderValueRanges($valueRangeArray) {
      ?>
        <table class="value_ranges">
      <?php
        for ($i=0; $i < count($valuerangeArray); $i++):
          $id = $valuerangeArray[0]->varname;
          $text = $valuerangeArray[0]->text;
      ?>
          <tr style="background-color:<?= $valuerangeArray[0]->bgcolor ?>">
            <td>
              <input type='radio' id="<?= $id ?>" value="0" <?= $i==0 ? "checked" : "" ?>>
            </td>
            <td>
              <label for="<?= $id ?>"><?= $text ?></label>
            </td>
      		</tr>
      <?php
         endfor;
      ?>
        </table>
      <?php
      }
      

      Die Variablen $id und $text sind nicht unbedingt nötig und Puristen würden sagen, die braucht man nicht. Ich finde, sie verbessern die Lesbarkeit und verhindern kilometerlange Codezeilen.

      Die Klasse beschriftung_radio_button, die ja ohnehin schon "LABEL" geschrieen hat, sollte im CSS mit einem geeigneten Selektor ersetzt werden. Möglichkeiten wären:

      • .value_ranges td:nth-of-type(2)
      • .value_ranges td:has(label)
      • oder direkt das label formatieren: .value_ranges label

      Je nach Bedarf und Belieben.

      Zu prüfen wäre auch noch, ob die Radiobuttons außer der ID auch noch ein name-Attribut brauchen. Nur mit id werden sie in einem Form nicht gepostet, wenn mich die Erinnerung nicht trügt.

      Rolf

      --
      sumpsi - posui - obstruxi
      1. Hallo Leute,

        vielen, vielen Dank. Ja ... der Fehler war banal, ein ">" zu viel.

        Die Verbesserungen/Optimierungen von Rolf habe eingefügt, nochmals Danke.

        Die Klasse beschriftung_radio_button, die ja ohnehin schon "LABEL" geschrieben hat, sollte im CSS mit einem geeigneten Selektor ersetzt werden. Möglichkeiten wären:

        .value_ranges td:nth-of-type(2)
        .value_ranges td:has(label)
        oder direkt das label formatieren: .value_ranges label
        

        Das verstehe ich aber nicht ....

        Anbei das aktuelle Teilscript.

        Hierzu hätte ich noch Fragen. Wie zu erkennen möchte ich einen Eingabedialog programmieren, der entweder ein Eingabefeld für Zahlen, oder ein "Auswahlfeld" (... mehrere Radiobutton) vorwählt. Die Informationen was wie angezeigt wird, erhalte ich aus einer Datenbank.

        Beim "Senden" (bestätigen der Eingabe) muss ich unterscheiden, welcher Radiobutton ausgewählt wurde. Dazu habe ich jedem Radiobutton eine eindeutige ID und NAME gegeben.

        Aktuelle bekomme ich aber nur den Wert (value) des ausgewählten Radiobuttons, was mache ich hier falsch?

        <!DOCTYPE html>
        <html lang="de">
        <head>
            <meta charset="UTF-8">
            <title>Eingabefeld</title>
            <style>
                #overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.8); display: flex; justify-content: center; align-items: center; color: white; }
                .modal { background: #333; padding: 20px; border-radius: 8px; text-align: center; }
                .hidden { display: none !important; }
        		.value_ranges { margin-inline:auto; border-spacing: 2px; border: 2px solid gray;
        						td { padding: 3px; border: 1px solid black"; }
        					  }
            </style>
        </head>
        
        <body>
        
        <?php if ($message === "SUCCESS"): ?>
            <div id="overlay">
                <div class="modal">
                    <h2>Daten erfolgreich gespeichert!</h2>
                    
                    <h1><?= $datatosave ?></h1>
                    
        <!--			<script>setTimeout(function(){ window.close(); }, 2000);</script>	-->
                    <button onclick="window.close();">Beenden</button>
                </div>
            </div>
        <?php endif; ?>
        
        <div id="overlay" class="<?= $show_form ? '' : 'hidden' ?>">    
            <div class="modal" id="form-container">
                <h2><?= $headline ?></h2>
        		<form method="POST" id="secure-form">
                    <input type="hidden" name="action" value="submit">
                    <label for="password">Passwort: </label><input type="password" id="password" name="password" minlength="4" maxlength="10" required><br><br>
        			<br><br>
        			
        			<!-- wenn value ausgewählt wurde muss ein Eingabefeld für Zahlen eingeblendet werden -->
        			<?php if ($value): ?>
        				<p>min. <?php $valueRangeArray[0]->min ?></p>
        				<p>max. <?php $valueRangeArrayangeArray[0]->max ?></p>
        
        				<input type="text" name="data" placeholder="Deine Daten" required>
        				<label for="data"><?= $valueRangeArray[0]->unit ?></label>
        				<br><br>
        			<?php endif; ?>
                       
                    <!-- wenn switch ausgewählt wurde muessen select Felder her -->
        			<?php 
        				if ($switch) { renderSwitchRange($valueRangeArray); }
        			?>
        			              
                    <br><br>
                    <button type="submit">Senden</button>
                    <button type="button" onclick="cancelAction()">Abbrechen</button>
                </form>
                <hr style="width: 50%;">
                <p id="timer-text">Timout: <span id="seconds">30</span>s</p>
                <?php if ($message === "WRONG_PASSWORD"): ?>
                    <p style="color: red;">falsches Passwort!</p>
                <?php endif; ?>
            </div>
        </div>
        
        <script>
        	
        	window.onload = function() {
        		// Ermittelt die benötigte Breite und Höhe des Inhalts
        		// scrollWidth/Height erfassen den gesamten Inhalt, auch wenn er versteckt ist
        		let contentWidth = document.documentElement.scrollWidth;
        		let contentHeight = document.documentElement.scrollHeight;
        
        		// Optional: Puffer für Browser-Rahmen/Scrollbars hinzufügen
        		window.resizeTo(contentWidth + 50, contentHeight + 200);
        };
        
            let timeLeft = 30;
            const timerSpan = document.getElementById('seconds');
            const overlay = document.getElementById('overlay');
        
            const countdown = setInterval(() => {
                timeLeft--;
                timerSpan.innerText = timeLeft;
                if (timeLeft <= 0) {
                    clearInterval(countdown);
                    cancelAction();
                }
            }, 1000);
        
        //########################################################################################################
        
        function cancelAction()
        {
        	overlay.classList.add('hidden');
        	window.close();
        }
        
            // Timer bei Mausbewegung zurücksetzen (optional)
            window.onmousemove = () => timeLeft = 30;
        
        //########################################################################################################
        
        </script>
        </body>
        </html>
        
        <?php
        function renderSwitchRange($valuerangearray) 
        {
        ?>
        <table class="value_ranges">
        <?php
          for ($i=0; $i < count($valuerangearray); $i++):
            $id = $valuerangearray[$i]->varname;
            $text = $valuerangearray[$i]->text;
            $set = $valuerangearray[$i]->set;
        ?>
            <tr style="background-color:<?= $valuerangearray[$i]->bgcolor ?>">
              <td>
                <input type='radio' id="<?= $id ?>" name="<?= $id ?>" value="<?= $set ?>" <?= $i==0 ? "checked" : "" ?>>
              </td>
              <td>
                <label for="<?= $id ?>"><?= $text ?></label>
              </td>
        		</tr>
        <?php
           endfor;
        ?>
          </table>
        <?php
        }
        
        
        1. Hallo Henry,

          ...beschriftung_radio_button ... geeigneter Selektor

          Das verstehe ich nicht

          Aus dem, was zu zeigst, sieht es so aus als würdest Du das Label gar nicht per CSS ansprechen. Dann wäre eher die Frage, ob Du die Klasse überhaupt brauchst.

          Vieles von dem, was Du zeigst, scheint aus dem Kontext gerissen, als ob Du Teile rausgelöscht hättest. Drum gehe ich lieber nicht sonderlich drauf ein.

          Aber ein paar Sachen hätte ich (die Radiogroup-Sache kommt am Ende).

          Warum setzt Du für das zweite div mit id="overlay" die Klasse hidden, wenn $show_form auf false steht? Warum versteckt zum Client schicken und den Ärger mit einer doppelt vorhandenen ID haben? Warum generierst Du diesen Teil überhaupt, wenn $show_form nicht gesetzt ist? Bei $message==="SUCCESS" machst Du es anders, dieser Teil wird übersprungen, wenn $message nicht "SUCCESS" enthält. Gibt es Gründe, dass Du den form-Teil immer generierst?

          Und warum das Gefummel mit einem fixed-Container? Du setzt die Fenstergröße doch eh auf die Inhaltsgröße, damit müsste dieser Container komplett überflüssig sein. Gib die 3 Flexbox-Eigenschaften einfach dem Body-Element, und setze am Body noch margin:0; width: 100vw; height: 100vh; - Höhe auf 100% dürfte eher nichts nützen. height:100% setzt die Höhe auf 100% des Elternelements, und um auf Fensterhöhe zu kommen, muss dann auch das Root-Element (html) auf height:100% gesetzt werden. 100vh am Body ist einfacher.

          Das Text-Eingabefeld verwendet ein Label, um die Einheit anzuzeigen? Das ist keine brauchbare Beschriftung. Ein Label muss den Zweck der Eingabe erkennen lassen, und ein Placeholder ist kein Label. Wie man das zugänglich mit der Einheit macht, weiß ich nicht genau. Das Label sollte so aussehen und vor dem input stehen (am besten drüber):

          <label for="data">Deine Daten (min. <?= $valueRangeArray[0]->min ?>, max. <?= ... ?></label>
          <input type="text" id="data" name="data" required min="..." max="...">
          

          Wichtig hier:

          • Einsteuern von Werten mit <?= ?>, nicht mit <?php ?>. Ersteres erzeugt einen echo für den Wert, zweiteres führt einen PHP-Befehl aus.
          • min und max können auch am input eingestellt werden. Wirken aber meines Wissens nur für ein numerisches Input. Wenn Du Zahlen erwartest, wäre input type="numeric" eh besser.
          • das input-Element braucht die id für das Label und name für das Senden zum Server. Es braucht beides!
          • "Deine Daten" mag ausnahmweise eine geeignete Beschriftung sein, im Normalfall würde ich aber annehmen, dass das zu abstrakt ist. Welche Bedeutung hat dieser Wert? Das sollte in der Beschriftung stehen.

          In deiner Timeout-Behandlung bist Du zu kompliziert, glaube ich. Hast Du Gründe für diese Fummelei? Reicht es nicht, bei Ablauf der Zeit einfach window.close() aufzurufen? Löschen des Intervalltimers und verstecken von #overlay sollte sich mit dem Schließen des Fensters erübrigen. Beim Klick auf Abbrechen hast Du das Löschen des Timers eh vergessen 😉

          Bezüglich der Radiogroup: da habe ich gepennt. Radiobuttons bilden nur dann eine Gruppe, wenn alle Radiobuttons den gleichen Namen haben. Zum Beispiel name="auswahl", such dir was fachlich passenden aus. Die ID verwendest Du als ID für den Button, damit das Label funktioniert, und speichere sie auch im value-Attribut. Wobei ich nicht weiß, was es mit $valuerangeArray[$i]->set auf sich hat, das Du im Moment als value verwendest.

          Jedenfalls - bei einer Radiogroup sorgt das Auswählen eines Buttons für das Abwählen der übrigen Buttons, und PHP bekommt beim Submit unter dem gemeinsamen Namen den Value des ausgewählten Buttons geschickt.

          Hoffe, ich konnte weiterhelfen.

          Rolf

          --
          sumpsi - posui - obstruxi
          1. Hallo Rolf,

            vielen Dank für dein feedback.

            Jedenfalls - bei einer Radiogroup sorgt das Auswählen eines Buttons für das Abwählen der übrigen Buttons, und PHP bekommt beim Submit unter dem gemeinsamen Namen den Value des ausgewählten Buttons geschickt.

            Genau das ist mein Problem, das nur der "value" zurückkommt.

            Hintergrund:

            In ein Datenbankfeld soll, je nach Auswahl der "Radiobutton" ein Wert "X" (value) geschrieben werden. Dazu nutze ich den Namen des Datenbankfeldes als "id" und den zu schreibenden Wert, als "value" das ich je "RadioButton" schreibe. z.B.

            <input type='radio' id="<?= $id ?>" name="immergleich" value="<?= $set ?>">

            Wenn ich einen "RadioButton" auswähle, hat dieser die Info, wie oben beschrieben.

            1. id => welches Datenbankfeld beschrieben werden soll
            2. set => welcher Wert in die Datenbank geschrieben werden soll

            Wie könnte ich dies anders lösen, das beim "senden" die "id" und der "value" des ausgewählten "Radiobutton" an das php-script geschickt wird?

            Vielen Dank!!

            1. Hallo der henry,

              Wie könnte ich dies anders lösen, das beim "senden" die "id" und der "value" des ausgewählten "Radiobutton" an das php-script geschickt wird?

              Du bekommst name=value, wenn in einem Form mit der Radiogroup

              <input type="radio" id="foo-1" name="foo" value="dings"><label for="foo-1">Dings</label>
              <input type="radio" id="foo-2" name="foo" value="bums"><label for="foo-2">Bums</label>
              <input type="radio" id="foo-3" name="foo" value="tra"><label for="foo-3">Tra</label>
              <input type="radio" id="foo-4" name="foo" value="lala"><label for="foo-4">Lala</label>
              

              der dritte Radiobutton ausgewählt ist und das Form mit POST gesendet wird, dann findest Du in PHP in $_POST["foo"] den Wert "tra" vor.

              Wenn Du zwei Werte haben willst, kannst Du tricksen und beide Werte in den Value schreiben. Zum Beispiel:

              <input type="radio" id="foo-3" name="foo" value="foo-3;tra"><label for="foo-3">Tra</label>
              

              Dann steht in $_POST["foo"] der Wert "foo-3;tra" und das kannst Du mit explode zerlegen. Aber ist das nötig? Brauchst Du unbedingt zwei Informationen zu einem Radiobutton?

              Rolf

              --
              sumpsi - posui - obstruxi