Frage/Funktionsweise zu Template-System mit dynamischer Html-Tabelle, mit Array-Daten

Davicito

Erfahrenes Mitglied
Hallo und ein frohes gesundes Neues, wünsche ich an dieser Stelle!

Ich beschäftige mich zur Zeit mit meinem Template-System und stelle fest, dass ich wenn ich Daten aus einem Array in eine Html-Tabelle bringen möchte, dass die Html-Tabelle dynamisch gestaltet werden muss, um je nachdem wie lang das Array auch sein mag, die HTML-Tabelle auf die Länge des Array angepasst werden muss.

Meine Idee dabei ist, in dem Template die Html-Tags für die Tabelle unterzubringen und die Datenfelder zu definieren.
HTML:
...
Tabellenkopf
<tr>
<th><h4>NR</h4></th>
<th><h4>Anrede</h4></th>				
<th><h4>Vorname</h4></th> 
<th><h4>Nachname</h4></th>
<th><h4>Telefon</h4></th>
<th><h4>Handy</h4></th>
<th><h4>Email  </h4></th>
</tr>

Tabellen-Content
<tr>
<td>[Zeile]</td>
<td>[Anrede]</td>
<td>[Vorname]</td>
<td>[Nachname]</td>
<td>[Telefon]</td>
<td>[Handy]</td>
<td>[Email]</td>
</tr>
...

Nun soll aus einer Klasse, ein Array, durch eine Foreach-Iteration, verarbeitet werden, welche die Array-Informationen an meine View
weiterleitet, die wiederum die Datenfelder Füllt.
PHP:
...
if(is_array($result) && !empty($result)){				
	(int) $i = 0;
	foreach($result as $key => $value){
		PSMView::assign('Zeile', ++$i);
		PSMView::assign('Anrede', $value['Anrede']);
		PSMView::assign('Vorname', $value['Vorname']);
		PSMView::assign('Nachname', $value['Nachname']);
		PSMView::assign('Telefon', $value['Telefon']);
		PSMView::assign('Handy', $value['Handy']);
		PSMView::assign('Email', $value['Email']);					
	}	
	PSMView::render();
}
...

Die Methode "assign()" bereitet die Array-Daten auf.
Und die Methode "render()" läd das Template und bekommt die Array-Daten zum füllen der Datenfelder, im oben gezeigten Template.

es wird auch eine Zeile im Template, in der Tabelle ausgegeben. Und zwar nur die letzte Zeile.

Table.jpg

Nun würde ich gerne alle Zeilen angezeigt bekommen, nur hab ich gerade nicht den blassenden Schimmer wie ich das noch machen könnte.

Habt ihr so etwas schon gemacht und könntet mir etwas auf die Sprünge helfen? Ich wäre wie immer über Eure Hilfe sehr dankbar!

LG, Davicito.
 
Zuletzt bearbeitet:
Hallo liebes Community,

ich bin nach langen Recherchen, gestern Abend noch zu einer Lösung gekommen. Wem es interessieren könnte, der schaue doch mal auf diese Seite hier!

http://www.inside-php.de/tutorial/PHP-Fortgeschrittene-11/eigenes-Template-System.html

Es stimmt wirklich, das PHP ja schon ein Template an sich darstellt, was einiges leichter macht, bei verschiedenen Aufgabe, die man an ein Template stellen möchte.

Zu meinem Problemchen, von Gestern, habe ich auch mit einem include_once, mein Template in der Controllerklasse geladen und dort die Ausgabe, aus einem Datenbank-Array, mit einer Iteration, im Template, integriert.

Template
HTML:
...
<div>
	<table>
		<tr>
			<th><h4>NR</h4></th>
			<th><h4>Anrede</h4></th>				
			<th><h4>Vorname</h4></th> 
			<th><h4>Nachname</h4></th>			
			<th><h4>Telefon</h4></th>
			<th><h4>Handy</h4></th>
			<th><h4>Email  </h4></th>			
		</tr>
			
		<?php (int) $zeile = 1; 
		foreach($result as $key => $value){?>				
			<tr>
				<td><?php echo $zeile++; ?></td>
				<td><?php echo $value['Anrede']?></td>
				<td><?php echo $value['Vorname']?></td>
				<td><?php echo $value['Nachname']?></td>				
				<td><?php echo $value['Telefon']?></td>
				<td><?php echo $value['Handy']?></td>
				<td><?php echo $value['Email']?></td>						                   
			</tr><br>
		<?php } ?>				
	</table> 
</div>	
...

Controller-Klasse
PHP:
...
$sqlStatement = "SELECT 
					....																					
					FROM 
                             ....
					WHERE									
					....";
						
$result = AuthModel::runQuery($sqlStatement);
						
if(is_array($result) && !empty($result))				
	include_once('Templates\MAOutputTempl.php');
var_dump($result);
...

Problem gelößt! ;-)

LG, Davicito.
 
Zuletzt bearbeitet:
Es stimmt wirklich, das PHP ja schon ein Template an sich darstellt, was einiges leichter macht, bei verschiedenen Aufgabe, die man an ein Template stellen möchte.

