Smarty: Inhalt einer Variable zur Variable machen?

WulfmanGER

Commander
Registriert
Juli 2005
Beiträge
2.296
Hallo zusammen,

ich kämpfe gerade mit Smarty 4@php8.2. Vielleicht hab ich gerade einen großen Denkfehler, Denkblockade...

Ich habe eine Datenbankabfrage. In der Spalte "EigeneKategorie" gibt es 5 verschiedene Kategorien. Evtl. kommt mal eine sechste dazu oder ich kürze auf 4. Das weiß ich nicht - ich möchte das Script so gestalten das es schlicht egal ist - in der Datenbank stehen plötzlich 6 Kategorien und ohne das ich im Script was ändere, bekomme ich alle 6 ausgewertet. Soviel zu bla ;)

In php erstelle ich die Arrays

Code:
$kategorie_array = array('Doku', 'Film', 'Kurzfilm', 'Show', 'Serie');

foreach ($kategorie_array as $ka)
{
    ${"genre_content_array_".$ka} = array();
}

Dann fülle ich die Arrays entsprechend via einer while-Schleife.

Danach folgt die zuweisung an Smarty:

Code:
$smarty->assign('genreCategory', $kategorie_array);
foreach ($kategorie_array as $kat)
{
    $smarty->assign('genreContent'.$kat, ${"genre_content_array_".$kat});
}


=> soweit klappt alles. Ich kann das jetzt in Smarty wie folgt abrufen:
Code:
        {foreach $genreContentFilm as $rowg}
            {$rowg.title}<br>
        {/foreach}
        {foreach $genreContentSerie as $rowg}
            {$rowg.title}<br>
        {/foreach}
Ich muss den code also für jede Kategorie erstellen. Das klappt auch. Aber wie gesagt: das soll dynamisch sein - theoretisch weiß ich nicht welche Kategorien ich habe.

Also würde ich im prinzip sowas wollen;
Code:
    {foreach $genreCategory as $cat}
        {foreach $genreContent$cat as $rowg}
            {$rowg.title}<br>
        {/foreach}
    {/foreach}
Und damit könnte ich dann alle 4,5,6 Kategorie anzeigen lassen - wenn sich am Ausgabecode was ändert, muss ich das einmal machen.
Natürlich klappt der Code so nicht ;)
In php erstelle ich mit ${"genre_content_array_".$kat} so eine dynamische Variable. Dafür such ich das Pendant in smarty.

GERNE auch eine andere Lösung ;)

Bei der Ausgabe möchte ich am ende das ganze in ein Container packen der 4,5 oder 6 Reiter hat. Auch Dynamisch - passend zum Ergebnis der sql-Abfrage. Das hab ich aber schon gemacht in einem anderen Menu.

Hab schon bissel gegoogled - ohne erfolg. Auch chatgpt hab ich gefragt - da gab es Ideen die alle nicht klappten.

Ideen?

PS: ursprünglich war die Idee eine andere: Ich klicke auf eine Kategorie und bekomme nur diese angezeigt. Das ist auch weiterhin mein Plan B+ - wäre auch mit Pagination bzw. Infinity-Scroll leichter ;). Das Wissen wie ich das gelöst bekomme, würde ich mir aber schon irgendwie aneignen.
 
WulfmanGER schrieb:
In php erstelle ich mit ${"genre_content_array_".$kat} so eine dynamische Variable. Dafür such ich das Pendant in smarty.
Einfach lassen. Variable Variablen sind großer Bullshit, machen den Code schwer lesbar/vorhersehbar und führen letztenendes zu Stabilitäts- und Sicherheitsproblemen.

Benutz einfach ein mehrdimensionales array:
(array() is ein umständlicherer Alias für eckige Klammern)
PHP:
$kategorien = [ 'Doku', 'Film', 'Kurzfilm', 'Show', 'Serie' ];

$genreContent = [];
foreach ($kategorien as $kategorie)
{
    $genreContent[$kategorie] = [];
    // Befüllung von genreContent[$kategorie] ...
}

$smarty->assign('genreContent', $genreContent);

In Smarty sollte dann folgendes gehen:
Code:
    {foreach $genreContent as $catContent}
        {foreach $catContent as $rowg}
            {$rowg.title}<br>
        {/foreach}
    {/foreach}

Bei dem Ansatz frage ich mich aber noch: Warum überhaupt die Kategorien einzeln auslesen nur um in Smarty die Kategorien in einer doppelten for-Schleife wieder in ungruppierte Einträge zu zerlegen? Wenn du eine Datenbank hast (SQL?), hole dir doch gleich alle Einträge auf einmal in ein einfaches array (ggf. mit pagination).
 
