Bernd: Daten vor einer foreach ausgeben?

Hallo,

ich habe mal wieder ein massives Problem. Ich habe folgendes Script

$datumStart = "2018-11-01";
$datumEnde  = "2018-11-30";

$userMonat1 = db_userMonat1($mysqli, $object->user_code, $datumStart, $datumEnde);

// Alle Daten gruppieren
$grouped = array_reduce($userMonat1, function($grouped, $entry){
	
	$key = $entry['usz_datum']; // nach Datum gruppieren
	$grouped[$key]['eintraege'][] = $entry;
	return $grouped;
});
	
// Summe pro Gruppe berechnen
$summed = array_map(function($group){

	$hours = array_column($group['eintraege'], 'usz_anzStunden'); // Stunden aus allen Spalten ziehen
	$hours 	= 	str_replace(",", ".", $hours);
	$group['summe'] = array_sum($hours); // Summe bilden
	return $group;

}, $grouped);
	

$stundenGesamt = "";

foreach ($summed as $datetime => $group) {

	$stundenGesamt += $group['summe'];

	  $datetime     = explode("-", $datetime);
    $datetime     = $datetime[2].".".$datetime[1].".";
    
    echo '<div>' . $datetime . '</div>';
    echo '<div> Stunden gesamt: '. $group['summe'] . "</div>";

    foreach ($group['eintraege'] as $grouped =>$eintraege) {


    	if ($eintraege['usz_anzStunden'] != "") {
    		
    		echo $eintraege['usz_anzStunden']. " Std. - " . $eintraege['usz_projektnummer'] . "<br>";
	    	
	    	if ($eintraege['usz_betreff'] != "") {
	    		echo '<div>'.nl2br($eintraege['usz_betreff']). "</div>";
	    	}
    	}
    	echo "<br>\n";
	} 
	echo "<br>";    
} 

echo "Gesamtstunden im " . $monate[$monat] . " :" . str_replace(".", ",", $stundenGesamt); 

Jetzt möchte ich gerne nach

echo '<div> Stunden gesamt: '. $group['summe'] . "</div>";

und vor

foreach ($group['eintraege'] as $grouped =>$eintraege)

noch zwei Einträge anzeigen lassen und zwar

  • usz_start
  • usz_ende

Muss ich dazu eine Datenbankabfrage starten oder kann ich diese in einem machen?

  1. foreach ... {
       echo '<div>'.nl2br($eintraege['usz_betreff']). "</div>";
    }
    

    noch zwei Einträge anzeigen lassen und zwar

    • usz_start
    • usz_ende

    Muss ich dazu eine Datenbankabfrage starten oder kann ich diese in einem machen?

    Voraussetzung:

    Ich vermute mal, dass usz_start und usz_ende innerhalb der foreach-Schleife festgelegt werden.

    Also, wenn Du die einzelnen Items nicht direkt ausgibst sondern mit etwas wie

    $out = '';
    foreach ... {
       $out .= '<div>'.nl2br($eintraege['usz_betreff']). "</div>";
    }
    echo $usz_start . ' | ' . $usz_ende;
    echo $out;
    

    oder etwas wie

    ob_start();
    foreach ... {
       echo '<div>'.nl2br($eintraege['usz_betreff']). "</div>";
    }
    $out = ob_get_clean();
    echo $usz_start . ' | ' . $usz_ende;
    echo $out;
    

    "einsammelst" und dann ausgibst, sollte es in einem Rutsch und ohne zusätzliche Abfrage gehen.

    1. Hallo,

      mein Problem ist, ich benötige die Werte vor der foreach Schleife. In deinem Beispiel habe ich diese nach der foreach Schleife?

      1. mein Problem ist, ich benötige die Werte vor der foreach Schleife.

        Eben hast Du gefragt, wie Du diese vor der foreach-Schleife anzeigen lassen kannst. Das hat, wie mein Code zeigt, mit "benötigen" nichts zu tun. Man muss halt nur die Ausgabe steuern, wozu das Einsammeln in einem String oder mit den Output-Control-Funktionen sehr hilfreich ist.

        <?php
        ob_start();
        echo "Erstens\n";
        $out = ob_get_clean();
        
        echo "Zweitens\n";
        echo $out;
        

        Ergebnis:

        Zweitens
        Erstens
        
        1. Danke für dein Beispiel. Ich mach es über zwei weitere Abfragen.

          1. Ich mach es über zwei weitere Abfragen.

            Naja. Falls sich usz_start und usz_ende nicht in der Schleife oder mit einer Abfage ermitteln lassen sollten (Ich kenne ja weder die konkrete Abfrage noch die dazu gehörenden Tabellen oder die Daten), dann "muss das wohl so".

            Allerdings könnte ich mir denken, dass es etwas wie

            SELECT
                min(`usz_datum`) as `usz_start`,
                max(`usz_datum`) as `usz_ende`,
                `foo`,
                `bar`
            FROM ...
            WHERE ...
            

            geringfügig schneller "tut".

      2. Hallo Bernd,

        ich weiß nicht, warum Du Probleme siehst wo keine sind.

        Die Lösung steht doch schon längst in deinem Code: Mach es vorneweg und speichere es in einem eigenen Eintrag der $group. Du müsstest in deinem array_map Callback für die Summenberechnung nur den array_column/array_sum durch eine ordentliche Schleife über die Einträge ersetzen, dann kannst Du Minima, Maxima und Summen nach Herzenzlist bilden.

        Rolf

        --
        sumpsi - posui - clusi
        1. Die Lösung steht doch schon längst in deinem Code: Mach es vorneweg und speichere es in einem eigenen Eintrag der $group.

          +1

          Du müsstest in deinem array_map Callback für die Summenberechnung nur den array_column/array_sum durch eine ordentliche Schleife über die Einträge ersetzen, dann kannst Du Minima, Maxima und Summen nach Herzenzlist bilden.

          Es muss nicht unbedingt eine Schleife sein. Das wäre der prozedurale Ansatz:

          $minimum = INF;
          $maximum = -INF;
          $sum = 0;
          foreach ($array as $value) {
              $minimum = min($minimum, $value);
              $maximum = max($maximum, $value);
              $sum = $sum + $value;
          }
          

          Das der funktionale:

          list($min, $max, $sum) = array_reduce($array, function ($accumulator, $value) {
              $min = min($accumulator[0], $value);
              $max = max($accumulator[1], $value);
              $sum = $accumulator[2] + $value;
              return [$min, $max, $sum];
          }, [INF, -INF, 0]);
          

          Persönlich finde ich die zweite Lösung schöner, aber das ist Geschmackssache. Falls die Möglichkeit besteht, würde ich aber auch die Berechnungen, wie von ursus vorgeschlagen, in der Datenbank durchführen.

  2. Hallo,

    noch zwei Einträge anzeigen lassen und zwar

    • usz_start
    • usz_ende

    Muss ich dazu eine Datenbankabfrage starten oder kann ich diese in einem machen?

    Klar geht das mit einer Abfrage. Die ein Array liefert mit usz_start im ersten und usz_ende im letzten Arrayelement. So kannst Du das auch vorher ausgeben.

    MfG