Hm. Ja, schon. Aber… na ja, die Leute, die etwa sagen, dass Template Engines nicht glücklich machen (der Klassiker), liegen – sagen wir mal – nicht wirklich richtig.

PHP kann auch Template-Sprache sein, bestimmte Template-Syntax (Twig, Smarty, whatever) hat aber definitiv ihre Daseinsberechtigung. Das Thema wird alle paar Monate mal durch alle Instanzen diskutiert. Etwa:

- http://www.php.de/php-einsteiger/89888-welche-variante-ist-besser-sauberer.html

ich bin nach langen Recherchen, gestern Abend noch zu einer Lösung gekommen.

Ich kann dir noch kurz sagen, wo dein Problem lag. PSMView::render(); hätte mit in der Schleife stehen müssen. Zumindest hast du in der Schleife die zugewiesenen Werte permanent überschrieben, ohne die einzelnen Einträge jeweils zwischendurch zu rendern.

Deine neue Lösung… Joa, kann man sicher so machen.

Du hast da halt keine halbwegs saubere Trennung der Zuständigkeiten mehr. Du pullst den Template-Code einfach in den aktuellen Scope der Controller-Methode und hast damit im Template-Code auf alles Zugriff, was zu dem Zeitpunkt in der einbindenden Methode so an Variablen/Kontext verfügbar ist. Im Umkehrschluss bedeutet das, dass du im Template nicht weißt, welche Variablen du sicher nutzen kannst (stell dir vor, du renderst dasselbe Template in unterschiedlichen Kontexten). Das würde eben ein Assign-Schritt erledigen. (Ach ja, include_once ist auch nicht gut. Nimm include oder require.)

Außerdem hast du auch keine explizite Semantik mehr, dass an der Stelle ein Template gerendert wird. include_once könnte alles sein. Ein Aufruf wie etwa renderTemplate(…) ist da schon offensichtlicher und leichter zu verstehen.



Am Rande:

PHP:
(int) $zeile = 1;

Das (int) bringt nichts, und das schreibt man in PHP auch so nicht. Weglassen.

Schau dir mal das Thema Kontextwechsel an. Speziell XSS. Dir fehlt Escaping (htmlspecialchars).

- http://wiki.selfhtml.org/wiki/Artikel:Kontextwechsel
 
Zuletzt bearbeitet:
Hallo mermshaus,

vielen Dank für Deine Ausführungen. Mit dem Template-Systemen magst Du ja vielliecht Recht haben, das dies heiß diskutiert wird... und ich werd auch nochmal in mich gehen um für mich zu sehen was da am besten ist. ;-)

Ich habe die Methode "renderer()" auch schon in die Schleife gemacht... nur dann habe ich das Problem, das ich meine render-Methode umprogrammieren muss, weil diese - bei jedem Schleifendurchgang, auch immer wieder das Template mit läd und den Tabellenkopf, der HTML-Tabelle, neu aus gibt! Daher fand ich jetzt meine Lösung besser.

Zu dem Carsten von Variablen ist prinzipiell nicht notwendig, ermöglich aber eine gewisse Typ-Sicherheit gegen Manipulationen von Außen! Wenn man von Anfang an, konsequent bleibt, den Variablen einen festen Typ zu zuweisen, kann sich das durch aus bewehren!
Wenn in eine Variable zum Beispiel eine Zuweisung durch eine Benutzereingabe - mittels POST oder GET - realisiert würde, dann könnte ein Srcipt-Attack, durch Böse, durchgeführt werden. Wenn ich eine Maskierung durchführe und am Besten den Typ bestimme, ist es nicht mehr so einfach einen Schadcode einzuschleusen. (s. Buchausgabe: PHP-Sicherheit, von Christopher Kunz & Stefan Esse, Auf den Seiten 67-69).
 
Zuletzt bearbeitet:
Zu dem Carsten von Variablen ist prinzipiell nicht notwendig, ermöglich aber eine gewisse Typ-Sicherheit gegen Manipulationen von Außen! Wenn man von Anfang an, konsequent bleibt, den Variablen einen festen Typ zu zuweisen, kann sich das durch aus bewehren!
Wenn in eine Variable zum Beispiel eine Zuweisung durch eine Benutzereingabe - mittels POST oder GET - realisiert würde, dann könnte ein Srcipt-Attack, durch Böse, durchgeführt werden. Wenn ich eine Maskierung durchführe und am Besten den Typ bestimme, ist es nicht mehr so einfach einen Schadcode einzuschleusen. (s. Buchausgabe: PHP-Sicherheit, von Christopher Kunz & Stefan Esse, Auf den Seiten 67-69).

Hmm, prinzipiell stimme ich zu, casten von Werten auf einen dedizierten Typ bringt etwas mehr Sicherheit, aber nur dann, wenn man es richtig macht. Was du gemacht hast, ist syntaktisch ok aber semantisch unsinnig. Erst mal deine Version:
PHP:
(int) $zeile = 1;

Jetzt meine Version:

PHP:
$zeile = (int)1;