Zuletzt bearbeitet:
Marco01_809 schrieb:
Warum überhaupt die Kategorien einzeln auslesen nur um in Smarty die Kategorien in einer doppelten for-Schleife wieder in ungruppierte Einträge zu zerlegen?
Weiß nicht so recht ob die ich die Frage verstehe.

Ich lese natürlich die komplette Tabelle aus.
Ich hab im Prinzip eine Genre-Tabelle: FilmID | GenreID ... über die FilmID hole ich in einer anderen Tabelle die dazugehörige Kategorie. Und über eine weitere das Rating.
Am Ende sieht meine Ausgabe so aus: FilmID | GenreID | Titel | Rating | Kategorie
Diese Ausgabe kommt dann ins Array.

Und hier kämpfe ich mit verschiedenen möglichkeiten der Ausgabe:
1) Ich klicke im Menu auf das Genre und bekomme im DIV alles mit dem Genre angezeigt (alle Kategorien) - dafür lässt sich dann Pagination gut umsetzen
2) .... bekomme im DIV 1-6 Reiter wo ich zwischen Film, Serie, Doku usw. switchen kann. Ähnliches hab ich in einem anderen Bereich im gleichen Projekt schon mal gemacht. NACHTEIL ... Wenn ich auf "Action" klicke sollte ich mit kleiner Schrift und Hochkant-Monitor arbeiten ;). Hier hatte ich an ein Infinty-Scroll je Kategorie nachgedacht (wobei das wohl komplex wird - bei bis zu 6 Reitern)
3) Im Menu links hab ich "Genre (Avg Wertung)" stehen. Rechts davon könnte ich | Filme | Dokus | Serien | ... machen. Das macht das "Menu" breiter - ist aber hier optisch kein Problem (der Rest der Seite lässt das zu ohne das es "komisch" ausschaut). Im Zugehörigen DIV (was am PC rechts, bei Mobile: links ist) zeigt dann nur die Kategorie an - hier kann ich dann Pagination oder InfinityScroll machen (wobei mich Infinity reizt - hab ich noch nie eingesetzt - das ist so mein Lern-Projekt). Nachteil: ich muss groß rumhantieren wenn sich etwas an den Kategorien ändert.

Die Variablen Variablen hätte ich für Variante 2 benötigt.

Mein Problem ist halt bei der Nr 2: woher weiß das Script wo die Kategorie hin soll - Tab 1, 2, 3 oder 4?.

Ok ich packe alles in die $genreContent: FilmID | GenreID | Titel | Rating | Kategorie
Aber bei der Ausgabe möchte ich die Kategorien wieder trennern - ich möchte ja ggf. bei #2 mit 1-2-3-4-5-6 Kategorie-Reitern arbeiten.

Code:
$kategorie_array = array('Doku', 'Film', 'Kurzfilm', 'Show', 'Serie');
Das ist quasi das "Matching"-Array. Ich habe diese Infos bereits in der Datenbank -> Array. Nur zum Trennen dachte ich das ich ein Array erstelle um damit die sachen rauszufiltern/splitten. Am Ende hätte ich über ein DISTINCT in mysql die Kategorien geholt. Immer aktuell. Verstehe daher deinen Code von dir nicht.
 
WulfmanGER schrieb:
Die Variablen Variablen hätte ich für Variante 2 benötigt.

Mein Problem ist halt bei der Nr 2: woher weiß das Script wo die Kategorie hin soll - Tab 1, 2, 3 oder 4?.
Nein, variable Variablen sind immer Unfug. Benutz einfach Arrays. Arrays können auch Strings als Key haben und beliebig tief verschachtelt werden.

WulfmanGER schrieb:
Ok ich packe alles in die $genreContent: FilmID | GenreID | Titel | Rating | Kategorie
Aber bei der Ausgabe möchte ich die Kategorien wieder trennern - ich möchte ja ggf. bei #2 mit 1-2-3-4-5-6 Kategorie-Reitern arbeiten.
In PHP einfach
PHP:
$kategorien = [];

foreach ($dbResult as $row) {
    if (!array_key_exists($row["Kategorie"], $kategorien)) {
        $kategorien[$row["Kategorie"]] = [];
    }
    $kategorien[$row["Kategorie"]][] = $row;
}
Jetzt hast du in $kategorien ein Mapping von der Kategorie auf ein Array mit allen Filmen in dieser Kategorie.

