verschachtelte foreach / if Anweisungen

kazuhisa

Grünschnabel
Hi zusammen,

ich habe ein Problem mit folgender Situation: Ich möchte in einem dreispaltigen Grid Artikel aufbauen. Bei manchen Artikeln brauche ich eine Überschrift, die dann natürlich oberhalb des wrappers stehen muss, damit die volle Breite und der Fluss korrekt ist.

Da die items in einem CMS hinzugefügt werden, wird manchen eine passende Überschrift, wie eine Kategorie, über ein select Feld hinzugefügt ($item->header). Problem hierbei ist, dass das foreach um den gesamten Komplex liegen sollte, damit die gefunden Artikel unter $item zu finden sind.

Ich habe den code stark gestutzt, damit das ganze übersichtlich bleibt. Ist es technisch möglich, ein verschachteltes foreach zu haben, und gleichzeitig eine Ausgabe des ersten foreach nicht allen anderen items anzuhängen.

Hier mein code, der ohne, aber mit header nicht korrekt funktioniert. Ich denke meine if- und foreach sind völliger Humbug?

<?php foreach($pages->find('template=article') as $header): ?>
<?php if ($header->headline): ?>
<div class='header' >
<h3><?=$item->header?></h3>
</div>
<?php endif; ?>
<div uk-grid>
<!-- wenn es keinen 'header' für ein item gibt, wird foreach im wrapper mit items bzw. einzelnen Spalten (uk-width-1-3) gefüllt -->
<div class="wrapper" uk-grid>
<?php foreach($pages->find('template=article') as $item): ?>
<div class="uk-width-1-3@m">
1/3 columns
</div>
<?php endforeach; ?>
</div>
</div>
<?php endforeach; ?>
 
Ohne das getestet zu haben besteht das Problem darin, dass Du, wenn Du erst die innere Schleife begonnen hast, nicht mehr in den oberen Zweig für den Header hinein kommst.
Ich würde das mit nur einer Schleife erledigen:
<?php
// Merker, der angibt, dass wir am Start der Ausgabe sind:
$start = true;
foreach ($pages->find('template=article') as $item):
// Hat das aktuelle Element eine Headline?
if ($item->headline):
if (!$start):
// Wenn wir nicht am Start der Ausgabe sind
// müssen wir den letzten Wrapper abschließen:
echo '</div>';
endif;
// Jetzt geben wir die Überschrift aus:
echo '<div class="header">';
echo '<h3>' . $item->header . '</h3>';
echo '</div>';
// Und öffnen den Wrapper für die übrigen Elemente:
echo '<div class="wrapper" uk-grid>';
endif;
// Hier geben wir die 3 Spalten aus:
echo '<div class="uk-width-1-3@m">';
echo '</div>';
endforeach;
// Jetzt müssen wir noch den letzten Wrapper abschließen:
echo '</div>';
Um einen besseren Überblick über die Struktur des PHP zu haben, war ich so frei, das Geflecht mit den öffnenden und schließenden PHP-Klammern weg zu lassen.

brauche ich eine Überschrift, die dann natürlich oberhalb des wrappers stehen muss, damit die volle Breite und der Fluss korrekt ist.
Nicht unbedingt, Du kannst in deinem Grid die drei Spalten verbinden und dort die Überschrift hinein schreiben. Dann wird das PHP ein ganzes Stück einfacher und übersichtlicher:
Code:
<div class="wrapper" uk-grid>';
    <?php
        foreach ($pages->find('template=article') as $header):
            // Hat das aktuelle Element eine Headline
            // geben wir diese aus:
            if ($header->headline):
                echo '<h3>' . $item->header . '</h3>';
            endif;
            // Hier geben wir das aktuelle Item aus
            // Ein Wrapper ist nicht erforderlich:
            echo '<div class="uk-width-1-3@m">';
            echo '</div>
        endforeach;
    ?>
</div>
CSS:
.wrapper {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}

.wrapper h3 {
grid-column: 1/4;
}
 
Zuletzt bearbeitet:
@Sempervivum wow, Danke! für die umfassende Darstellung der Möglichkeiten. Ich habe die Schleifen des ersten code-Blocks in mein Template übertragen. Das öffnen bzw. schließen der tags scheint nicht ganz korrekt, hier der Quelltext zweier Ausgabe/n:

1. Der zweite Eintrag mit Headline

Code:
<div class='uk-width-1-3@m' role='img'>
    <img src='' />
    <div class='team-text'>
        <h6 class='uk-margin-remove'>Item 1</h6>
        <div class='position'>
            <p>Position</p>
        </div>
        <address class='team-contact'>Daten</address>
    </div>
</div>
</div>
<div class='uk-width-1-1 uk-margin-remove-bottom'>
    <h3>Kapitel Überschrift</h3>
</div>
<div class='uk-grid-medium uk-margin-medium-top' uk-grid>
    <div class='uk-width-1-3@m' role='img'>
        <img src='' />
        <div class='team-text'>
            <h6 class='uk-margin-remove'>Item 2</h6>
            <div class='position'>
                <p>Position</p>
            </div>
            <address class='team-contact'>Daten</address>
        </div>
    </div>