Warum so und nicht anders?

PHP ist left-aligned. Das heißt, es geht von rechts nach links. Das int vor der Variable ist keine Deklaration. Aber es liefert nach Links den Wert von $zeile gecastet auf int ins Nirvana. In Einzelschritte auf gedröselt beduetet die Code-Zeile

0. Erstelle eine Variable dynamischer Größe und Typs in der internen Hash-Table.
1. Weise den konstanten Wert 1 (der an sich ja schon int ist) nach links und caste auf den Typ int.
2. Nehme den Wert von rechts kommend (1) auf und lege ihn am Speicherplatz der Variablen ab.
3. Weise der Wert der Variablen nach links.

Dass das wirklich so ist, kannst du gern testen:

PHP:
if( $var1 = (int) 1) { // Diese Bedingung ist immer wahr*
  echo "\$var1 hat den Wert 1<br/>";
}
else {
  echo "Bedingung 1 nicht erfüllt<br/>";
}

if( $var2 = (int) 0) { // Diese Bedingung ist immer falsch*
  echo "\$var hat den Wert 1<br/>";
}
else {
  echo "Bedingung 2 nicht erfüllt<br/>";
}

* Weil 1 keinen Wert von "false" darstellt. false wäre auch durch
- false
- 0
- null
- ""
erreicht.

Daran sieht man sehr deutlich, dass der Wert von $var1 bzw. $var2 nach links weiter gegeben wird. In der if-Condition wird der Wert ausgewertet, und zwar dadurch, dass versucht wird, ihn in einen boolschen Typen zu casten. Bei allen Werten aus der Liste oben kommt durch das (interne) Casten ein boolscher Wert "false" raus.

Da 1 als konstanter Wert ohnehin schon int ist, macht es keinen Sinn, ihn zu casten. Stände statt der 1 eine Variable, wäre das sinnvoll.


So, genug klug geschissen, aber manchmal muss ein kleiner Exkurs in die PHP-Internals sein.
 
Davicito hat gesagt.:
Zu dem Carsten von Variablen ist prinzipiell nicht notwendig, ermöglich aber eine gewisse Typ-Sicherheit gegen Manipulationen von Außen! Wenn man von Anfang an, konsequent bleibt, den Variablen einen festen Typ zu zuweisen, kann sich das durch aus bewehren!
Wenn in eine Variable zum Beispiel eine Zuweisung durch eine Benutzereingabe - mittels POST oder GET - realisiert würde, dann könnte ein Srcipt-Attack, durch Böse, durchgeführt werden. Wenn ich eine Maskierung durchführe und am Besten den Typ bestimme, ist es nicht mehr so einfach einen Schadcode einzuschleusen. (s. Buchausgabe: PHP-Sicherheit, von Christopher Kunz & Stefan Esse, Auf den Seiten 67-69).

Die Idee ist durchaus nicht verkehrt, sie passt nur nicht auf eine Zeile wie (int) $i = 1;. Warum das (int) am Zeilenbeginn die Variable $i überhaupt nicht manipuliert, hat saftmeister ja bereits erklärt. Aber auch $i = (int) 1; ist nicht „sinnvoller“, denn es führt zu keiner Veränderung.

PHP:
$i = 1;
$j = (int) 1;

var_dump($i, $j); // int(1), int(1)

Beide Variablen sind vom Datentyp Integer. Genauso ist $s in $s = 'Hallo Welt'; vom Datentyp String, auch wenn du kein (string) hinzufügst.

Eine Variable in PHP hat immer einen Datentyp. Der ist aber nie fest. Wenn du $var = 'foo bar'; schreibst, ist $var ab dort vom Datentyp String. Dagegen kannst du nichts machen. PHP funktioniert so.

Bei Zuweisung/Initialisierung wird der Datentyp gewählt, der zum zugewiesenen Wert passt. Das ist bei 1 eben Integer, bei '1' wäre es String und bei 1.0 wäre es Float/Double (ist dasselbe).

Ich glaube, bei Strings wird es ganz offensichtlich, warum $s = (string) 'Hallo Welt'; nicht so sinnvoll ist. Das ist: „Caste einen String zu einem String.“

saftmeister hat gesagt.:
PHP ist left-aligned. Das heißt, es geht von rechts nach links.

Ich kann mir gar nicht so recht erklären, warum (int) $i = 1; überhaupt gültige Syntax ist. Laut Operator-Rangfolge müsste das meiner Interpretation nach eigentlich so ausgeführt werden: ((int) $i) = 1;

(Vielleicht bezieht sich die Rangfolge nur auf Vergleiche mit linksassoziativen Operatoren und rechtsassoziative haben untereinander eigentlich den gleichen Rang.)

Edit: Ah, das hier gilt vermutlich auch für Typecasts:

Although = has a lower precedence than most other operators, PHP will still allow expressions similar to the following: if (!$a = foo()), in which case the return value of foo() is put into $a.

- http://php.net/manual/en/language.operators.precedence.php

So habe ich das noch nie gelesen. :)
 
Zuletzt bearbeitet:

Neue Beiträge

Zurück