Bei nur 6 Kategorien kannst du auch einfach 6 Abfragen an die Datenbank machen, das ist kein großes Problem, sofern die Datenbank schnell ist bzw. geeignete Indizes hat.

WulfmanGER schrieb:
Code:
$kategorie_array = array('Doku', 'Film', 'Kurzfilm', 'Show', 'Serie');
Das ist quasi das "Matching"-Array. Ich habe diese Infos bereits in der Datenbank -> Array. Nur zum Trennen dachte ich das ich ein Array erstelle um damit die sachen rauszufiltern/splitten. Am Ende hätte ich über ein DISTINCT in mysql die Kategorien geholt. Immer aktuell. Verstehe daher deinen Code von dir nicht.
Das ist genau dein Code den du im OP so skizziert hast (wenn die variablen Variablen in Smarty gehen würden); es gibt jeden Titel aus jeder Kategorie zusammen mit einem <br> aus.

WulfmanGER schrieb:
Ich hab im Prinzip eine Genre-Tabelle: FilmID | GenreID ... über die FilmID hole ich in einer anderen Tabelle die dazugehörige Kategorie. Und über eine weitere das Rating.
Am Ende sieht meine Ausgabe so aus: FilmID | GenreID | Titel | Rating | Kategorie
Okay, dachte zuerst du hast vielleicht eine Tabelle je Kategorie. Kann ein Film denn in mehreren Kategorien und/oder Genres sein, oder warum die Kategorie per FilmID holen? Bzw. warum nicht eine Film-Tabelle mit KategorieID und GenreID Spalten?

WulfmanGER schrieb:
1) Ich klicke im Menu auf das Genre und bekomme im DIV alles mit dem Genre angezeigt (alle Kategorien) - dafür lässt sich dann Pagination gut umsetzen
Das ist ja kein Problem und sollte schon gehen oder nicht? Einfach alle Einträge holen mit einer bestimmten GenreID.

WulfmanGER schrieb:
2) .... bekomme im DIV 1-6 Reiter wo ich zwischen Film, Serie, Doku usw. switchen kann. Ähnliches hab ich in einem anderen Bereich im gleichen Projekt schon mal gemacht. NACHTEIL ... Wenn ich auf "Action" klicke sollte ich mit kleiner Schrift und Hochkant-Monitor arbeiten ;). Hier hatte ich an ein Infinty-Scroll je Kategorie nachgedacht (wobei das wohl komplex wird - bei bis zu 6 Reitern)
Das ist dann ein Untermenü zu dem Genre-Menü? Wenn du immer nur eine Kategorie sehen kannst zwischen denen man mit Tabs wechseln kann, dann ist Infinity-Scroll ja nichts anderes als Pagination.

WulfmanGER schrieb:
3) Im Menu links hab ich "Genre (Avg Wertung)" stehen. Rechts davon könnte ich | Filme | Dokus | Serien | ... machen. Das macht das "Menu" breiter - ist aber hier optisch kein Problem (der Rest der Seite lässt das zu ohne das es "komisch" ausschaut). Im Zugehörigen DIV (was am PC rechts, bei Mobile: links ist) zeigt dann nur die Kategorie an - hier kann ich dann Pagination oder InfinityScroll machen (wobei mich Infinity reizt - hab ich noch nie eingesetzt - das ist so mein Lern-Projekt). Nachteil: ich muss groß rumhantieren wenn sich etwas an den Kategorien ändert.
Verstehe nicht wieso es einen Unterschied macht wie/wo du die Kategorie-Auswahl machst. Du wählst ein Genre aus. Jetzt hast du einen Reiter wo du noch die Kategorie wählen kannst und die Liste der entsprechenden Filme darunter. In jedem Fall weißt du doch beim Abrufen der Liste das Genre und die Kategorie. Du kannst auch noch einen zusätzlichen Reiter einfügen ala (alle), wo dann nicht nach Kategorie gefiltert wird.

In SQL hätte ich es folgendermaßen gemacht:
kategorie: id | name
genre: id | name
film: id | genreID | kategorieID | titel | rating (+ jeweils ein Index für (genreID) und (genreID, kategorieID))

Falls die DB für mehrere Nutzer ist statt der Rating-Spalte eine extra Tabelle:
rating: id | userID | filmID | rating (oder id weglassen und ein composite primary key aus (userID, filmID))