</div>
<div class='uk-width-1-3@m' role='img'>
    <img src='' />
    <div class='team-text'>
        <h6 class='uk-margin-remove'>Item 3</h6>
        <div class='position'>
            <p>Position</p>
        </div>
        <address class='team-contact'>Daten</address>
    </div>
</div>
</div>
</div>

2. Der erste Eintrag mit Headline

Code:
<div class='uk-width-1-1 uk-margin-remove-bottom'>
    <h3>Kapitel Überschrift</h3>
</div>
<div class='uk-grid-medium uk-margin-medium-top' uk-grid>
    <div class='uk-width-1-3@m' role='img'>
        <img src='' />
        <div class='team-text'>
            <h6 class='uk-margin-remove'>Item 1</h6>
            <div class='position'>
                <p>Position</p>
            </div>
            <address class='team-contact'>Daten</address>
        </div>
    </div>
</div>
<div class='uk-width-1-3@m' role='img'>
    <img src='' />
    <div class='team-text'>
        <h6 class='uk-margin-remove'>Item 2</h6>
        <div class='position'>
            <p>Position</p>
        </div>
        <address class='team-contact'>Daten</address>
    </div>
</div>
</div>
<div class='uk-width-1-3@m' role='img'>
    <img src='' />
    <div class='team-text'>
        <h6 class='uk-margin-remove'>Item 3</h6>
        <div class='position'>
            <p>Position</p>
        </div>
        <address class='team-contact'>Daten</address>
    </div>
</div>
</div>
</div>

Nicht schlau werde ich aus
Code:
// müssen wir den letzten Wrapper abschließen:
echo '</div>';

da diesem, soweit ich sehe, kein öffnendes div vorausgeht? Ein schließendes /div ist im Quelltext zu viel, im code fett markiert.

Im Quelltext der ersten Version fehlt der wrapper, der eigentlich nicht an die Headline gebunden ist?
Code:
<div class='uk-grid-medium uk-margin-medium-top' uk-grid>
Ich habe die Headline daher dem ersten Eintrag hinzugefügt, vom zweiten entfernt.
 
Ich habe die Headline daher dem ersten Eintrag hinzugefügt, vom zweiten entfernt.
Und was ist das Ergebnis? Funktioniert immer noch nicht richtig?

Habe ich dies überhaupt richtig verstanden:
Nicht unbedingt, Du kannst in deinem Grid die drei Spalten verbinden und dort die Überschrift hinein schreiben. Dann wird das PHP ein ganzes Stück einfacher und übersichtlicher:
Dabei bin ich davon aus gegangen, dass Du ein Layout mit fest 3 Spalten hast aber das scheint nicht zuzutreffen denn ich sehe vor dem div.team-text mit 3 Elementen noch ein img-Tag? Das wären dann 4 Spalten.

Mir ist nicht ganz klar, wie das HTML aussehen soll.
 
PHP und Daten werden korrekt gelesen, die Ausgabe ist ebenfalls vollständig. Die items liegen nicht neben-, sie liegen untereinander. Mein Fehler, ich habe es nicht ausreichend erklärt.

Eine Grafik:

item-column.png

Die Anzahl der items ist unbekannt, ebenso die Anzahl der Headlines. Ich habe es mir wahrscheinlich zu einfach vorgestellt? Die Idee ist:
Wird ein Artikel, ein item, hinzugefügt, öffnet sich ein wrapper und schließt den oder die Artikel ein. Wird einem Artikel eine Headline hinzugefügt, wird oberhalb des Artikels die Headline angezeigt. Der oder die Artikel selbst, befinden sich im darunter liegenden wrapper… bis zur nächsten item-headline.
 
Danke, dadurch wird das Ganze jetzt klar.
In diesem Fall ist ein Gridlayout das Mittel der Wahl, die 2. Lösung in meinem Posting #2. Das PHP wird unschlagbar einfach und Du brauchst keinen Wrapper für die Zeilen.
Ich weiß nicht was für CSS an diesem div.uk-width-1-3@m hängt, möglicher Weise eine Definition der Breite. Die braucht es dann nicht mehr.
 
Okay, danke! Werde morgen früh das Template mit der Version aufbauen und entspr. Feedback geben.
Das verwendete Framework ist UIkit, weil dieses im verwendeten CMF Processwire fürs Backend bereits enthalten ist.
Würde die Version #1, die ich jetzt aufgebaut habe, mit dem nun bekannten Aufbau aus techn. Gründen gar nicht funktionieren? Ich sehe, dass es recht viele wenn / aber gibt, daher verstehe ich, dass es nicht geht. Ich frage nur aus Interesse.
 
Geht nicht gibt's nicht, das würde ganz sicher funktionieren wenn man es richtig aufbaut. Aber unnötig kompliziert, das PHP der Grid-Version spricht für sich.
 

Neue Beiträge

Zurück