Alle Filme eines Genres inkl. Name der Kategorie:
SQL:
SELECT id, kategorie.name, titel, rating.rating
JOIN kategorie ON film.kategorieID = kategorie.id
JOIN rating ON film.id = rating.filmID AND rating.userID = :userid
WHERE genreID = :genre
Alle Filme eines Genres und Kategorie:
SQL:
SELECT id, titel, rating.rating
JOIN rating ON film.id = rating.filmID AND userID = :userid
WHERE genreID = :genre
AND kategorieID = :kategorie
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: Oelepoeto
kategorie: id | name
genre: id | name
film: id | genreID | kategorieID | titel | rating

Das funktioniert so nicht. Filme können 2+ Genres haben (Action, Komödie, Drama = 1 Film) daher
genre: filmid, genreid (den Namen für die GenreID bekomme ich wo anders her)
FilmTech: filmid, kategorieNAME, Techgedöns ... <- die einzige Tabelle die quasi in Handarbeit entsteht: Excel->CSV
FilmDetails: filmid, tmdb_titel usw. <- wird per TMDB-API geholt - Anhand der FilmTech-Tabelle
rating: filmid, imdb, ofdb, tmdb, rotten, fsk, usw. usf. (relativ "breit"; 15 verschiedene Ratings)
Über die FilmID komme ich dann an weitere Daten ran - wie eben Genre, Produktionsländer, Networks usw.

Kategorie gibt es nur einmal je Eintrag. Ein Eintrag ist entweder ein FILM oder eine SERIE(nepisode) oder eine DOKU usw. Die Kategorie ist von mir. Das Genre ist ein TMDB-Import. Es gibt aber leider in der TMDB nur zwei Kategorie: Film und Serie (oder movie und tv) - das reicht mir aber leider so nicht und ignoriere die (im output; sind auch oft nicht richtig und ungünstig gewählt) und das reicht mir nicht. TMDB kennt auch keine Dokus (doch ... ein paar - die dann entweder als Film oder Serie laufen....) => Daher brauch ich eine eigene Kategorisierung

Ich versuch das mal zu visualisieren was ich vorhabe:
Variante 1 "Holzhammer" - alles in einer Liste - darüber brauchen wir nicht sprechen ;). Das hab ich in den Vorgängersystemen schon gemacht - will ich weg von ;)
Variante 2:
1711466151706.png

Ich klicke aus auf das Genre Action - im Genre Action enthalten sind insgesamt 1000 Einträge. Die Einträge gehören in die Kategorie Film, Serie, Doku. Default wird z.b. Filme als erstes angezeigt. Jetzt klicke auf auf Serie und bekomme die Serien angezeigt oder auf Doku für die Dokus. Das ganze Mengenmässig unter Kontrolle zu bringen ist die nächste Baustelle - ich denke hier an InfinityScroll

Variante 3: "Optischer Holzhammer"
1711466686727.png

Ein breites "Genre + Kategorie-Menu: Genre ist nicht explizit verlinkt - aber die ganzen zahlen unter den 6 Kategorien. Klick ich drauf, öffnet sich rechts ein Fenster (DIV) wo ich hier im Beispiel alle Serien aus dem Genre Action angezeigt bekomme.

Variante 2 fände ich am elegantesten - vorallem wenn Infinity noch klappen würde.


Du hast vorschlagen das ich ja im "gesamt"-Smarty-Array die Kategorie stehen habe. Das würde ich am besten sortieren nach Kategorie, Rating.

Bei der Ausgabe hab ich eine "Content"-Div
Beim ersten Datensatz erstelle ich den Reiter + DIV für die erste Kategorie
Wenn dann z.b. 129 Datensätze durch sind und die Kategorie wechselt - nächster Reiter + DIV

So grob ...
 
Zuletzt bearbeitet:
Ich hab das jetzt gelöst. Variante 2. Ich sortiere die Daten nach Kategorie, Rating. Danach lese als in Smarty die Kategorien (unique) aus und erstelle für jede einen DIV-Tab. Danach fülle ich die Tabs. Klappt recht gut. Bzw. Pagination/Infinty hab ich mich für Quick&Dirty entschieden (das Thema behalte ich für das nächste Upgrad ein 3-4 Jahren im Hinterkopf): Gibt es nicht. Ich mache ein Infity-Fake-Scroll via Tabelle und festgesetzter DIV-Höhe. Das ganze hat natürlich den Nachteil das ich den kompletten Inhalt im Quelltext liegen habe. Das Clientseitige Laden von 1000+ Datensätzen geht aber recht zügig. Passt für mich (ich bin der einzige Nutzer dieser Seite)
 
Zurück
Oben