Barksalot: KW als Spalte einfügen

0117

KW als Spalte einfügen

  1. 1
    1. 0
      1. 0
        1. 0
          1. 1
            1. 0
              1. 1
                1. 0
              2. 0
                1. 0
                  1. 0
                    1. 0
                2. 0
                  1. 0
                    1. 0
                      1. 0
                      2. 1
                        1. 0
                      3. 0

                        Hier mal meine Vorgehensweise

                        1. 0

                          (Fortsetzung)

                        2. 0

                          2. Fortsetzung: Termine

                          1. 0
                            1. 0
                              1. 0
                                1. 0
                                  1. 0
                                    1. 0
                                      1. 0
                                        1. 0
                                    2. 0
                              2. 0
                                1. 0
                                  1. 0
                              3. 0
                              4. 0
                  2. 2
                  3. 2
                    1. 0
                      1. 0
                        1. 0
                      2. 0
                    2. 0
                      1. 0
                        1. 0
                          1. 0
                            1. 0
                      2. 0
                        1. 0
                          1. 0
                            1. 0
                              1. 0
                                1. 0
                                  1. 0
                                    1. 0
                                      1. 0
                                        1. 0
                                          1. 0
                                            1. 0
                                              1. 0
                                                1. 0
                                                  1. 0
                                                    1. 0
                                                      1. 0
                                                        1. 0
                                                          1. 0
                                                            1. 0
                                                              1. 0

                                                                Anmerkung zu $mysqli: KW als Spalte einfügen

                                                                1. 0
                                                                  1. 0
                                                                    1. 0
                                                                      1. 0
                                                                        1. 0
                                                                        2. 0
                                                                          1. 0
                                                                            1. 0
                                                                              1. 0
                                                                                1. 0
                                                                                  1. 0
                                                                                2. 0
                                                                                  1. 0
                                                                                    1. 0
                                                                                      1. 1
                                                                                        1. 0
                                                                                          1. 0
                                                                                      2. 0
                                                                                        1. 0
                                                                                  2. 0
                                                                                    1. 0
                                                                                      1. 0
                                                                                        1. 0
                                                                                          1. 0
                                                                                            1. 0
                                                                                              1. 0
                                                                                              2. 0
                                                                2. 0
                                                                  1. 0
                                                                    1. 0
                3. 0
                  1. 0
                    1. 0
                    2. 0
          2. 0

            Einträge anordnen

            1. 0
              1. 0
                1. 0
                  1. 0
  2. 1

    Danke!

    1. 1
      1. 0
        1. 0
          1. 0

            Grundsatzdiskussion bind ./. fetch_assoc und prepare ./. mysqli_real_escape_string

            1. 0
              1. 0
                1. 0
                  1. 0
                    1. 0

                      Humor...

Hallo,

ich komme an einem Punkt leider nicht weiter. Und zwar möchte ich in die Spalte #KW (im PHP Code als xxx gekennzeichnet) immer die aktuelle Kalenderwoche der Zeile einfügen.

Der Aufbau schaut wie folgt aus

// Anzahl der Tage ermitteln $day_count = date('t', $timestamp); // 0:So 1:Mo 2:Di usw... $str = date('w', mktime(0, 0, 0, date('m', $timestamp), 0, date('Y', $timestamp))); // Kalender zusammenbauen!! $weeks = array(); $week = ''; // Leer Zeilen hinzufügen $week .= '<td>xxx</td>'; $week .= str_repeat('<td></td>', $str); for ( $day = 1; $day <= $day_count; $day++, $str++) { $date = $ym.'-'.$day; $week .= '<td><a href="day.php?date='.$date .'">'.$day .'</a>'; $week .= '</td>'; // Ende der Woche bzw. Ende des Monats if ($str % 7 == 6 || $day == $day_count) { if($day == $day_count) { // Zelle hinzufügen $week .= str_repeat('<td></td>', 6 - ($str % 7)); } $weeks[] = '<tr>'.$week.'</tr>'; // Neue Woche $week = ''; $week .= '<td>xxx</td>'; } }

Und die HTML Ausgabe so

<table> <tr> <th>KW</th> <th>Mo</th> <th>Di</th> <th>Mi</th> <th>Do</th> <th>Fr</th> <th>Sa</th> <th>So</th> </tr> <?php foreach ($weeks as $week) { echo $week; } ?> </table>

Wie könnte ich dieses am besten und einfachsten lösen?

Bis bald!
Bernd

Akzeptierte Antworten zum Thema:

  1. date('W', timestamp) liefert die Wochennummer nach ISO 8601. Wenn Du eine andere brauchst wird es schwieriger.

    Wenn Du keinen Timestamp hast kannst Du den auch aus einem String parsen lassen:

    <?php $t = strtotime( '2018-09-30' ); echo date( 'W', $t );

    Für mich sieht das einfach genug aus:

    $weekNumber = date( 'W', strtotime( "$Y-$m-$d" ) );
    1. Hallo Regina,

      date('W', timestamp) liefert die Wochennummer nach ISO 8601. Wenn Du eine andere brauchst wird es schwieriger.

      Wenn Du keinen Timestamp hast kannst Du den auch aus einem String parsen lassen:

      <?php $t = strtotime( '2018-09-30' ); echo date( 'W', $t );

      Für mich sieht das einfach genug aus:

      $weekNumber = date( 'W', strtotime( "$Y-$m-$d" ) );

      danke für deine Hilfe. Wenn ich dieses so einsetzte dann habe ich das Problem, dass ich immer die gleiche Kalenderwoche erhalte

      $t = strtotime( '2018-09-08' ); $week .= '<td>'. date( 'W', $t ).'</td>'; $week .= str_repeat('<td></td>', $str); for ( $day = 1; $day <= $day_count; $day++, $str++) { $date = $ym.'-'.$day; $week .= '<td><div><a href="day.php?date='.$date .'">'.$day .'</a></div>'; $week .= '</td>'; // Ende der Woche bzw. Ende des Monats if ($str % 7 == 6 || $day == $day_count) { if($day == $day_count) { // Zelle hinzufügen $week .= str_repeat('<td></td>', 6 - ($str % 7)); } $weeks[] = '<tr>'.$week.'</tr>'; // Neue Woche $week = ''; $week .= '<td>'. date( 'W', $t ) .'</td>'; } }

      dieses liegt liegt natürlich daran

      $t = strtotime( '2018-09-08' );

      Jetzt muss ich irgendwie ermitteln welches Datum jeweils am Wochenanfang ist?

      Bis bald!
      Bernd

      1. Jetzt muss ich irgendwie ermitteln welches Datum jeweils am Wochenanfang ist?

        Ja. Aber ich sehe:

        $date = $ym.'-'.$day;

        Das macht es einfach - oder?

        1. Hallo Regina,

          verstehe ich ehrlich gesagt nicht. Außerdem habe ich ein Wert außerhalb von

          for ( $day = 1; $day <= $day_count; $day++, $str++) { $date = $ym.'-'.$day; }

          den benötige ich, sonst wird die erste KW nicht eingefügt, sieh Bild

          Bis bald!
          Bernd

          1. Du hast Doch:

            $day_count = date( 't', $timestamp );

            vor der Schleife über die Tage. Ermittle dort auch die Woche.

            $weekNumber = date( 'W', $timestamp );

            In der Schleife kannst Du auch einfach hochzählen:

            for ( $day = 1; $day <= $day_count; $day++, $str++) { # Montags: if ( $str % 7 == 1 ) { $weekNumber ++; } }

            oder meinetwegen Montags die Wochennummer ermitteln.

            $str verwendet man üblicherweise für einen String mit äußerst kurzer Lebensdauer. Du solltest einen besseren Name finden, das hilft beim Programmieren.

            1. Hallo Regina,

              danke wieder für deine Hilfe. Jetzt habe ich immer in der ersten und zweite Woche die gleichen Wochennummern

              $weekNumber = date('W', $timestamp); $week .= '<td>'. $weekNumber .'</td>'; $week .= str_repeat('<td></td>', $str); for ( $day = 1; $day <= $day_count; $day++, $str++) { if ( $str % 7 == 1 ) { $weekNumber ++; } $date = $ym.'-'.$day; $week .= '<td><div><a href="day.php?date='.$date .'">'.$day .'</a></div>'; $week .= '</td>'; // Ende der Woche bzw. Ende des Monats if ($str % 7 == 6 || $day == $day_count) { if($day == $day_count) { // Zelle hinzufügen $week .= str_repeat('<td></td>', 6 - ($str % 7)); } $weeks[] = '<tr>'.$week.'</tr>'; // Neue Woche $week = ''; $week .= '<td>'. $weekNumber .'</td>'; } }

              Außer wenn der 1 gleich ein Montag ist.

              Ich habe hier ein Beispiel gefunden:
              https://www.tutorials.de/threads/kalenderwoche-neben-kalender-einfuegen.241980/

              Allerdings ist dieser Kalender komplett anderes aufgebaut. Da Frage ich mich, ob meine oder seine Version besser ist?

              Bis bald!
              Bernd

              1. Ganz einfach: setz die Wochennummer eben Sonntags hoch:

                if ( $str % 7 == 6 ) { $weekNumber ++; }
                1. Hallo Regina,

                  vielen vielen vielen vielen vielen DANK!

                  Bis bald!
                  Bernd

              2. Hallo Bernd,

                wie Du dieses Problem löst, zeige ich Dir jetzt, weil es als Programmierlektion wichtig ist - aber das kannst Du für deinen Kalender nicht verwenden! Reginas Tipp hat einen unangenehmen Fehler (wenn sonst nichts im Beitrag stände, müsste ich dafür das [-] klicken). Erklärung folgt.

                Du solltest das Erhöhen der Wochennummer und das Erstellen der Nummernspalte nicht trennen. Der Effekt ist bei Dir, dass beim ersten Wochenwechsel noch kein Inkrement stattgefunden hat. Entferne das $weekNumber++ vom Anfang der Schleife und setze es an dieser Stelle ein, ohne Bedingung (weil Du ja hier schon weißt dass ein Wochenwechsel vorliegt):

                // Neue Woche $week = ''; $week .= '<td>'. $weekNumber .'</td>';

                Und bei der Gelegenheit kannst Du auch das Leeren von $week und das Anhängen des ersten Inhaltes zu einem Befehl verbinden. Der Code müsste nach der Verschiebung so aussehen:

                // Neue Woche $weekNumber++; $week = '<td>'. $weekNumber .'</td>';

                Das könnte man noch verkürzen (in bester C-Tradition: Einzeilige Programme beliebiger Komplexität), indem man den ++ Operator als Präfix einsetzt ($a++ und ++$a inkrementieren beide $a, aber $a++ liefert den alten und ++$a den neuen Wert von $a):

                // Neue Woche $week = '<td>'. (++$weekNumber) .'</td>';

                Die Klammer ist formal nicht nötig, die habe ich als Lesehilfe gesetzt.

                Warum Du das nicht verwenden kannst

                2017 und 2016 hättest Du im Januar Probleme, weil da der 01.01. zur KW des vorigen Jahres gehört. Deine Wochen wären also von 52-56 oder von 53-57 gelaufen.

                Dieses Jahr hättest Du im Dezember Probleme, weil Du den 31.12. in die KW 53 setzen würdest. Er liegt aber in KW 01-2019.

                Am einfachsten ist es wohl, die KW pro Schleifendurchlauf neu von PHP bestimmen zu lassen. Und wenn Deine Programmstruktur in etwa der logischen Struktur der Ausgabe entspricht, tust Du Dich in einigem leichter! Als Leser tut man sich leichter, wenn Kommentare da sind die besagen, was da inhaltlich passiert. Ich habe mal ein paar eingefügt. Plus ein paar Kommentare mit technischen Hinweisen für Dich, die eine von dir bisher vorher nicht verwendete PHP Funktion erläutern.

                // Erzeugt ein Array mit den Elementen des Tagesdatums $today = getDate(); // Bestimme Wochentag des letzten Tages im vorigen Monat. 0=So, 1=Mo, ... 6=Sa $wDay = date('w', mktime(0,0,0,$today['mon'],0,$today['year'])); // $curDay ist der aktuell aufbereitete Kalendertag. Beginnt der Monat nicht mit // dem Montag, wird $curDay soweit rückgerechnet dass es einem Montag entspricht. Der vorher ermittelte $wDay-Wert passt dafür prima. $curDay = 1 - $wDay; // Tage im laufenden Monan. In $today[0] steht der Unix-Timestamp $day_count = date('t', $today[0]); // Helper für die Date-Links $ym = strftime("%Y-%m-", $today[0]); while ($curDay <= $day_count) { // mktime-Eigenschaft: Es rechnet Werte um, die außerhalb der erlaubten Bereich liegen. // Der -4.09.2018 entspricht dem 27.08. // $curDay wird so verwaltet, dass es zu diesem Zeitpunkt immer auf einem Montag steht. $week = "<td>" . date("W", mktime(0,0,0,$today['mon'],$curDay,$today['year'])) . "</td>"; // Eine Wochenzeile, bestehend aus 7 Tagen, produzieren for ($d=0; $d<7; $d++) { if ($curDay < 1 || $curDay > $day_count) { // außerhalb des Monatszeitfensters. Man könnte hier auch eine ausgegraute Tagesnummer // hinschreiben :) $week .= "<td></td>"; } else { $curDayFmt = sprintf("%02d",$curDay); $week .= "<td><div><a href='day.php?date=$ym$curDayFmt'>$curDay</a></div></td>"; } $curDay++; } $weeks[] = "<tr>" . $week . "</tr>"; }

                Der Code ist grob in PHP Sandbox getestet - aber keine Garantie für Korrektheit :). Er dürfte aber einige der bisherigen Probleme nicht mehr haben.

                Ein weiterer Schritt - geh ihn wenn Du willst

                Als weiteren Schritt könnte man jetzt noch einwenden, dass es falsch ist, Daten und HTML in einem zu generieren. EIGENTLICH müsste der bisher gezeigte Code eine Datenstruktur aufbauen, die einen Kalendermonat inclusive der Fülltage repräsentiert, und die dann im zweiten Schritt - da wo auch dein übriges HTML steht - als HTML dargestellt wird. Trennung von Fachlogik und Repräsentation heißt das Prinzip.

                Dein $weeks-Array sollte geschlüsselt sein mit den Wochennummern, der Inhalt sollte ein Array sein mit den darzustellenden Tagen. Ein Tag ist entweder leer oder eine Tagesnummer (integer). Jahr und Monat könnten String-Keys von $weeks sein. Wobei - $weeks ist dann der falsche Name, besser wäre dann $calendar_month oder so.

                D.h. das Basisgerüst ist dies (mit [] Operator statt ARRAY() ):

                $calendar_month = [ 'year' => $today['year'], 'month' => $today['mon'], 'day_count' => $day_count, 'weeks' => [] ];

                und die Wocheneinträge erzeugst Du stumpf so:

                while ($curDay <= $day_count) { $weekNr = date("W", mktime(0,0,0,$today['mon'],$curDay,$today['year'])); $week = []; for ($d=0; $d<7; $d++) { $week[] = $curDay++; } $calendar_month['weeks'][$weekNr] = $week; }

                Und dann kannst Du in der HTML Aufbereitung alles weitere tun. Da gehört es hin. Also: prüfen ob die Tagesnummer im Monat liegt, formatieren des Links, entscheiden wie ein Tag außerhalb des Monats dargestellt werden soll. Die Wochen verarbeitest Du da mit der Key=>Value Version von foreach:

                foreach ($calendar_month['weeks'] as $weekNr => $week) { ... }

                Rolf

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

                  danke für deine sehr ausführliche Erklärung. Allerdings funktioniert dieses leider nicht. Wenn ich meinen Code so umbaue wie du es beschrieben hast habe ich in jedem Monat die gleichen Wochennummern. Außerdem kann ich schlecht alles komplett umbauen, der Code hat im realen Einsatz knapp 500 Zeilen Code, wo Termine ausgelesen werden usw... das wäre ein Unding wenn ich dieses alles umbauen muss, ich sitze an diesem Kalender jetzt fast ein Jahr und es funktioniert noch immer nicht so wie ich es gerne hätte. Mit deinen Änderungen fange ich fast wieder bei 0 an, das kann ich leider nicht.

                  Schade, dann muss ich wohl auf meine Wochennummern verzichten.

                  Nur dass du mal siehst wie das ganze ausschaut. Hier der Code inkl. aller Abfragen und Abhängigkeiten.

                  $admin_kalenderarten = admin_kalenderarten($mysqli); function Kalender_Termine($mysqli, $datum, $teile25, $limit=false) { $values = $teile25; $empfaengerListe = "'".implode("','", $values)."'"; $select = "SELECT kt_id, kt_kalenderID, kt_datum, test, k_code, k_art, k_jobNr, k_bezeichnung, k_auto, k_farbe, k_datum_von, k_ganztags, k_von, k_bis, f_bezeichnung, f_kennzeichen, ka_farbe, kf_farbe, kf_color FROM kalender_termine LEFT JOIN kalender ON kalender.k_code = kalender_termine.kt_kalenderID LEFT JOIN fuhrpark ON fuhrpark.f_id = kalender.k_auto LEFT JOIN kalender_arten ON kalender_arten.ka_code = kalender.k_art LEFT JOIN kalender_terminfarbe ON kalender_terminfarbe.kf_farbe = kalender_arten.ka_farbe WHERE kt_datum=? AND k_art IN (" . $empfaengerListe . ") ORDER by test ASC"; if ($limit != false) { $stmt = $mysqli->prepare($select . " LIMIT ?" ); $stmt->bind_param("ss", $datum, $limit); } else { $stmt = $mysqli->prepare($select ); $stmt->bind_param("s", $datum); } $stmt->execute(); $stmt->bind_result($kt_id, $kt_kalenderID, $kt_datum, $test, $k_code, $k_art, $k_jobNr, $k_bezeichnung, $k_auto, $k_farbe, $k_datum_von, $k_ganztags, $k_von, $k_bis, $f_bezeichnung, $f_kennzeichen, $ka_farbe, $kf_farbe, $kf_color); $stmt->store_result(); if($stmt->num_rows() > 0) { while ($stmt->fetch()){ $Kalender_Termine[] = array( 'kt_id' => $kt_id, 'kt_kalenderID' => $kt_kalenderID, 'kt_datum' => $kt_datum, 'test' => $test, 'k_code' => $k_code, 'k_art' => $k_art, 'k_jobNr' => $k_jobNr, 'k_bezeichnung' => $k_bezeichnung, 'k_auto' => $k_auto, 'k_farbe' => $k_farbe, 'k_datum_von' => $k_datum_von, 'k_ganztags' => $k_ganztags, 'k_von' => $k_von, 'k_bis' => $k_bis, 'f_bezeichnung' => $f_bezeichnung, 'f_kennzeichen' => $f_kennzeichen, 'ka_farbe' => $ka_farbe, 'kf_farbe' => $kf_farbe, 'kf_color' => $kf_color ); } return $Kalender_Termine; } } // Vor und Zurück if (isset($_GET['ym'])) { $ym = $_GET['ym']; $parts = explode("-", $ym); $month = (int)$parts[1]; // convert string to integer $year = (int)$parts[0]; } else { // Aktueller Monat $ym = date('Y-m'); $parts = explode("-", $ym); $month = date("n"); $year = (int)$parts[0]; } $timestamp = strtotime($ym."-01"); if ($timestamp === false) { $timestamp = time(); } // Monate auf Deutsch $monate = array(1=>"Januar", 2=>"Februar", 3=>"März", 4=>"April", 5=>"Mai", 6=>"Juni", 7=>"Juli", 8=>"August", 9=>"September", 10=>"Oktober", 11=>"November", 12=>"Dezember"); // Heute ermitteln $today = date('Y-m-j', time()); // H3 Title $html_title = date('Y / m', $timestamp); // Prev & Next / Monat Link $prev = date('Y-m', mktime(0, 0, 0, date('m', $timestamp)-1, 1, date('Y', $timestamp))); $next = date('Y-m', mktime(0, 0, 0, date('m', $timestamp)+1, 1, date('Y', $timestamp))); // Anzahl der Tage ermitteln $day_count = date('t', $timestamp); // 0:So 1:Mo 2:Di usw... $str = date('w', mktime(0, 0, 0, date('m', $timestamp), 0, date('Y', $timestamp))); // Kalender zusammenbauen!! $weeks = array(); $week = ''; // Leer Zeilen hinzufügen $week .= str_repeat('<td></td>', $str); for ( $day = 1; $day <= $day_count; $day++, $str++) { $date = $ym.'-'.$day; $datumTermine = Kalender_Termine($mysqli, $date, $teile25, 3); $datumTermine_Alle = Kalender_Termine($mysqli, $date, $teile25); $test = count($datumTermine_Alle); if ($today == $date) { if ($test > 3) { $week .= '<td class="today testEintrag"><div style="margin:5px 8px">'.$day .' - <a href="tageskalender.php?date='.$date .'">Alle '.$test.' anzeigen</a></div>'; } else { $week .= '<td class="today testEintrag"><div style="margin:5px 8px"><a href="tageskalender.php?date='.$date .'">'.$day .'</a></div>'; } } else { if ($test > 3) { $week .= '<td class="testEintrag"><div style="margin:5px 8px">'.$day .' - <a href="tageskalender.php?date='.$date .'">Alle '.$test.' anzeigen</a></div>'; } else { $week .= '<td class="testEintrag"><div style="margin:5px 8px"><a href="tageskalender.php?date='.$date .'">'.$day .'</a></div>'; } } if($datumTermine > 0) { //$week .= '<br><br>'; foreach($datumTermine as $array){ $test_datum = $array["kt_datum"]; $wochentage = array ('So','Mo','Di','Mi','Do','Fr','Sa'); list ($jahr, $monat, $tag) = explode ('-', $test_datum) ; $datum = getdate(mktime ( 0,0,0, $monat, $tag, $jahr)); $wochentag = $datum['wday']; if ($array["kt_datum"] == $array["k_datum_von"]) { if ($array["k_ganztags"] == "0") { if ($array["k_jobNr"] == "") { $week .= '<div style="background:'.$array["ka_farbe"].'; margin-bottom:5px; padding-left:8px;"> <a href="/kalender-datenblatt.php?code='.$array["k_code"].'" style="color:'.$array["kf_color"].';">'. $array["k_bezeichnung"]. "</a> <span style='color:".$array["kf_color"]."; font-size:10px; display: block; padding-bottom: 2px;'>". $array["k_von"]. " bis " . $array["k_bis"]. " Uhr". '</span> </div>'; } else { $week .= '<div style="background:'.$array["ka_farbe"].'; margin-bottom:5px; padding-left:8px;"> <a href="/kalender-datenblatt.php?code='.$array["k_code"].'" style="color:'.$array["kf_color"].';">'. shortText($array["k_bezeichnung"],15). "</a> <span style='color:".$array["kf_color"]."; font-size:10px; display: block; padding-bottom: 2px;'>". $array["k_jobNr"] . " - " . $array["k_von"]. " bis " . $array["k_bis"]. " Uhr". '</span> </div>'; } } else { if ($array["k_auto"] == "") { if ($array["k_jobNr"] == "") { $week .= '<div style="background:'.$array["ka_farbe"].'; margin-bottom:5px; padding-left:8px; min-height: 37px;"> <a href="/kalender-datenblatt.php?code='.$array["k_code"].'" style="color:'.$array["kf_color"].'">'.shortText($array["k_bezeichnung"],15). '</a> </div>'; } else { $week .= '<div style="background:'.$array["ka_farbe"].'; margin-bottom:5px; padding-left:8px; min-height: 37px;"> <a href="/kalender-datenblatt.php?code='.$array["k_code"].'" style="color:'.$array["kf_color"].'">'.shortText($array["k_bezeichnung"],15). "</a> <span style='color:".$array["kf_color"]."; font-size:10px; display: block; padding-bottom: 2px;'>". $array["k_jobNr"]. '</span> </div>'; } } else { $week .= '<div style="background:'.$array["ka_farbe"].'; margin-bottom:5px; padding-left:8px; min-height: 37px;"> <a href="/kalender-datenblatt.php?code='.$array["k_code"].'" style="color:'.$array["kf_color"].'">'.shortText($array["f_bezeichnung"],15). "</a> <span style='color:".$array["kf_color"]."; font-size:10px; display: block; padding-bottom: 2px;'>". $array["k_jobNr"]. '</span> </div>'; } } } else { if ($wochentage[$wochentag] == "Mo") { if ($array["k_auto"] == "") { $week .= '<div style="background:'.$array["ka_farbe"].'; margin-bottom:5px; padding-left:8px; height: 37px;"><span style="color:'.$array["kf_color"].'"><a href="/kalender-datenblatt.php?code='.$array["k_code"].'" style="color:'.$array["kf_color"].'">'.shortText($array["k_bezeichnung"],15).'</a> <span style="color:'.$array["kf_color"].'; font-size:10px; display: block; padding-bottom: 2px;">'. $array["k_jobNr"]. '</span></div>'; } else { $week .= '<div style="background:'.$array["ka_farbe"].'; margin-bottom:5px; padding-left:8px; height: 37px;"><span style="color:'.$array["kf_color"].'"><a href="/kalender-datenblatt.php?code='.$array["k_code"].'" style="color:'.$array["kf_color"].'">'.shortText($array["f_bezeichnung"],15).'</a><span style="color:'.$array["kf_color"].'; font-size:10px; display: block; padding-bottom: 2px;">'. $array["k_jobNr"]. '</span></div>'; } } else { $week .= '<div style="background:'.$array["ka_farbe"].'; margin-bottom:5px; padding-left:8px; height: 37px;"></div>'; } } }} $week .= '</td>'; // Ende der Woche bzw. Ende des Monats if ($str % 7 == 6 || $day == $day_count) { if($day == $day_count) { // Zelle hinzufügen $week .= str_repeat('<td></td>', 6 - ($str % 7)); } $weeks[] = '<tr>'.$week.'</tr>'; // Neue Woche $week = ''; } }

                  Bis bald!
                  Bernd

                  Folgende Nachrichten verweisen auf diesen Beitrag:

                  1. Hallo Barksalot,

                    Wenn ich meinen Code so umbaue wie du es beschrieben hast habe ich in jedem Monat die gleichen Wochennummern.

                    Dann verwendest Du bei der Generierung der Wochennummer vielleicht die falsche Datum?

                    Deinen Gesamtcode müsste ich mir erstmal genauer anschauen und dafür habe ich dieses Wochenende keine Zeit. Teile davon hab es ja früher schon zu sehen. Aber ganz ehrlich: der schreit ohnehin "bau mich um". 500 Zeilen Code am Stück sind ungenießbares Spaghetti. Den musst Du nach Aufgaben in Funktionen zerlegen. Insbesondere in die Bereiche Datenbeschaffung, Datenaufbereitung und HTML-Erzeugung. Die Datenbeschaffung holt die benötigten DB-Inhalte und erzeugt ein Fachmodell der Daten. Die Datenaufbereitung setzt das Fachmodell in ein Viewmodell um. Und die HTML Erzeugung übersetzt das Viewmodell in HTML. Mein nachträglich reineditierter $calendar_month oben ist so ein Viewmodell. Das kann man über assoziative Arrays lösen, oder mit PHP Klassen. Ganz nach Geschmack und Know-How.

                    Ggf. solltest Du auch die style-Attribute reduzieren und mehr auf CSS setzen. Ohne genaueres Hingucken kann ich das nicht sicher sagen.

                    Wenn man baut und baut, ohne innezuhalten, dann entstehen solche Monster bevor man es bemerkt. Aber wenn sie da sind, muss man sie zerteilen. UNBEDINGT. Diese Arbeit lohnt sich. Ich war in meinen 33 Jahren Entwicklerarbeit nämlich auch schon öfter an der Stelle, wo Du jetzt bist. Mit noch größeren Monstern. Und nachdem man sowas ein paar Monate liegen gelassen hat, und DANN wieder einsteigen muss, bemerkt man erst die diversen Abhängigkeiten, auf die man aufpassen muss und die danach trachten, einem links und rechts die Zehen von den Füßen zu schießen.

                    Rolf

                    -- sumpsi - posui - clusi
                    1. hallo

                      Ggf. solltest Du auch die style-Attribute reduzieren und mehr auf CSS setzen. Ohne genaueres Hingucken kann ich das nicht sicher sagen.

                      eventuell meinst du auf <style> elemente setzen. Die darf man praktisch überall benutzen und da ja dynamisch Werte gesetzt werden, ist das ev. auch angebracht.

                      -- https://beat-stoecklin.ch/pub/index.html
                2. Hallo Rolf,

                  dein zweiter Abschnitt "Ein weiterer Schritt - geh ihn wenn Du willst" habe ich vorhin irgendwie gar nicht gesehen. Danke auch für diese Erklärung. Aber es bringt nichts, wenn ich diesen Code nicht in meinen Kalender integrieren kann ohne dass ich alles neu machen muss.

                  Schade dass die Option von Regina zu einem Fehler führt, dieser wäre so einfach gewesen. Sehr schade.

                  Bis bald!
                  Bernd

                  1. Hallo Barksalot,

                    hab mir den Code grad mal aus deinem Posting kopiert; sind doch nur 245 Zeilen 😂

                    Ich gehe das jetzt mal durch.

                    Rolf

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

                      hab mir den Code grad mal aus deinem Posting kopiert; sind doch nur 245 Zeilen 😂

                      😟 ich finde diesen dennoch viel zu groß/lang. Immer wieder neue Optionen hinzugefügt wenn ich etwas haben wollte bzw. gebraucht habe.

                      Ich frag mich manchmal wie machen das große Firmen sagen wir mal wie Facebook oder Google, da gibt es doch bestimmt Millionen von Zeilen Code? Wie kann man da den Überblick behalten bzw. wie wird dort ein Code erweitert? Es kann doch nicht immer alles komplett über den Haufen geworfene werden?

                      Und danke dir, dass du dir den ganzen Schlamassel mal anschaust.

                      Bis bald!
                      Bernd

                      1. Hallo Barksalot,

                        es wird auch nicht alles über den Haufen geworfen. Der Schlüssel heißt strikte Aufteilung. Bei Objektorientierung: Eine Methode, genau eine Aufgabe.

                        Und die Millionen an Codezeilen sind auch nicht alle voneinander abhängig, sondern so sehr wie es geht entkoppelt. D.h. in Mikroservices aufgeteilt, durch Interfaces voneinander abstrahiert, durch Unit Tests abgesichert, durch Dependency Injection entkoppelt, und viel mehr.

                        Das sind Themen die man nicht eben mal in einem Posting erklären kann, aber wenn Du Objektorientierung lernen und beherrschen willst, sind das die Programmiermuster, deren Anwendung du lernen musst, sonst ist OOP nur ein Aufkleber über dem alten "Modularisierung" Etikett aus prozeduraler Zeit.

                        Aber auch ohne OOP kann man Code aufteilen. Die Entkoppelung fällt nur schwerer. Aber genau das ist das Ziel der Informatik seit den 50er Jahren: Abstrahierung von der Maschine, Trennung der Verantwortlichkeiten, Austauschbarkeit von Implementierungen.

                        Rolf

                        -- sumpsi - posui - clusi
                      2. Hallo Barksalot,

                        boay ey, dein HTML ist echt etwas Besonderes. Diese ganzen manuellen Styles machen es unübersichtlich und es scheint auch einiges redundant zu sein.

                        Die Farben, die Du aus der DB holst, musst Du natürlich per style-Attribut hinzufügen. Der Rest ist eigentlich immer konstant und gehört in eine CSS Datei.

                        Ich verstehe allerdings ein paar Details nicht. Teils liegen sie in deiner Fachlichkeit.

                        • Deine Akrobatik, um den Wochentag des kt_datum zu bestimmen, verstehe ich nicht. Eigentlich kann strtotime() Datümer im Format yyyy-mm-dd automatisch verarbeiten. Einziger Grund für deine manuelle Behandlung könnten kt_datum Inhalte sein, die das Jahr zweistellig enthalten. Das würde strtotime durcheinander bringen. HAST DU SOWAS? Wenn ja, bereinige die DB...
                        • Das div, das einen Termineintrag einschließt, hat für "datum=datum_von und ganztags=0" keine Höhe, für "datum=datum_von und ganztags!=0" ein min-height:37px und für "datum!=datum_von" ein height:37px. Das muss alles so sein? Was bedeutet "datum=datum_von"? Erster/Einziger Tag eines Termins? Dann sollte das div eine Klasse "first-day" oder so bekommen. Für Ganztags eine Klasse "full-day". Und dann kannst Du die Höhen per Stylesheet steuern. Deine td für die Kalenderzellen haben ".testEintrag" Klassen, die könnte man als Anker nehmen (wobei testEintrag nach einem Rename ruft...).
                        td.testEintrag .first-day:not(.full-day) { min-height: 37px; } td.testEintrag :not(.first-day) { height: 37px; }
                        • Der mittlere Block (Datum=Tagesdatum, Ganztags!=0: Wenn k_auto leer ist, prüfst Du ob die Jobnummer leer ist und lässt sie dann weg. Ansonsten würdest Du auch eine leere Jobnummer ausgeben. Ist die Jobnummer garantiert gefüllt, wenn in k_auto was drinsteht, so dass diese Prüfung da irrelevant ist?
                        • Die Links im letzten Block (der Teil, wenn das Datum nicht das Tagesdatum ist): Nur da sind die Links in einen span eingehüllt. Warum ist das nötig?

                        Abgesehen davon habe ich die grundlegende Refaktorierung jetzt durch 😀. Geht sicher noch mehr, aber erstmal warte ich auf deine Antworten. Die Wochensteuerung kommt als nächstes, dafür brauche ich aber Zeit die ich am So+Mo nicht habe. Wird frühestens Di Abend was.

                        Rolf

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

                          boay ey, dein HTML ist echt etwas Besonderes. Diese ganzen manuellen Styles machen es unübersichtlich und es scheint auch einiges redundant zu sein.

                          Ich weiß, ich kann mich da gerne heute mal hinsetzten und den Code von dem ganzen manuellen Styles befreien. Dann ist er bestimmt etwas übersichtlicher.

                          • Deine Akrobatik, um den Wochentag des kt_datum zu bestimmen, verstehe ich nicht. Eigentlich kann strtotime() Datümer im Format yyyy-mm-dd automatisch verarbeiten. Einziger Grund für deine manuelle Behandlung könnten kt_datum Inhalte sein, die das Jahr zweistellig enthalten. Das würde strtotime durcheinander bringen. HAST DU SOWAS? Wenn ja, bereinige die DB...

                          In der Datenbank steht das Datum eigentlich im richtigen Format, siehe Screenshot

                          • Das div, das einen Termineintrag einschließt, hat für "datum=datum_von und ganztags=0" keine Höhe, für "datum=datum_von und ganztags!=0" ein min-height:37px und für "datum!=datum_von" ein height:37px. Das muss alles so sein?

                          Da siehst du mal was alles passieren kann, wenn man ständig einfach nur etwas hinzufügt ohne drauf zu achten was schon alles in einem anderen Code steht. Natürlich sollten hier alle min-height und height die gleichen px Angaben haben.

                          Was bedeutet "datum=datum_von"? Erster/Einziger Tag eines Termins? Dann sollte das div eine Klasse "first-day" oder so bekommen. Für Ganztags eine Klasse "full-day". Und dann kannst Du die Höhen per Stylesheet steuern. Deine td für die Kalenderzellen haben ".testEintrag" Klassen, die könnte man als Anker nehmen (wobei testEintrag nach einem Rename ruft...).

                          Genau, "datum=datum_von" bedeutet der erste Eintrag. Dann gibt es noch ein "datum=datum_bis", siehe Screenshot

                          Die beiden "datum=datum_von" und "datum=datum_bis" liegen in der Tabelle "kalender" das oben genannte Datum "kt_datum" liegt in der Tabelle kalender_termine.

                          • Der mittlere Block (Datum=Tagesdatum, Ganztags!=0: Wenn k_auto leer ist, prüfst Du ob die Jobnummer leer ist und lässt sie dann weg. Ansonsten würdest Du auch eine leere Jobnummer ausgeben. Ist die Jobnummer garantiert gefüllt, wenn in k_auto was drinsteht, so dass diese Prüfung da irrelevant ist?

                          Leider nein, ich bekomme diese Nummern manchmal erst sehr kurzfristig. Daher ist diese Prüfung leider unumgänglich.

                          • Die Links im letzten Block (der Teil, wenn das Datum nicht das Tagesdatum ist): Nur da sind die Links in einen span eingehüllt. Warum ist das nötig?

                          Diese habe ich eingefügt um die Schriftfarbe ändern zu können. Wenn ich dieses anderes machen könnte, können die natürlich auch weg. Stören aber auch nicht?

                          Hier siehst du mal einen kleinen Ausschnitt wie die Ausgabe ausschaut, sollte dieses vielleicht noch wichtig sein, dass du siehst was es mit den Farben usw. auf sich hat und vielen vielen dank für deine Hilfe

                          Bis bald!
                          Bernd

                      3. problematische Seite

                        <?php class MonthCalendar { public $locale = ''; # show https://msdn.microsoft.com/en-us/library/39cwe7zf(v=vs.90).aspx # show https://msdn.microsoft.com/en-us/library/cdax410z(v=vs.90).aspx # Linux: show results from `locale -a` # Linux: show /etc/locale.gen, edit and use `sudo locale-gen` public $maxDayNamesLength = 2; # 1 | 2 | 3 | 99 public $datum = false; public $htmlCalendarId = 'Calendar'; public $htmlCalendarClass = 'Calendar'; public $htmlThisDayId = 'ThisDay'; public $htmlHolidayClass = 'Holyday'; public $htmlPartialHolidayClass = 'PartialHolyday'; public $htmlSondayClass = 'Son'; public $htmlSaturdayClass = 'Sat'; public $yearNextSymbol = '⇨'; public $yearBeforeSymbol = '⇦'; public $monthNextSymbol = '→'; public $monthBeforeSymbol = '←'; public $arMonthList; public $arWeekdayList; public $daysSprintf = '%02d'; public $daysLinkSprintf = 'calendar.php?y=%04d&amp;m=%02d&amp;d=%02d'; public $outsideDaysShow = '&nbsp;'; public $showYear = true; public $showMonth = true; public $showWeekNr = true; public function __construct() { $this -> datum = mktime( 0,0,0, date('n'), 1, date('Y') ); if ($this -> locale) { $this -> setLocale ( $this -> locale ); } } private function getMonthNames() { for ( $i=1; $i<13; $i++ ) { $d = mkTime( 0, 0, 0, $i, 1, 1971 ); $names[$i] = strftime( '%B', $d ); } $names[0] = false; return $names; } private function getWeakDayNames() { for ( $i = 1; $i < 8; $i++ ) { $d = mkTime(0, 0, 0, 1, 3+$i, 1971); $names[$i] = mb_substr( strftime( '%A', $d ) , 0, $this -> maxDayNamesLength); } $names[0] = $names[7]; return $names; } public function setLocale( $locale ) { if (false === setlocale( LC_TIME, $locale ) ) { trigger_error("Ungültige Locale-Einstellung: $locale", E_USER_NOTICE); } $this -> arMonthList = $this -> getMonthNames(); $this -> arWeekdayList = $this -> getWeakDayNames(); } public function setYear($y) { $i = intval($y); $t = mktime(1, 1, 1, 12, 31, $y); if ( $t && $i == $y ) { $m = date('n', $this -> datum ); $this -> datum = mktime( 0, 0, 0, $m, 1, $y ); return true; } else { trigger_error("Ungültiges Jahr: $y" ); return false; } } public function setMonth($m) { $i = intval($m); if ($m > 0 && $m <= 12 && $i == $m ) { $y = date('y', $this -> datum ); if ( mktime( 0,0,0, $m, 1, $y ) ) { $this -> datum = mktime( 0,0,0, $m, 1, $y ); return true; } else { trigger_error("UngültigesDatum"); } } else { return false; } } public function setYearNext () { $y = date( 'Y', $this -> datum ) + 1; $m = date( 'n', $this -> datum ); if ( mktime( 0,0,0, $m, 1, $y ) ) { $this -> datum = mktime( 0,0,0, $m, 1, $y ); return true; } else { trigger_error("Ungültiges Jahr: " . $y ); return false; } } public function setYearBefore () { $y = date( 'Y', $this -> datum ) - 1; $m = date( 'n', $this -> datum ); if ( mktime( 0,0,0, $m, 1, $y ) ) { $this -> datum = mktime( 0,0,0, $m, 1, $y ); return true; } else { trigger_error("Ungültiges Jahr: " . $y ); return false; } } public function setMonthNext () { $y = date( 'Y', $this -> datum ); $m = date( 'n', $this -> datum ) + 1; if ( mktime( 0,0,0, $m, 1, $y ) ) { $this -> datum = mktime( 0,0,0, $m, 1, $y ); return true; } else { trigger_error("UngültigesDatum"); return false; } } public function setMonthBefore () { $y = date( 'Y', $this -> datum ); $m = date( 'n', $this -> datum ) - 1; if ( mktime( 0,0,0, $m, 1, $y ) ) { $this -> datum = mktime( 0,0 ,0, $m, 1, $y ); return true; } else { trigger_error("UngültigesDatum"); return false; } } public function getCalendar() { if ( $this -> htmlCalendarId ) { $htmlCalendarId = ' id="' . $this -> htmlCalendarId .'"'; } if ( $this -> htmlCalendarClass ) { $htmlCalendarClass=' class="' . $this -> htmlCalendarClass .'"'; } if ( $this -> showWeekNr ) { $headerCols=8; } else { $headerCols=6; } $year = date( 'Y', $this -> datum ); $month = date( 'n', $this -> datum ); $out = ' <table' . $htmlCalendarId . $htmlCalendarClass . '> <thead>'; if ( $this -> showYear ) { $out .= ' <tr class="CalendarYearRow"> <th>' . $this -> yearBeforeSymbol . '</th> <th colspan=' . ( $headerCols - 2 ) . '>' . $year . '</th> <th>' . $this -> yearNextSymbol . '</th> </tr>'; } if ( $this -> showMonth ) { $out .= ' <tr class="CalendarMountRow"> <th>' . $this -> monthBeforeSymbol . '</th> <th colspan=' . ($headerCols - 2) . '>' . $this -> arMonthList[$month] . '</th> <th>' . $this -> monthNextSymbol . '</th> </tr>'; } $out .= ' <tr class="CalendarWeekDayRow">'; if ( $this -> showWeekNr ) { $out .= ' <th class="weeksColumn"></th>'; } $out .= ' <th>' . $this -> arWeekdayList[1] . '</th> <th>' . $this -> arWeekdayList[2] . '</th> <th>' . $this -> arWeekdayList[3] . '</th> <th>' . $this -> arWeekdayList[4] . '</th> <th>' . $this -> arWeekdayList[5] . '</th> <th>' . $this -> arWeekdayList[6] . '</th> <th>' . $this -> arWeekdayList[7] . '</th> </tr>'; $firstWeekDay = date( 'N', $this -> datum ); $WeekNumber = date( 'W', $this -> datum ); $lastDayofMounth = date( 't', $this -> datum ); # Nicht zugehörige Tage: $out .= ' <tr>'; if ( $this -> showWeekNr ) { $out .= ' <th class="weeksColumn">' . sprintf($this -> daysSprintf, $WeekNumber) . '</th>'; } $counter = 0; for ($i = 1; $i<$firstWeekDay; $i++) { $out .= ' <td class="outsideDay">' . $this -> outsideDaysShow . '</td>'; $counter++; } # zugehörige Tage: for ($i=1; $i <= $lastDayofMounth; $i++) { if ( ! $this -> daysLinkSprintf ) { $link=''; $endlink=''; } else { $link = '<a href="' . sprintf ($this -> daysLinkSprintf, date( 'Y', $this -> datum ), date( 'n', $this -> datum ), $i ) . '">'; $endlink = '</a>'; } if ( 6 == ( $counter + 8 ) % 7 ) { $class = 'class="' . $this -> htmlSaturdayClass .'" '; } else if ( 0 == ( $counter + 8 ) % 7 ) { $class = 'class="' . $this -> htmlSondayClass .'" '; } else if ( date('Y') == $year && date('n') == $month && date('j') == $i ) { $class = 'class="today" '; } else { $class = ''; } $out .= ' <td ' . $class . 'data-Datum="' . sprintf( '%04d-%02d-%02d', date( 'Y', $this->datum ), date( 'm', $this->datum ), $i ) . '">' . $link . sprintf( $this -> daysSprintf, $i ) . $endlink . '</td>'; $counter++; if ($i < $lastDayofMounth && 0 == ( $counter ) % 7 ) { $out .= ' </tr> <tr>'; if ( $this -> showWeekNr ) { if ( 53 == $WeekNumber) { $WeekNumber = 0; } $out .= ' <th class="weeksColumn">' . sprintf($this -> daysSprintf, ++$WeekNumber) . '</th>'; } } } # Nicht zugehörige Tage: while (0 != $counter % 7) { $out .= ' <td class="outsideDay">' . $this -> outsideDaysShow . '</td>'; $counter++; } $out .= ' </tr> </tbody> </table> '; return $out; } public function printCalendar() { echo $this -> getCalendar(), "\n"; } }

                        Aufruf:

                        <?php error_reporting( E_ALL ); ini_set( "display_errors", 1 ); require 'MonthCalendar.php'; $o = new MonthCalendar(); #$o -> setLocale( 'de_DE.utf-8' ); $o -> setLocale( 'de_AT.utf-8' ); #$o -> setLocale( 'fi_FI.utf-8' ); #$o -> setLocale( 'ar_YE.utf-8' ); if ( isset( $_GET['action'] ) ) { if( 'nextYear' == $_GET['action'] ) { $o-> setYearNext(); } if( 'earlierYear' == $_GET['action'] ) { $o-> setYearBefore(); } if( 'nextMonth' == $_GET['action'] ) { $o-> setMonthNext(); } if( 'earlierMonth' == $_GET['action'] ) { $o-> setMonthBefore(); } } if ( isset( $_GET['y'] ) ) { $o-> setYear($_GET['y']); } if ( isset( $_GET['m'] ) ) { $o-> setMonth($_GET['m']); } $o->daysSprintf = '%d'; # '%02d'-> "01" (default) , '%d' -> "1" #$o -> setYear(2200); #$o -> setMonthNext(); $o -> daysLinkSprintf='https://home.fastix.org/Tests/PHP:Feiertage/test-feiertage-form.php?jahr=%04d&amp;monat=%02d&amp;tag=%02d'; ?> <!Doctype html> <html> <head> <title>Kalender</title> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=Edge"> <meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"> <style type="text/css"> body, html { font-family: sans-serif; } #Calendar td, #Calendar th { text-align:center; min-width:2.0em; border: 2px solid transparent; border-collapse: collapse; border-radius: 5px; } #Calendar td.today { background-color: #9c27b0; color:#f5f5f5; font-weight:900; } #Calendar td a, #Calendar td a:link, #Calendar td a:visited, #Calendar td a:hover, #Calendar td a:focus { display:block; width:100%; height:100%; text-decoration: none; color: inherit; } #Calendar th { background-color: #b2ebf2; } #Calendar td.Sat { background-color: #f8bbd0; } #Calendar td.Son { background-color: #f48fb1; } #Calendar td:hover { border-color: #d1c4e9; font-weight: 900; } #Calendar td.outsideDay:hover { border-color: transparent; } </style> <head> <body> <hr> <?php for ( $m=1; $m < 13; $m++ ) { #$o = new MonthCalendar(); $o -> setMonth($m); echo $o -> getCalendar(), "<br>\n"; } ?> </body> </html>
                        1. problematische Seite

                          Es hat wegen der Einschränkung des Forums nicht alles gepasst.

                          • Die Testausgabe ist via "problematische Seite" erreichbar.

                          • Falls Dich der "Jänner" (Januar) in der Ausgabe stört, sieh Dir die Zeile

                          $o -> setLocale( 'de_AT.utf-8' );

                          in der aufrufenden Seite an. Sind alle (sudo apt install locales-all) oder die passenden lokales installiert kann man den Request-Header übersetzen. Welche locales installiert sind erfährt man unter Linux mit locale -a oder z.B. apt list "locales*"

                        2. problematische Seite

                          Die eigentlichen Termine solltest über ein zweites Objekt zur Verfügung stellen. Das hat in etwa den Job, die Termine für einen bestimmten Zeitraum (z.B. den angezeigten Monat) bereit zustellen (eg. $t = newTermine(2018, 9, '*', ['privat', 'dienstlich'])) ($t = newTermine(intJahr, intMonat, intTag or *, arrayKategorien or *)) und über eine Methode ($t -> getTermine(2018, 9, 30, '*', '*')) als Array zu liefern.

                          1. problematische Seite

                            Hallo Regina,

                            danke auch dir für deine Hilfe. Dein Code weicht natürlich vollständig von meinem ab und auch die Darstellung hast du komplett anderes. Ich habe Termine im jeweiligen Feld stehen, siehe Screenshot

                            Aber auch dein Kalender hat der Fehler, der @Rolf B genannt hat, der 31.12.2018 ist in der KW 1 und nicht wie bei dir und mir in KW 53

                            Hier sieht du die korrekten Kalenderwochen:
                            http://kalenderwoche.net/alle-kalenderwochen-2018.php

                            Bis bald!
                            Bernd

                            1. problematische Seite

                              Aber auch dein Kalender hat der Fehler, der @Rolf B genannt hat, der 31.12.2018 ist in der KW 1 und nicht wie bei dir und mir in KW 53

                              Korrigiert. Tests:

                              Also, das Gestalten der Tabelle und das Einfügen der Termine, verschiedene Ansichten wie Tages oder Wochenansicht überlasse ich jetzt mal Dir, weil ich Deine Datenbasis nicht kenne.

                              <?php class MonthCalendar { public $locale = ''; # show https://msdn.microsoft.com/en-us/library/39cwe7zf(v=vs.90).aspx # show https://msdn.microsoft.com/en-us/library/cdax410z(v=vs.90).aspx # Linux: show results from `locale -a` # Linux: show /etc/locale.gen, edit and use `sudo locale-gen` public $maxDayNamesLength = 2; # 1 | 2 | 3 | 99 public $datum = false; public $htmlCalendarId = 'Calendar'; public $htmlCalendarClass = 'Calendar'; public $htmlThisDayId = 'ThisDay'; public $htmlHolidayClass = 'Holyday'; public $htmlPartialHolidayClass = 'PartialHolyday'; public $htmlSondayClass = 'Son'; public $htmlSaturdayClass = 'Sat'; public $yearNextSymbol = '⇨'; public $yearBeforeSymbol = '⇦'; public $monthNextSymbol = '→'; public $monthBeforeSymbol = '←'; public $arMonthList; public $arWeekdayList; public $daysSprintf = '%02d'; public $daysLinkSprintf = 'calendar.php?y=%04d&amp;m=%02d&amp;d=%02d'; public $outsideDaysShow = '&nbsp;'; public $showYear = true; public $showMonth = true; public $showWeekNr = true; public function __construct() { $this -> datum = mktime( 0,0,0, date('n'), 1, date('Y') ); if ($this -> locale) { $this -> setLocale ( $this -> locale ); } } private function getMonthNames() { for ( $i=1; $i<13; $i++ ) { $d = mkTime( 0, 0, 0, $i, 1, 1971 ); $names[$i] = strftime( '%B', $d ); } $names[0] = false; return $names; } private function getWeakDayNames() { for ( $i = 1; $i < 8; $i++ ) { $d = mkTime(0, 0, 0, 1, 3+$i, 1971); $names[$i] = mb_substr( strftime( '%A', $d ) , 0, $this -> maxDayNamesLength); } $names[0] = $names[7]; return $names; } public function setLocale( $locale ) { if (false === setlocale( LC_TIME, $locale ) ) { trigger_error("Ungültige Locale-Einstellung: $locale", E_USER_NOTICE); } $this -> arMonthList = $this -> getMonthNames(); $this -> arWeekdayList = $this -> getWeakDayNames(); } public function setYear($y) { $i = intval($y); $t = mktime(1, 1, 1, 12, 31, $y); if ( $t && $i == $y ) { $m = date('n', $this -> datum ); $this -> datum = mktime( 0, 0, 0, $m, 1, $y ); return true; } else { trigger_error("Ungültiges Jahr: $y" ); return false; } } public function setMonth($m) { $i = intval($m); if ($m > 0 && $m <= 12 && $i == $m ) { $y = date('y', $this -> datum ); if ( mktime( 0,0,0, $m, 1, $y ) ) { $this -> datum = mktime( 0,0,0, $m, 1, $y ); return true; } else { trigger_error("UngültigesDatum"); } } else { return false; } } public function setYearNext () { $y = date( 'Y', $this -> datum ) + 1; $m = date( 'n', $this -> datum ); if ( mktime( 0,0,0, $m, 1, $y ) ) { $this -> datum = mktime( 0,0,0, $m, 1, $y ); return true; } else { trigger_error("Ungültiges Jahr: " . $y ); return false; } } public function setYearBefore () { $y = date( 'Y', $this -> datum ) - 1; $m = date( 'n', $this -> datum ); if ( mktime( 0,0,0, $m, 1, $y ) ) { $this -> datum = mktime( 0,0,0, $m, 1, $y ); return true; } else { trigger_error("Ungültiges Jahr: " . $y ); return false; } } public function setMonthNext () { $y = date( 'Y', $this -> datum ); $m = date( 'n', $this -> datum ) + 1; if ( mktime( 0,0,0, $m, 1, $y ) ) { $this -> datum = mktime( 0,0,0, $m, 1, $y ); return true; } else { trigger_error("UngültigesDatum"); return false; } } public function setMonthBefore () { $y = date( 'Y', $this -> datum ); $m = date( 'n', $this -> datum ) - 1; if ( mktime( 0,0,0, $m, 1, $y ) ) { $this -> datum = mktime( 0,0 ,0, $m, 1, $y ); return true; } else { trigger_error("UngültigesDatum"); return false; } } public function getCalendar() { if ( $this -> htmlCalendarId ) { $htmlCalendarId = ' id="' . $this -> htmlCalendarId .'"'; } if ( $this -> htmlCalendarClass ) { $htmlCalendarClass=' class="' . $this -> htmlCalendarClass .'"'; } if ( $this -> showWeekNr ) { $headerCols=8; } else { $headerCols=6; } $year = date( 'Y', $this -> datum ); $month = date( 'n', $this -> datum ); $out = ' <table' . $htmlCalendarId . $htmlCalendarClass . '> <thead>'; if ( $this -> showYear ) { $out .= ' <tr class="CalendarYearRow"> <th>' . $this -> yearBeforeSymbol . '</th> <th colspan=' . ( $headerCols - 2 ) . '>' . $year . '</th> <th>' . $this -> yearNextSymbol . '</th> </tr>'; } if ( $this -> showMonth ) { $out .= ' <tr class="CalendarMountRow"> <th>' . $this -> monthBeforeSymbol . '</th> <th colspan=' . ($headerCols - 2) . '>' . $this -> arMonthList[$month] . '</th> <th>' . $this -> monthNextSymbol . '</th> </tr>'; } $out .= ' <tr class="CalendarWeekDayRow">'; if ( $this -> showWeekNr ) { $out .= ' <th class="weeksColumn"></th>'; } $out .= ' <th>' . $this -> arWeekdayList[1] . '</th> <th>' . $this -> arWeekdayList[2] . '</th> <th>' . $this -> arWeekdayList[3] . '</th> <th>' . $this -> arWeekdayList[4] . '</th> <th>' . $this -> arWeekdayList[5] . '</th> <th>' . $this -> arWeekdayList[6] . '</th> <th>' . $this -> arWeekdayList[7] . '</th> </tr>'; $firstWeekDay = date( 'N', $this -> datum ); $WeekNumber = date( 'W', $this -> datum ); $lastDayofMounth = date( 't', $this -> datum ); # Nicht zugehörige Tage: $out .= ' <tr>'; if ( $this -> showWeekNr ) { $out .= ' <th class="weeksColumn">' . sprintf($this -> daysSprintf, $WeekNumber) . '</th>'; } $counter = 0; for ($i = 1; $i<$firstWeekDay; $i++) { $out .= ' <td class="outsideDay">' . $this -> outsideDaysShow . '</td>'; $counter++; } # zugehörige Tage: for ($i=1; $i <= $lastDayofMounth; $i++) { if ( ! $this -> daysLinkSprintf ) { $link=''; $endlink=''; } else { $link = '<a href="' . sprintf ($this -> daysLinkSprintf, date( 'Y', $this -> datum ), date( 'n', $this -> datum ), $i ) . '">'; $endlink = '</a>'; } if ( 6 == ( $counter + 8 ) % 7 ) { $class = 'class="' . $this -> htmlSaturdayClass .'" '; } else if ( 0 == ( $counter + 8 ) % 7 ) { $class = 'class="' . $this -> htmlSondayClass .'" '; } else if ( date('Y') == $year && date('n') == $month && date('j') == $i ) { $class = 'class="today" '; } else { $class = ''; } $out .= ' <td ' . $class . 'data-Datum="' . sprintf( '%04d-%02d-%02d', date( 'Y', $this->datum ), date( 'm', $this->datum ), $i ) . '">' . $link . sprintf( $this -> daysSprintf, $i ) . $endlink . '</td>'; $counter++; if ($i < $lastDayofMounth && 0 == ( $counter ) % 7 ) { $out .= ' </tr> <tr>'; if ( $this -> showWeekNr ) { $WeekNumber = date('W', strtotime(date( 'Y-m-', $this->datum ) . ( $i + 1 ) ) ); $out .= ' <th class="weeksColumn" title="' . ( $i + 1 ) . '">' . sprintf($this -> daysSprintf, $WeekNumber) . '</th>'; } } } # Nicht zugehörige Tage: while (0 != $counter % 7) { $out .= ' <td class="outsideDay">' . $this -> outsideDaysShow . '</td>'; $counter++; } $out .= ' </tr> </tbody> </table> '; return $out; } public function printCalendar() { echo $this -> getCalendar(), "\n"; } }
                              1. problematische Seite

                                Hallo Regina,

                                danke nochmals für deine Hilfe, aber mit diesem Code kann ich leider überhaupt nichts anfangen. Dieser weicht komplett von meinem ab.

                                Bis bald!
                                Bernd

                                1. problematische Seite

                                  aber mit diesem Code kann ich leider überhaupt nichts anfangen. Dieser weicht komplett von meinem ab.

                                  echo 'aber mit diesem Code kann ich leider überhaupt nichts anfangen. Dieser weicht komplett von meinem ab.' | sed -e 's/ kann / will /'

                                  Können kannst Du schon.

                                  Die Größen der Felder sind HTML und CSS, die Termine aus der Datenquelle zu holen ist Sache eines weiteren Objekts $termins, welches Du beim construct ($cal=new Calendar($termins)) durchreichst. Die müssen also nur noch eingetragen werden. Der Link vom Tag kann zu "alle Termine" anzeigen" verschoben werden und dann eine Tagesansicht liefern...

                                  1. problematische Seite

                                    Hallo Regina,

                                    einer der sich damit auskennt, der kann es vielleicht, ich nicht! Du hast vielleicht mein Code gesehen wie dieses ausschaut?

                                    https://forum.selfhtml.org/self/2018/sep/8/kw-als-spalte-einfuegen/1731443#m1731443

                                    Bis bald!
                                    Bernd

                                    1. problematische Seite

                                      einer der sich damit auskennt, der kann es vielleicht, ich nicht!

                                      Das ist so: Wenn man noch lernt macht man auch mal was von Beginn an falsch. Das ist nicht schlimm, man muss aber dazu bereit sein, auch mal was wieder einzureißen und natürlich mehr Zeit zu planen.

                                      Du hast Dir für Deine ersten Schritte auch ganz schön viel vorgenommen … aber das hab ich seinerzeit genau so gemacht: Ich hab als Anfänger in perl eine Wohnungssuchmaschine geschrieben und später (wieder als Anfänger) nach PHP übersetzt. Das war ganz schön heftig.

                                      Also: Nicht verzagen!

                                      Ich mach mich jetzt reisefertig. Morgen ist Excel-VBA mit mir als Seminarleiter angesagt.

                                      1. problematische Seite

                                        Hallo Regina,

                                        ich wollte eigentlich nur Kalenderwochen einfügen. Mit dem Rest wäre ich zufrieden gewesen denn es funktioniert. Ich sitze da jetzt fast ein Jahr dran. Und jetzt alles wieder komplett ändern? Für die 1-2 Jahre die ich vielleicht noch zu leben habe?

                                        Scheinbar geht es nicht in meinen Code Wochennummern einzufügen, schade damit muss ich dann eben leben. In den Code von dir kann ich auf keine Fälle meine Termin eintragen mit den ganzen Abhängigkeiten die ich habe.

                                        Außerdem habe ich nur Monatsansichten und keine Jahresansichten so wie du es hast.

                                        Bis bald!
                                        Bernd

                                        1. problematische Seite

                                          Außerdem habe ich nur Monatsansichten und keine Jahresansichten so wie du es hast.

                                          Hm. Wenn Du in der testMonthCalendar.php die For-Schleife weglässt wirst Du sehen, dass dass es nicht ein Jahreskalender sondern 12 Monatskalender sind:

                                          <?php error_reporting( E_ALL ); ini_set( 'display_errors', 1 ); require 'MonthCalendar.php'; $o = new MonthCalendar(); $o -> setLocale( 'de_DE.utf-8' ); if ( isset( $_GET['action'] ) ) { if( 'nextYear' == $_GET['action'] ) { $o -> setYearNext(); } if( 'earlierYear' == $_GET['action'] ) { $o -> setYearBefore(); } if( 'nextMonth' == $_GET['action'] ) { $o -> setMonthNext(); } if( 'earlierMonth' == $_GET['action'] ) { $o -> setMonthBefore(); } } if ( isset( $_GET['y'] ) ) { $o -> setYear($_GET['y']); } if ( isset( $_GET['m'] ) ) { $o -> setMonth($_GET['m']); } $o -> daysSprintf = '%d'; # '%02d' -> "01" (default) , '%d' -> "1" $o -> daysLinkSprintf='https://home.fastix.org/Tests/PHP:Feiertage/test-feiertage-form.php?jahr=%04d&amp;monat=%02d&amp;tag=%02d'; ?> <!Doctype html> <html> <head> <title>Kalender</title> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=Edge"> <meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"> <style type="text/css"> body, html { font-family: sans-serif; } table.Calendar td, table.Calendar th { text-align:center; min-width:2.0em; border: 2px solid transparent; border-collapse: collapse; border-radius: 5px; } table.Calendar td.ThisDay { background-color: #9c27b0; color:#f5f5f5; font-weight:900; } table.Calendar td a, table.Calendar td a:link, table.Calendar td a:visited, table.Calendar td a:hover, table.Calendar td a:focus { display:block; width:100%; height:100%; text-decoration: none; color: inherit; } table.Calendar th { background-color: #b2ebf2; } table.Calendar td.Sat { background-color: #f8bbd0; } table.Calendar td.Son { background-color: #f48fb1; } table.Calendar td:hover { border-color: #d1c4e9; font-weight: 900; } table.Calendar td.NotExistentDay:hover { border-color: transparent; } </style> <head> <body> <hr> <?php $o -> printCalendar(); ?> </body> </html>

                                          So. Auf und davon jetzt!

                                    2. problematische Seite

                                      Hallo Bernd,

                                      wenn ich mit dem Refactoring durch bin, sieht der Code auch ganz anders aus. Das ist unvermeidlich.

                                      Der Unterschied zu Regina wird sein, dass ich deine Lernkurve nicht mit OOP zusätzlich steiler machen will. Das heißt nicht, dass das für dich nicht von Interesse sein sollte. Mit OOP und den davon gebotenen Möglichkeiten kann man Dinge in den Griff bekommen, die klassisch prozedural sehr schwierig oder umständlich sind.

                                      Soweit ich das am Handy erkennen kann (während hinter mir das Pfarrfest tobt), hat Regina auch das HTML geputzt.

                                      Rolf

                                      -- sumpsi - posui - clusi
                              2. problematische Seite

                                hallo

                                Beispiel

                                $out .= ' <tr class="CalendarYearRow"> <th>' . $this -> yearBeforeSymbol . '</th> <th colspan=' . ( $headerCols - 2 ) . '>' . $year . '</th> <th>' . $this -> yearNextSymbol . '</th> </tr>'; } if ( $this -> showMonth ) { $out .= ' <tr class="CalendarMountRow"> <th>' . $this -> monthBeforeSymbol . '</th> <th colspan=' . ($headerCols - 2) . '>' . $this -> arMonthList[$month] . '</th> <th>' . $this -> monthNextSymbol . '</th> </tr>'; }

                                ...etc

                                Könnte nicht schaden, das ganze im semantischen und zugänglichen Sinne zu überarbeiten.

                                -- https://beat-stoecklin.ch/pub/index.html
                                1. problematische Seite

                                  Steht nicht umsonst in "/Tests/work"… und ich habe es als Vorgehensweise beschrieben.

                                  1. problematische Seite

                                    hallo

                                    Steht nicht umsonst in "/Tests/work"… und ich habe es als Vorgehensweise beschrieben.

                                    Hab ich mir schon gedacht. Wollts nur gesagt haben, weil man sonst auf falsche Gedanken kommen könnte.

                                    Für Testausgaben sollte da auch ein printf reichen.

                                    -- https://beat-stoecklin.ch/pub/index.html
                              3. problematische Seite

                                Der ganze Trick besteht darin, sich

                                • Am Monatsbeginn die Wochennummer vom 1. und danach
                                • quasi schon Sonntags die Wochennummer vom Montag ( aktueller tag +1 ) zu holen.
                                if ( $this -> showWeekNr ) { $WeekNumber = date( 'W', strtotime(date( 'Y-m-', $this->datum ) . ( $i + 1 ) ) ); $out .= ' <th class="weeksColumn">' . sprintf( $this -> daysSprintf, $WeekNumber ) . '</th>';
                              4. problematische Seite

                                Hallo Regina,

                                so, jetzt bin ich mal zum tieferen Überfliegen deines Codes gekommen.

                                Hast Du das für dieses Posting zusammengeschneidert? Oder lag das fertig in deiner Code-Schublade? Ich vermute ersteres, z.B. ist das Errorhandling unvollständig (z.B. ohne setlocale() sind keine Tages-/Monatsnamen da und man greift auf null mit Array-Operatoren zu).

                                Ich bin auch mit den setYear.../setMonth... Methoden unzufrieden; das ist Datumsarithmetik und der Rest Deiner Klasse befasst sich dem Rendern des HTML für einen Kalender. Da werden Concerns vermischt.

                                Trotz der kleinen Kritik: für ein "schnelles Beispiel" ist das eine ganze Menge, was Du da gebaut hast. Das Thema "Datenversorgung" hätte ich beinah kritisiert - aber dann gesehen dass Du das als Übung für Bernd zurückgestellt hast.

                                Für Bernd ist es ein Beispiel, wie man Code in Klassen kapseln kann, und es zeigt einige I18N Aspekte. Es sind auch wichtige Vorschläge für's HTML drin. Für ein OOP Muster ist allerdings die getCalendar Methode viel zu unhandlich, da muss man nochmal dringend mit der Axt ran und sie in kleinere Elemente zerlegen. Das Wochen-Handling gehört z.B. in eine private beginRow Methode, die dann vor der Schleife sowie in der Schleife aufgerufen wird. Die Ermittlung von $class sollte auch isoliert sein, etc.

                                Für die Datenversorgung könnte man eine abstrakte Methode renderDay($datum) vorsehen. Ein Anwender kann dann eine Subklasse erzeugen, renderDay überschreiben und darüber das Markup für einen Tagesinhalt zurückliefern. Die nötige SQL Abfrage KÖNNTE dann in renderDay stattfinden, oder man greift auf einen bereits geladenen Datenbestand zu.

                                Ich hoffe, ich komme morgen dazu, mein prozedurales Refactoring vorzustellen.

                                Rolf

                                -- sumpsi - posui - clusi
                  2. Hallo Bernd,

                    ich bin jetzt durch und möchte Dir meinen Stand vorstellen. Er ist NICHT objektorientiert, damit er zum Rest deines Codes passt. Vielleicht könnte man über eine Hybridlösung nachdenken, d.h. prozedurale Programmierung mit Klassenunterstützung. Ich habe aber den Eindruck, dass dein Know How an diesem Punkt noch nicht ist. Wenn doch, kann man dahingehend weiter machen.

                    Deinen Code ersetze ich zunächst einmal im Wesentlichen durch zwei Funktionsaufrufe. Den Teil, mit dem ich nichts anfangen konnte, habe ich stehen gelassen 😂

                    $admin_kalenderarten = admin_kalenderarten($mysqli); // Monate auf Deutsch $monate = array(1=>"Januar", 2=>"Februar", 3=>"März", 4=>"April", 5=>"Mai", 6=>"Juni", 7=>"Juli", 8=>"August", 9=>"September", 10=>"Oktober", 11=>"November", 12=>"Dezember"); // Anzuzeigenden Monat aus $_GET["ym"] laden und auf 1. des Monats einstellen $timestamp = get_anzeigemonat_timestamp(); $showYear = date('Y', $timestamp); $showMonth = date('m', $timestamp); // H3 Title $html_title = sprintf("%04d / %02d", $showYear, $showMonth); // Prev & Next / Monat Link $nextMonth = date('Y-m', mktime(0, 0, 0, $showMonth+1, 1, $showYear)); $prevMonth = date('Y-m', mktime(0, 0, 0, $showMonth-1, 1, $showYear)); // <tr>...</tr> Zeilen für die Kalenderausgabe konstruieren $weeks = erzeuge_kalenderwochen($timestamp, $mysqli, $teile25);

                    $timestamp hätte ich gern umbenannt, weiß aber nicht wo Du die Variable sonst noch brauchst.

                    Die Funktionen sind selbsterklären benannt und zusätzlich ist der Aufruf kommentiert.

                    $showMonth und $showYear sind im Prinzip temporäre Werte. Würde dieser Code in einer Klasse stehen, wären es lokale Variablen einer allgemeinen Initialisierungsfunktion.

                    $mysqli und $teile25 sind Variablen, die Du vorher setzt (Dein Code setzt sie ebenfalls voraus) und die in erzeuge_kalenderwochen benötigt werden. Daher reiche ich sie durch.

                    Die Implementierung von get_anzeigemonat_timestamp und erzeuge_kalenderwochen könnte nun ganz woanders stehen. Solche Funktionen SOLLTE man gemäß PSR-1 aus einer anderen Datei includen (die dann NUR Funktionen enthält). Oder Du sammelst sie am Ende deiner PHP Datei (was dem Basic Coding Standard widerspricht)


                    Nun zu den Funktionen, Stück für Stück.

                    Beachte den PHPDocs Kommentar vor den Funktionen. Das ist eine Standardschreibweise für Funktions-Selbstbeschreibungen, die von guten IDEs verstanden wird und Dir Codierungshilfe (a.k.a. Intellisense) geben kann.

                    /** * Ermittle den Timestamp für den 1. des anzuzeigenden Monats. Der Monat wird * im Query-Parameter ym übergeben. Fehlt der oder hat falsches Format, wird * der aktuelle Monat verwendet. * * @return int Unix-Timestamp des ersten Tages im Anzeigemonat */ function get_anzeigemonat_timestamp() { $ym = filter_input(INPUT_GET, "ym", FILTER_VALIDATE_REGEXP, [ 'options' => [ 'regexp'=>'/\d{4}-\d{1,2}/' ] ]); // Parameter fehlt oder die Validierung ist gescheitert if (is_null($ym) || $ym === false) { $ym = date('Y-m'); } // $ym ist jetzt immer im Format yyyy-mm. // Entweder durch Regex bestätigt, oder von date geliefert. $parts = explode("-", $ym); // Monat Jahr return mktime(0,0,0,intval($parts[1]),1,intval($parts[0])); }

                    Bei Eingaben aus $_GET sollte man immer vorsichtig sein, daher filter_input als Schirm davor, zusammen mit einer Regex als Überprüfung auf das richtige Format. Die Funktion sollte zusammen mit den PHPDocs selbsterklärend sein!


                    /** * Generiert Table Rows mit Kalendereinträgen. Daten werden automatisch beschafft. * * @return array Ein Array mit fertigen HTML Fragmenten pro Row */ function erzeuge_kalenderwochen($firstOfMonth, $mysqli, $teile25) { $thisMonth = date("Y-m", $firstOfMonth); $showYear = intval(date('Y', $firstOfMonth)); $showMonth = intval(date('m', $firstOfMonth)); // date('w') liefert 0:So 1:Mo 2:Di usw... // Finde Wochentag des Monatsersten, +6, %7, ergibt Wochentag des Tages zuvor. // Diese Tagesnummer ist die Anzahl von leeren Feldern vor dem 1. des Monats // $day wird die auszugebende Tagesnummer sein, d.h. um N Felder leerzulassen, // wird $day auf 1-N initialisiert. $weekDayBeforeFirst = (6 + intval(date('w', $firstOfMonth))) % 7; $day = 1 - $weekDayBeforeFirst; // Kalender zusammenbauen // Tagesdatum und YYYY-MM Form des aktuellen Monats ermitteln $today = date('Y-m-d', time()); // Anzahl der Tage im Anzeigemonat ermitteln $day_count = intval(date('t', $firstOfMonth)); // $weeks: Ein Eintrag pro Anzeigewoche $weeks = []; while ($day <= $day_count) { // Negative Werte oder zu große Werte für $day sind kein Problem, die werden // von mktime in den passenden Monat verschoben. $weekNr = date('W', mktime(0,0,0,$showMonth, $day, $showYear)); $weekParts = [ "<td class='kw'>$weekNr</td>" ]; // Die 7 Tage einer Woche aufbereiten for ($i=0; $i<7; $i++) { $weekParts[] = formatiere_tag($thisMonth, $day_count, $day, $today, $mysqli, $teile25); $day++; } $weeks[] = "<tr>".implode('', $weekParts)."</tr>"; } return $weeks; }

                    $showMonth und $showYear berechne ich hier erneut. Das verschwendet ein paar Taktzyklen, aber um das zu sparen hätte ich eine Klasse erzeugen müssen und die Variablen dort als private Werte speichern. Vielleicht später. Jedenfalls wollte ich keine Hilfswerte als Parameter durchschleusen.

                    Die Variable $day enthält den aufbereiteten Tag im Monat. Die Logik zu Beginn setzt sie so, dass sie immer auf dem Montag steht, der vor dem Monatsersten liegt, bzw. auf dem Monatsersten, wenn der ein Montag ist. Wenn z.B. der Monatserste ein Donnerstag ist, beginnt $day mit -2.

                    Vor der Hauptschleife werden noch ein paar erforderliche Werte vorbereitet, und dann geht's los. Laufe so lange, bis $day größer ist als der letzte Tag im Monat.

                    Der Code ist analog zum Kalender strukturiert, d.h. er bereitet immer eine ganze Woche auf. Solange $day außerhalb des Monats liegt, werden Leerzellen geschrieben. Das erzeugt die Füllung vor der ersten und nach der letzten Woche.

                    Zu Beginn einer Woche wird die KW ermittelt und an den Anfang der Row gesetzt. Danach folgt die Aufbereitung der 7 Tage. Wie ein Tag formatiert wird, entscheidet allein die aufgerufene Funktion. Bei Verwendung von Klassen könnte man auf ein paar Parameter verzichten...

                    Bisher hatten wir nur Formatierung und Delegation. Nun geht's tiefer.


                    /** * Formatiere das HTML Fragment für einen Kalendertag * * @param \mysqli $mysqli mysqli-Objekt für Datenbeschaffung * @param string $date Anfragedatum, yyyy-mm-tt * @param bool $aktuellerTag True um Tag als aktuelles Datum zu formatieren * @return string */ function formatiere_tag($thisMonth, $day_count, $day, $today, $mysqli, $teile25) { if ($day < 1 || $day > $day_count) { return "<td class='emptyDay'></td>"; } $date = $thisMonth . sprintf('-%02d', $day); // Daten beschaffen $datumTermine = kalender_termine($mysqli, $date, $teile25, 3); $anzTermineGesamt = count_alle_kalender_termine($mysqli, $date, $teile25); $dayClasses = ($date == $today ? "today " : ""); $dayHtml = "<td class='$dayClasses calendarDay'>" . formatiere_tag_header($date, $day, $anzTermineGesamt); foreach ($datumTermine as $termin) { $dayHtml .= formatiere_termin($termin); } return $dayHtml . '</td>'; }

                    Diese Funktion steuert die Aufbereitung eines Tages. Um Kalenderwochen und sonstigen Firlefanz kümmert sie sich nicht. Sie holt die Daten aus der DB, und bereitet sie als Tabellenzelle auf.

                    Ich verwende hier an einigen Stellen String Parsing, also das Ersetzen von Variablen in Strings. Man braucht dann nicht so viele Verkettungsschritte.

                    Im nächsten Posting mache ich weiter.

                    Rolf

                    -- sumpsi - posui - clusi
                  3. Hallo Barksalot,

                    weiter geht's. Als nächstes kommt die Datenbeschaffung. Die habe ich fast unverändert gelassen. Die Frage nach der Güte deines SQL habe ich nicht betrachtet. Es fehlte ein $stmt->close(), um das verarbeitete Resultset freizugeben und Speicher zu sparen.

                    Was auf jeden Fall noch passieren müsste, ist eine Trennung von Prepare und Execute. Ein prepared statement nur einmal auszuführen lohnt nicht. Das wird aber nur durch Klassen-Techniken sinnvoll (die binds müssten an Properties der Klasse erfolgen, damit die gebundenen Variablen ihren Scope behalten, und die RÜckgabe wäre vielleicht besser mit get_result und fetch_assoc zu handlen). Darum lasse ich das erstmal so stehen.

                    Die Story mit dem LIMIT ist so eine Sache. Du rufst das Statement zweimal auf. Einmal mit Limit 3, einmal ohne Limit. Nur um festzustellen wieviele Termine es am Tag gibt. Das ist ineffektiv. Eigentlich müsstest Du für diesen Zählvorgang ein eigenes Statement preparen und ausführe, das nur COUNT(*) zurückliefert. Und bei der Gelegenheit schauen, ob Du alle Joins für den Zählvorgang brauchst. Das Statement, das Du jetzt verwendest, kann dann konstant mit Limit 3 laufen.

                    Ohne dieses Statement bleibt zum Zählen nur der Aufruf ohne Limit, den habe ich in der count_alle_kalender_termine gekapselt. Aber eigentlich gehört da ein anderes Statement hin.

                    /** * Ermittle alle Kalendereinträge zu einem Datum und einer Liste von Empfängern * * @param \mysqli $mysqli Eine MySQLI Connection * @param string $datum Das Abfragedatum im Format yyyy-mm-dd * @param string[] $teile25 Komma-getrennte Liste der möglichen Kalenderarten (k_art) * * @return Array */ function kalender_termine($mysqli, $datum, $teile25, $limit = false) { $values = $teile25; $empfaengerListe = "'".implode("','", $values)."'"; $select = "SELECT kt_id, kt_kalenderID, kt_datum, test, k_code, k_art, k_jobNr, k_bezeichnung, k_auto, k_farbe, k_datum_von, k_ganztags, k_von, k_bis, f_bezeichnung, f_kennzeichen, ka_farbe, kf_farbe, kf_color FROM kalender_termine LEFT JOIN kalender ON kalender.k_code = kalender_termine.kt_kalenderID LEFT JOIN fuhrpark ON fuhrpark.f_id = kalender.k_auto LEFT JOIN kalender_arten ON kalender_arten.ka_code = kalender.k_art LEFT JOIN kalender_terminfarbe ON kalender_terminfarbe.kf_farbe = kalender_arten.ka_farbe WHERE kt_datum=? AND k_art IN (" . $empfaengerListe . ") ORDER by test ASC"; if ($limit != false) { $stmt = $mysqli->prepare($select . " LIMIT ?" ); $stmt->bind_param("ss", $datum, $limit); } else { $stmt = $mysqli->prepare($select ); $stmt->bind_param("s", $datum); } $stmt->execute(); $stmt->bind_result($kt_id, $kt_kalenderID, $kt_datum, $test, $k_code, $k_art, $k_jobNr, $k_bezeichnung, $k_auto, $k_farbe, $k_datum_von, $k_ganztags, $k_von, $k_bis, $f_bezeichnung, $f_kennzeichen, $ka_farbe, $kf_farbe, $kf_color); $Kalender_Termine[] = ARRAY(); if ($stmt->num_rows() > 0) { while ($stmt->fetch()) { $Kalender_Termine[] = array( 'kt_id' => $kt_id, 'kt_kalenderID' => $kt_kalenderID, 'kt_datum' => $kt_datum, 'test' => $test, 'k_code' => $k_code, 'k_art' => $k_art, 'k_jobNr' => $k_jobNr, 'k_bezeichnung' => $k_bezeichnung, 'k_auto' => $k_auto, 'k_farbe' => $k_farbe, 'k_datum_von' => $k_datum_von, 'k_ganztags' => $k_ganztags, 'k_von' => $k_von, 'k_bis' => $k_bis, 'f_bezeichnung' => $f_bezeichnung, 'f_kennzeichen' => $f_kennzeichen, 'ka_farbe' => $ka_farbe, 'kf_farbe' => $kf_farbe, 'kf_color' => $kf_color ); } } $stmt->close(); return $Kalender_Termine; } /** * Zähle die Kalendereinträge zu einem Datum und einer Liste von Kalenderarten * * @param \mysqli $mysqli Eine MySQLI Connection * @param string $datum Das Abfragedatum im Format yyyy-mm-dd * @param string[] $teile25 Komma-getrennte Liste der möglichen Kalenderarten (k_art) * * @return int Anzahl Einträge */ function Count_Alle_Kalender_Termine($mysqli, $datum, $teile25) { // Bis eine bessere Abfrage bereitstelt, auf die alte Technik der unlimitierten // Abfrage zurückfallen $termine = Kalender_Termine($mysqli, $datum, $teile25); return count($termine); }

                    Ansonsten brauchst Du in formatiere_tag noch die Funktionen zum Aufbereiten des Tages-Headers und der Termine selbst:

                    function formatiere_tag_header($date, $day, $anzTermine) { $dailyLink = '<a href="tageskalender.php?date='.$date .'">'; if ($anzTermine > 3) { $header .= "$day - {$dailyLink}Alle $anzTermine anzeigen</a>"; } else { $header .= $dailyLink.$day."</a>"; } return "<div class='dayHeader'>$header</div>"; }

                    und

                    function formatiere_termin($termin) { // Formatiere_Datenblatt_Link wählt k/f-Bezeichnung automatisch aus. // Formatiere_JobNr_und_Zeit gibt nur ein <span> aus wenn die JobNr // gefüllt oder ein Zeitraum angefordert ist. Sonst kommt '' zurück. if ($termin["kt_datum"] == $termin["k_datum_von"]) { if ($termin["k_ganztags"] == "0") { $terminHoehe = ''; $terminInhalt = formatiere_datenblatt_link($termin) . formatiere_jobNr_und_zeit($termin, true); } else { $terminHoehe = 'min-height: 37px;'; $terminInhalt = formatiere_datenblatt_link($termin) . formatiere_jobNr_und_zeit($termin, false); } } else { $terminHoehe = 'height: 37px;'; // Wochentag des Termindatums prüfen $datum = getdate(strtotime($termin["kt_datum"])); if ($datum['wday'] == 1) // Montag { $terminInhalt = formatiere_datenblatt_link($termin) . formatiere_jobNr_und_zeit($termin, false); } else { $terminInhalt = ''; } } return '<div style="background:'.$termin["ka_farbe"].'; margin-bottom:5px; padding-left:8px;'.$terminHoehe.'">' . $terminInhalt . '</div>'; }

                    Hier müsstest Du dein HTML besser aufräumen, dann könnten Fallunterscheidungen möglicherweise entfallen. Die Zweige werden eigentlich nur gebildet um die unterschiedlichen Höhen zu setzen, und wegen dieser Montagslogik, die ich nicht verstanden habe.

                    Die Formatierer sehen so aus:

                    unction Formatiere_Datenblatt_Link($termin) { $text = ($termin["k_auto"] == "") ? $termin["k_bezeichnung"] : $termin["f_bezeichnung"]; $url = '/kalender-datenblatt.php?code='.$termin["k_code"]; $farbe = 'color:'.$termin["kf_color"]; return '<a href="'.$url.'" style="'.$farbe.'">'.shortText($text, 15).'</a>'; //return '<span style="color:'.$termin["kf_color"].'"><a href="'.$url.'" style="'.$farbe.'">'.shortText($text, 15).'</a></span>'; } /** * Formatiere JobNr und Zeitraum eines Termineintrags. * * Ist die JobNr leer und kein Zeitraum gefordert, wird ein Leerstring zurückgegeben. * * Ist die JobNr bestückt und ein Zeitraum gefordert, werden beide durch " - " getrennt. * * Das Ergebnis wird in einen span mit style-Attribut eingehüllt, das die Farbe gemäß * Datenbank setzt. TODO: Unnötige Styles ins CSS verlegen! * * @param array $termin Terminzeile aus dem SQL Ergebnis * @param bool $mitZeitraum true übergeben um auch den Zeitraum auszugeben * * @return string HTML-Text mit span Element, das die Werte enthält */ function Formatiere_JobNr_und_Zeit($termin, $mitZeitraum) { $parts = []; if ($termin['k_jobNr'] != '') { $parts[] = $termin['k_jobNr']; } if ($mitZeitraum) { $parts[] = $termin['k_von'].' bis '.$termin['k_bis'].' Uhr'; } if (count($parts) == 0) { return ''; } return '<span style="color:'.$termin["kf_color"].'; font-size:10px; display: block; padding-bottom: 2px;">' . implode(' - ', $parts) . '</span>'; }

                    Tja. Das war's. Hoffentlich habe ich keine blöden Fehler eingebaut. Möglicherweise passen ein paar Namen mit Groß- und Kleinschrift nicht, da habe ich hin- und her geändert.

                    Bei mir in NetBeans sind es nun 50 Zeilen mehr als Dein Code, aber es sind viel mehr Kommentare drin. Ohne die würde es ein gutes Stück kürzer.

                    Rolf

                    -- sumpsi - posui - clusi

                    Folgende Nachrichten verweisen auf diesen Beitrag:

                    1. Hi,

                      Die Story mit dem LIMIT ist so eine Sache. Du rufst das Statement zweimal auf. Einmal mit Limit 3, einmal ohne Limit. Nur um festzustellen wieviele Termine es am Tag gibt. Das ist ineffektiv.

                      SQL_CALC_FOUND_ROWS und FOUND_ROWS() könnten das Problem lösen (wenn's mysql ist).

                      cu,
                      Andreas a/k/a MudGuard

                      1. Hallo Andreas,

                        nach mysql sieht es aus ($mysqli-Variable ist ein verräterischer Hinweis 😉).

                        Muss man dann mit multi_query arbeiten? Oder kann man das in zwei getrennten Query-Aufrufen tun?

                        Andererseits könnte man auch mal schauen, wieviele Termine TYPISCHERWEISE pro Tag vorhanden sind. Wenn es im Normalfall weniger als drei oder vier sind, sollte man vielleicht einfach immer alle abrufen und das Result im PHP auf 3 limitieren. Das ist jetzt eine Frage des Datenbestandes, das kann nur Bernd wissen.

                        Rolf

                        -- sumpsi - posui - clusi
                        1. Tach!

                          Muss man dann mit multi_query arbeiten? Oder kann man das in zwei getrennten Query-Aufrufen tun?

                          Solange man die Verbindung nicht schließt, ist das auch in mehreren Abfragen möglich. Multiquery bringt aber keine großen Vorteile in dem Fall, weil zwar das mehrfache Query wegfällt, aber das Jonglieren mit den Resultsets hinzukommt.

                          dedlfix.

                      2. SQL_CALC_FOUND_ROWS und FOUND_ROWS() könnten das Problem lösen (wenn's mysql ist).

                        Also eine Abfrage (ohne Limit) reicht. Denn die liefert neben denselben selbst auch die Anzahl der Datensätze. Danach in der Schleife halt die Ausgabe auf 3 (oder was auch immer konfiguriert ist) begrenzen.

                        # $limit = 3 $counter = 0; $retHash['AnzahlTermine'] = $stmt -> num_rows; while ( $stmt -> fetch() && counter < $limit ) { $counter ++; retHash['Kalender_Termine'][] = array( #... ) } return $retHash

                        Die Menge der Daten, die "notlos" abgefragt, sortiert und ausgeliefert werden wird sich bei einem Kalender voraussichtlich in engen Grenzen (oft unter dem Vorschau-Limit) halten, so dass die Gesamtperformance darunter vorhersehbar weniger leidet als unter einer zweiten Abfrage.

                    2. Hallo Rolf,

                      erst einmal vielen vielen vielen Dank für deine Hilfe und dem Code. Wahnsinn, ich weiß gar nicht was ich sagen soll. Vielen Dank auch für das Kommentieren. Ist es üblich dass man so ausführlich einen Code dokumentiert oder hast du dieses jetzt nur für dieses Beispiel gemacht?

                      Ich muss zugeben ich bekomme es irgendwie nicht wirklich zum laufen. Hab mir den Code den ganzen Nachmittag immer wieder angesehen und getestet. Egal was ich mache, es kommen folgende Meldungen

                      Notice: Undefined variable: header
                      Notice: Undefined index: kt_datum
                      Notice: Undefined index: k_datum_von
                      Notice: Undefined index: k_ganztags
                      Notice: Undefined index: k_auto
                      Notice: Undefined index: k_bezeichnung
                      Notice: Undefined index: k_code
                      Notice: Undefined index: kf_color
                      Notice: Undefined index: k_jobNr
                      Notice: Undefined index: ka_farbe

                      Weißt du zufällig was ich noch falsch mache? Es werden auch keine Termine ausgegeben. Die Wochennummern stimmen auch am 31.12.2018.

                      Dennoch ich bin noch immer Sprachlos, so hat mir bis jetzt noch niemand geholfen.

                      Bis bald!
                      Bernd

                      1. Notice: Undefined variable: header Notice: Undefined index: kt_datum Notice: Undefined index: k_datum_von Notice: Undefined index: k_ganztags Notice: Undefined index: k_auto Notice: Undefined index: k_bezeichnung Notice: Undefined index: k_code Notice: Undefined index: kf_color Notice: Undefined index: k_jobNr Notice: Undefined index: ka_farbe

                        Was steht denn in den Zeilen, welche diese Notizen werfen?

                        1. Hallo Regina,

                          Notice: Undefined variable: header

                          $header .= $dailyLink.$day."</a>";

                          Notice: Undefined index: kt_datum

                          $termin["kt_datum"] == $termin["k_datum_von"]

                          Notice: Undefined index: k_datum_von

                          $termin["kt_datum"] == $termin["k_datum_von"]

                          Notice: Undefined index: k_ganztags

                          $termin["k_ganztags"] == "0""

                          Notice: Undefined index: k_auto

                          $termin["k_auto"] == ""

                          Notice: Undefined index: k_bezeichnung

                          $termin["k_bezeichnung"]

                          Notice: Undefined index: k_code

                          $termin["k_code"]

                          Notice: Undefined index: kf_color

                          $farbe = 'color:'.$termin["kf_color"];

                          Notice: Undefined index: k_jobNr

                          $termin['k_jobNr']

                          Irgendwie stimmt etwas mit $termin nicht.

                          Bis bald!
                          Bernd

                          1. Irgendwie stimmt etwas mit $termin nicht.

                            wenn Du das schon weisst, dann zeige alle Zeilen VOLLSTÄNDIG, in denen

                            $termin=

                            steht. Auch mit Leerzeichen zwischen dem "n" und dem "=".

                            Nicht schlecht wäre auch, an passender Stelle (also vor den Notizen) ein

                            echo "<pre>"; print_r( $termin ), exit;

                            auszuführen.

                            1. Hallo Regina,

                              /** * Formatiere das HTML Fragment für einen Kalendertag * * @param \mysqli $mysqli mysqli-Objekt für Datenbeschaffung * @param string $date Anfragedatum, yyyy-mm-tt * @param bool $aktuellerTag True um Tag als aktuelles Datum zu formatieren * @return string */ function formatiere_tag($thisMonth, $day_count, $day, $today, $mysqli, $teile25) { if ($day < 1 || $day > $day_count) { return "<td class='emptyDay'></td>"; } $date = $thisMonth . sprintf('-%02d', $day); // Daten beschaffen $datumTermine = kalender_termine($mysqli, $date, $teile25, 3); $anzTermineGesamt = count_alle_kalender_termine($mysqli, $date, $teile25); $dayClasses = ($date == $today ? "today " : ""); $dayHtml = "<td class='$dayClasses calendarDay'>" . formatiere_tag_header($date, $day, $anzTermineGesamt); foreach ($datumTermine as $termin) { $dayHtml .= formatiere_termin($termin); } return $dayHtml . '</td>'; } function Count_Alle_Kalender_Termine($mysqli, $datum, $teile25) { // Bis eine bessere Abfrage bereitstelt, auf die alte Technik der unlimitierten // Abfrage zurückfallen $termine = Kalender_Termine($mysqli, $datum, $teile25); return count($termine); } function formatiere_termin($termin) { // Formatiere_Datenblatt_Link wählt k/f-Bezeichnung automatisch aus. // Formatiere_JobNr_und_Zeit gibt nur ein <span> aus wenn die JobNr // gefüllt oder ein Zeitraum angefordert ist. Sonst kommt '' zurück. if ($termin["kt_datum"] == $termin["k_datum_von"]) { if ($termin["k_ganztags"] == "0") { $terminHoehe = ''; $terminInhalt = formatiere_datenblatt_link($termin) . formatiere_jobNr_und_zeit($termin, true); } else { $terminHoehe = 'min-height: 37px;'; $terminInhalt = formatiere_datenblatt_link($termin) . formatiere_jobNr_und_zeit($termin, false); } } else { $terminHoehe = 'height: 37px;'; // Wochentag des Termindatums prüfen $datum = getdate(strtotime($termin["kt_datum"])); if ($datum['wday'] == 1) // Montag { $terminInhalt = formatiere_datenblatt_link($termin) . formatiere_jobNr_und_zeit($termin, false); } else { $terminInhalt = ''; } } return '<div style="background:'.$termin["ka_farbe"].'; margin-bottom:5px; padding-left:8px;'.$terminHoehe.'">' . $terminInhalt . '</div>'; } function Formatiere_Datenblatt_Link($termin) { $text = ($termin["k_auto"] == "") ? $termin["k_bezeichnung"] : $termin["f_bezeichnung"]; $url = '/kalender-datenblatt.php?code='.$termin["k_code"]; $farbe = 'color:'.$termin["kf_color"]; return '<a href="'.$url.'" style="'.$farbe.'">'.shortText($text, 15).'</a>'; //return '<span style="color:'.$termin["kf_color"].'"><a href="'.$url.'" style="'.$farbe.'">'.shortText($text, 15).'</a></span>'; } /** * Formatiere JobNr und Zeitraum eines Termineintrags. * * Ist die JobNr leer und kein Zeitraum gefordert, wird ein Leerstring zurückgegeben. * * Ist die JobNr bestückt und ein Zeitraum gefordert, werden beide durch " - " getrennt. * * Das Ergebnis wird in einen span mit style-Attribut eingehüllt, das die Farbe gemäß * Datenbank setzt. TODO: Unnötige Styles ins CSS verlegen! * * @param array $termin Terminzeile aus dem SQL Ergebnis * @param bool $mitZeitraum true übergeben um auch den Zeitraum auszugeben * * @return string HTML-Text mit span Element, das die Werte enthält */ function Formatiere_JobNr_und_Zeit($termin, $mitZeitraum) { $parts = []; if ($termin['k_jobNr'] != '') { $parts[] = $termin['k_jobNr']; } if ($mitZeitraum) { $parts[] = $termin['k_von'].' bis '.$termin['k_bis'].' Uhr'; } if (count($parts) == 0) { return ''; } return '<span style="color:'.$termin["kf_color"].'; font-size:10px; display: block; padding-bottom: 2px;">' . implode(' - ', $parts) . '</span>'; }

                              Bis bald!
                              Bernd

                      2. Hallo Barksalot,

                        ja, Code kommentiert man so. Vielleicht nicht GANZ so viel, aber jede nichttriviale fachliche Überlegung oder Entscheidung schreibt man auf (z.B. diese Sache mit $day = 1 - $weekDayBeforeFirst;. Schau Dir alten Code von Dir an - weißt Du an jeder Stelle, was Du Dir dabei gedacht hast? Würdest Du Dir nicht wünschen, dass da eine Notiz bei wäre? Kommentare sind Post - von Dir an Dein um 6 Monate älteres Selbst, das dafür zutiefst dankbar sein wird.

                        Noch wichtiger als Kommentare sind sinnvoll benannte Variablen und Funktionen. Wenn die Namensgebung gut ist, spricht der Code im Wesentlichen für sich selbst (ich hoffe, ich habe das halbwegs gut geschafft). Und PHPDocs sind die ideale Hilfe, wenn man eine IDE hat, die das unterstützt. Ich arbeite seit 20 Jahren mit dem Intellisense von Visual Studio, und wenn man auf einem Funktionsnamen nur Strg+Space drücken muss und dann eine Beschreibung plus Parameter angezeigt bekommt, müllt man seinen Kopf mit viel weniger Kram zu. Alle Library-Funktionen von .net bringen die Intellisense-Doku mit. Und dann möchte man das für die eigenen auch haben. Der Aufwand lohnt sich.

                        Die Sache mit dem $header ist eine punktuelle Ungenauigkeit von mir. Die Lösung zu finden sei als leichte Übung dem Studenten überlassen.

                        Die Meldung über die fehlenden Indizes verstehe ich zur Zeit auch nicht. Die Meldung kommt, wenn man auf einen Array-Eintrag zugreifen will, der nicht existiert. Dass also $termin ein Array ist, aber keinen Eintrag unter dem Namen 'kt_datum' enthält. Vom Code her sehe ich nicht, wie das passieren könnte. Ist es möglich, dass Du was falsch kopiert hast?

                        Mit Draufgucken kommt man nicht weiter. Man muss sich von der Stelle, wo der Fehler gemeldet wird, rückwärts hangeln. Immer mit var_dump überprüfen, ob die Variablen die erwarteten Werte enthalten.

                        Wichtige Kontrollpunkte wären:

                        1. zu Begin von formatiere_termin -> kommt da ein sinnvoller Termin an
                        2. am Ende von kalender_termine -> liefert die Abfragefunktion ein korrektes Termine-Array
                        3. In der Leseschleife von kalender_termine -> stehen in den gebundenen Variablen sinnvolle Werte (DAS würde ich jetzt erstmal als gegeben voraussetzen).

                        Rolf

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

                          Wichtige Kontrollpunkte wären: 1. zu Begin von formatiere_termin -> kommt da ein sinnvoller Termin an

                          wenn ich

                          var_dump($termin);

                          ausgeben lasse, erhalte ich folgendes

                          Array ( [0] => Array ( ) ) Array ( [0] => Array ( ) )

                          das heißt $termin ist leer? Mir vor meinst du doch so?

                          var_dump($termin); function formatiere_termin($termin) {......}

                          Die Sache mit dem $header ist eine punktuelle Ungenauigkeit von mir. Die Lösung zu finden sei als leichte Übung dem Studenten überlassen.

                          Dieses Problem habe ich so geöst

                          function formatiere_tag_header($date, $day, $anzTermine) { $header = ""; $dailyLink = '<a href="tageskalender.php?date='.$date .'">'; if ($anzTermine > 3) { $header .= "$day - {$dailyLink}Alle $anzTermine anzeigen</a>"; } else { $header .= $dailyLink.$day."</a>"; } return "<div class='dayHeader'>$header</div>"; }

                          Bis bald!
                          Bernd

                          1. Hallo Barksalot,

                            nee, das meinte ich nicht mit "vor formatiere_termin". So wie Du es jetzt gemacht hast ergibt es keinen Sinn. Du möchtest doch wissen, welchen Wert $termin beim Einstieg in die Funktion hat. Aaalso?1

                            Das $header-Problem hätte man auch so lösen können. Du hast richtig erkannt dass $header nicht initialisiert war. Aber wenn man = statt .= schreibt, braucht man vorher nicht zu initialisieren 😀

                            function formatiere_tag_header($date, $day, $anzTermine) { $dailyLink = '<a href="tageskalender.php?date='.$date .'">'; if ($anzTermine > 3) { $header = "$day - {$dailyLink}Alle $anzTermine anzeigen</a>"; } else { $header = $dailyLink.$day."</a>"; } return "<div class='dayHeader'>$header</div>"; }

                            Rolf

                            1. Sorry wenn ich Dich jetzt raten lasse. Aber ich will einen Lerneffekt bei Dir auslösen 😀

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

                              dann kann es ja nur so gemeint sein?

                              function formatiere_termin($termin) { var_dump($termin); }

                              Und da erhalte ich folgende Ausgabe

                              array(0) { }

                              Bis bald!
                              Bernd

                              1. function formatiere_termin($termin) { var_dump($termin); }

                                Und da erhalte ich folgende Ausgabe

                                array(0) { }

                                Fragen hierzu:

                                • Ist das ein Tag ohne Termin?
                                • Wir müssten jetzt mal Dein Hauptprogramm (ohne Funktionen) sehen.
                                1. Hallo Regina,

                                  in diesem Monat gibt es jeden Tag einen bzw. mehrere Termine.

                                  Bis bald!
                                  Bernd

                                  1. Ok. Das War Teil 1 der Fragen.

                                    Ich hab aber nicht grundlos nach dem Hauptprogramm gefragt. Es muss nämlich untersucht werden, warum $termin ein leeres Array enthält.

                                    1. Hallo Regina,

                                      was meinst du mit Hauptprogramm? Ich denke es hängt irgendwie damit zusammen? Denn da wird $termin gefällt?

                                      function formatiere_tag($thisMonth, $day_count, $day, $today, $mysqli, $teile25) { if ($day < 1 || $day > $day_count) { return "<td class='emptyDay'></td>"; } $date = $thisMonth . sprintf('-%02d', $day); var_dump($date); // Daten beschaffen $datumTermine = kalender_termine($mysqli, $date, $teile25, 3); $anzTermineGesamt = count_alle_kalender_termine($mysqli, $date, $teile25); var_dump($datumTermine); $dayClasses = ($date == $today ? "today " : ""); $dayHtml = "<td class='$dayClasses calendarDay'>" . formatiere_tag_header($date, $day, $anzTermineGesamt); foreach ($datumTermine as $termin) { $dayHtml .= formatiere_termin($termin); } return $dayHtml . '</td>'; }

                                      Bis bald!
                                      Bernd

                                      1. // Daten beschaffen $datumTermine = kalender_termine($mysqli, $date, $teile25, 3);

                                        Füge da mal temporär diese Zeile ein:

                                        // Daten beschaffen $datumTermine = kalender_termine($mysqli, $date, $teile25, 3); echo "<pre>"; print_r( $datumTermine ); exit;

                                        und gib uns die Ausgaben sowie die Funktion kalender_termine()

                                        1. Hallo Regina,

                                          da erhalte ich folgende Ausgabe

                                          string(10) "2018-09-01" Notice: Undefined variable: datumTermine

                                          Bis bald!
                                          Bernd

                                          1. da erhalte ich folgende Ausgabe

                                            string(10) "2018-09-01" Notice: Undefined variable: datumTermine

                                            Das kann eigentlich nicht sein. Doch steigen wir mal tiefer ein. Ersetze die Funktion formatiere_tag vollständig durch dieses:

                                            function formatiere_tag($thisMonth, $day_count, $day, $today, $mysqli, $teile25) { if ($day < 1 || $day > $day_count) { return "<td class='emptyDay'></td>"; } $date = $thisMonth . sprintf('-%02d', $day); // Daten beschaffen $datumTermine = kalender_termine($mysqli, $date, $teile25, 3); ##### Debugging ##################################################### echo "<pre>Testausgabe:\n\n"; echo '$datumTermine: '; print_r( $datumTermine ); echo "\n" . '$date: '; print_r( $date ); echo "\n" . '$teile26: '; print_r( $teile25 ); exit; ##################################################################### $anzTermineGesamt = count_alle_kalender_termine($mysqli, $date, $teile25); var_dump($datumTermine); $dayClasses = ($date == $today ? "today " : ""); $dayHtml = "<td class='$dayClasses calendarDay'>" . formatiere_tag_header($date, $day, $anzTermineGesamt); foreach ($datumTermine as $termin) { $dayHtml .= formatiere_termin($termin); } return $dayHtml . '</td>'; }
                                            • Ich brauche zusätzlich zu den Ausgaben die vollständige Funktion kalender_termine().
                                            1. Hallo Regina,

                                              dein geändertes Script ergibt folgende Ausgabe

                                              Testausgabe: $datumTermine: Array ( [0] => Array ( ) ) $date: 2018-09-01 $teile26: Array ( [0] => 385c1689fa43c389c23c296b1b35f5cd [1] => 45c1d715636b9a9e2497d67b8a79b760 [2] => 58a32d92f11e310890adc077d0c52d2a [3] => b8b44273be5ef2df5ce61d9fcb6aa672 [4] => 733f9760ca7330cc78ecda3353393dd9 [5] => 7e9538479e00ad135a34d6e7a5047706 [6] => 1f7a6a2f19572cd8ece913eaae15f997 )

                                              Ich brauche zusätzlich zu den Ausgaben die vollständige Funktion kalender_termine().

                                              Das ist diese:

                                              function kalender_termine($mysqli, $datum, $teile25, $limit = false) { $values = $teile25; $empfaengerListe = "'".implode("','", $values)."'"; $select = "SELECT kt_id, kt_kalenderID, kt_datum, test, k_code, k_art, k_jobNr, k_bezeichnung, k_auto, k_farbe, k_datum_von, k_ganztags, k_von, k_bis, f_bezeichnung, f_kennzeichen, ka_farbe, kf_farbe, kf_color FROM kalender_termine LEFT JOIN kalender ON kalender.k_code = kalender_termine.kt_kalenderID LEFT JOIN fuhrpark ON fuhrpark.f_id = kalender.k_auto LEFT JOIN kalender_arten ON kalender_arten.ka_code = kalender.k_art LEFT JOIN kalender_terminfarbe ON kalender_terminfarbe.kf_farbe = kalender_arten.ka_farbe WHERE kt_datum=? AND k_art IN (" . $empfaengerListe . ") ORDER by test ASC"; if ($limit != false) { $stmt = $mysqli->prepare($select . " LIMIT ?" ); $stmt->bind_param("ss", $datum, $limit); } else { $stmt = $mysqli->prepare($select ); $stmt->bind_param("s", $datum); } $stmt->execute(); $stmt->bind_result($kt_id, $kt_kalenderID, $kt_datum, $test, $k_code, $k_art, $k_jobNr, $k_bezeichnung, $k_auto, $k_farbe, $k_datum_von, $k_ganztags, $k_von, $k_bis, $f_bezeichnung, $f_kennzeichen, $ka_farbe, $kf_farbe, $kf_color); $Kalender_Termine[] = ARRAY(); if ($stmt->num_rows() > 0) { while ($stmt->fetch()) { $Kalender_Termine[] = array( 'kt_id' => $kt_id, 'kt_kalenderID' => $kt_kalenderID, 'kt_datum' => $kt_datum, 'test' => $test, 'k_code' => $k_code, 'k_art' => $k_art, 'k_jobNr' => $k_jobNr, 'k_bezeichnung' => $k_bezeichnung, 'k_auto' => $k_auto, 'k_farbe' => $k_farbe, 'k_datum_von' => $k_datum_von, 'k_ganztags' => $k_ganztags, 'k_von' => $k_von, 'k_bis' => $k_bis, 'f_bezeichnung' => $f_bezeichnung, 'f_kennzeichen' => $f_kennzeichen, 'ka_farbe' => $ka_farbe, 'kf_farbe' => $kf_farbe, 'kf_color' => $kf_color ); } } $stmt->close(); return $Kalender_Termine; }

                                              Bis bald!
                                              Bernd

                                              1. Vermutlich hast Du einen SQL-Error, den Du nicht abgefangen hast. Lass Dir das mal anzeigen und ändere zu diesem Zweck die Funktion wie folgt:

                                                function kalender_termine($mysqli, $datum, $teile25, $limit = false) { $values = $teile25; $empfaengerListe = "'".implode("','", $values)."'"; $select = "SELECT kt_id, kt_kalenderID, kt_datum, test, k_code, k_art, k_jobNr, k_bezeichnung, k_auto, k_farbe, k_datum_von, k_ganztags, k_von, k_bis, f_bezeichnung, f_kennzeichen, ka_farbe, kf_farbe, kf_color FROM kalender_termine LEFT JOIN kalender ON kalender.k_code = kalender_termine.kt_kalenderID LEFT JOIN fuhrpark ON fuhrpark.f_id = kalender.k_auto LEFT JOIN kalender_arten ON kalender_arten.ka_code = kalender.k_art LEFT JOIN kalender_terminfarbe ON kalender_terminfarbe.kf_farbe = kalender_arten.ka_farbe WHERE kt_datum=? AND k_art IN (" . $empfaengerListe . ") ORDER by test ASC"; if ($limit != false) { $stmt = $mysqli->prepare($select . " LIMIT ?" ); $stmt->bind_param("ss", $datum, $limit); } else { $stmt = $mysqli->prepare($select ); $stmt->bind_param("s", $datum); } $stmt->execute(); ######### temporär Einfügen ############################################# if ( $mysqli -> error ) { echo "<pre>"; printf("Errormessage: %s\n", $mysqli -> error); echo "<hr>"; echo $select; exit; } ######################################################################## $stmt->bind_result( $kt_id, $kt_kalenderID, $kt_datum, $test, $k_code, $k_art, $k_jobNr, $k_bezeichnung, $k_auto, $k_farbe, $k_datum_von, $k_ganztags, $k_von, $k_bis, $f_bezeichnung, $f_kennzeichen, $ka_farbe, $kf_farbe, $kf_color ); $Kalender_Termine[] = ARRAY(); if ($stmt->num_rows() > 0) { while ($stmt->fetch()) { $Kalender_Termine[] = array( 'kt_id' => $kt_id, 'kt_kalenderID' => $kt_kalenderID, 'kt_datum' => $kt_datum, 'test' => $test, 'k_code' => $k_code, 'k_art' => $k_art, 'k_jobNr' => $k_jobNr, 'k_bezeichnung' => $k_bezeichnung, 'k_auto' => $k_auto, 'k_farbe' => $k_farbe, 'k_datum_von' => $k_datum_von, 'k_ganztags' => $k_ganztags, 'k_von' => $k_von, 'k_bis' => $k_bis, 'f_bezeichnung' => $f_bezeichnung, 'f_kennzeichen' => $f_kennzeichen, 'ka_farbe' => $ka_farbe, 'kf_farbe' => $kf_farbe, 'kf_color' => $kf_color ); } } $stmt->close(); return $Kalender_Termine; }
                                                1. Hallo Regina,

                                                  ein Fehler kann eigentlich nicht sein, denn in meiner früheren Version die ohne Kalenderwochen läuft, funktioniert es einwandfrei. Hier die Ausgabe

                                                  Testausgabe: $datumTermine: $date: 2018-09-01 $teile26: Array ( [0] => 385c1689fa43c389c23c296b1b35f5cd [1] => 45c1d715636b9a9e2497d67b8a79b760 [2] => 58a32d92f11e310890adc077d0c52d2a [3] => b8b44273be5ef2df5ce61d9fcb6aa672 [4] => 733f9760ca7330cc78ecda3353393dd9 [5] => 7e9538479e00ad135a34d6e7a5047706 [6] => 1f7a6a2f19572cd8ece913eaae15f997 ) NULL Warning: Invalid argument supplied for foreach() in /monatskalender-wochen.php on line 222 Testausgabe: $datumTermine: $date: 2018-09-02 $teile26: Array ( [0] => 385c1689fa43c389c23c296b1b35f5cd [1] => 45c1d715636b9a9e2497d67b8a79b760 [2] => 58a32d92f11e310890adc077d0c52d2a [3] => b8b44273be5ef2df5ce61d9fcb6aa672 [4] => 733f9760ca7330cc78ecda3353393dd9 [5] => 7e9538479e00ad135a34d6e7a5047706 [6] => 1f7a6a2f19572cd8ece913eaae15f997 ) NULL Warning: Invalid argument supplied for foreach() in /monatskalender-wochen.php on line 222 Testausgabe: $datumTermine: $date: 2018-09-03 $teile26: Array ( [0] => 385c1689fa43c389c23c296b1b35f5cd [1] => 45c1d715636b9a9e2497d67b8a79b760 [2] => 58a32d92f11e310890adc077d0c52d2a [3] => b8b44273be5ef2df5ce61d9fcb6aa672 [4] => 733f9760ca7330cc78ecda3353393dd9 [5] => 7e9538479e00ad135a34d6e7a5047706 [6] => 1f7a6a2f19572cd8ece913eaae15f997 ) NULL Warning: Invalid argument supplied for foreach() in /monatskalender-wochen.php on line 222 Testausgabe: $datumTermine: $date: 2018-09-04 $teile26: Array ( [0] => 385c1689fa43c389c23c296b1b35f5cd [1] => 45c1d715636b9a9e2497d67b8a79b760 [2] => 58a32d92f11e310890adc077d0c52d2a [3] => b8b44273be5ef2df5ce61d9fcb6aa672 [4] => 733f9760ca7330cc78ecda3353393dd9 [5] => 7e9538479e00ad135a34d6e7a5047706 [6] => 1f7a6a2f19572cd8ece913eaae15f997 ) NULL

                                                  usw....

                                                  In der Teile 222 steht folgendes

                                                  foreach ($datumTermine as $termin)

                                                  Bis bald!
                                                  Bernd

                                                  1. ein Fehler kann eigentlich nicht sein,

                                                    Und doch ist $datumTermine nach dem Aufruf von kalender_termine($mysqli, $date, $teile25, 3); leer... was so nicht sein soll.

                                                    Lass Dir also den (wahrscheinlichen) Fehler ausgeben! Wenn es keinen geben sollte, dann lass Dir in der Funktion kalender_termine()

                                                    das $select ausgeben.

                                                    echo "<pre>"; print_r( $select ); echo "</pre>" ; $stmt -> execute();

                                                    Eine ganz wichtige Frage:

                                                    Hast Du error_reporting( E_ALL ) eingeschaltet?

                                                    1. Hallo Regina,

                                                      wenn ich mir das ausgeben lasse, erhalte ich folgende Ausgabe

                                                      1 Testausgabe: $datumTermine: $date: 2018-09-01 $teile26: Array ( [0] => 385c1689fa43c389c23c296b1b35f5cd [1] => 45c1d715636b9a9e2497d67b8a79b760 [2] => 58a32d92f11e310890adc077d0c52d2a [3] => b8b44273be5ef2df5ce61d9fcb6aa672 [4] => 733f9760ca7330cc78ecda3353393dd9 [5] => 7e9538479e00ad135a34d6e7a5047706 [6] => 1f7a6a2f19572cd8ece913eaae15f997 ) SELECT kt_id, kt_kalenderID, kt_datum, test, k_code, k_art, k_jobNr, k_bezeichnung, k_auto, k_farbe, k_datum_von, k_ganztags, k_von, k_bis, f_bezeichnung, f_kennzeichen, ka_farbe, kf_farbe, kf_color FROM kalender_termine LEFT JOIN kalender ON kalender.k_code = kalender_termine.kt_kalenderID LEFT JOIN fuhrpark ON fuhrpark.f_id = kalender.k_auto LEFT JOIN kalender_arten ON kalender_arten.ka_code = kalender.k_art LEFT JOIN kalender_terminfarbe ON kalender_terminfarbe.kf_farbe = kalender_arten.ka_farbe WHERE kt_datum=? AND k_art IN ('385c1689fa43c389c23c296b1b35f5cd','45c1d715636b9a9e2497d67b8a79b760', '58a32d92f11e310890adc077d0c52d2a','b8b44273be5ef2df5ce61d9fcb6aa672', '733f9760ca7330cc78ecda3353393dd9','7e9538479e00ad135a34d6e7a5047706', '1f7a6a2f19572cd8ece913eaae15f997') ORDER by test ASC 1 NULL Warning: Invalid argument supplied for foreach() in /monatskalender-wochen.php on line 222 SELECT kt_id, kt_kalenderID, kt_datum, test, k_code, k_art, k_jobNr, k_bezeichnung, k_auto, k_farbe, k_datum_von, k_ganztags, k_von, k_bis, f_bezeichnung, f_kennzeichen, ka_farbe, kf_farbe, kf_color FROM kalender_termine LEFT JOIN kalender ON kalender.k_code = kalender_termine.kt_kalenderID LEFT JOIN fuhrpark ON fuhrpark.f_id = kalender.k_auto LEFT JOIN kalender_arten ON kalender_arten.ka_code = kalender.k_art LEFT JOIN kalender_terminfarbe ON kalender_terminfarbe.kf_farbe = kalender_arten.ka_farbe WHERE kt_datum=? AND k_art IN ('385c1689fa43c389c23c296b1b35f5cd','45c1d715636b9a9e2497d67b8a79b760', '58a32d92f11e310890adc077d0c52d2a','b8b44273be5ef2df5ce61d9fcb6aa672', '733f9760ca7330cc78ecda3353393dd9','7e9538479e00ad135a34d6e7a5047706', '1f7a6a2f19572cd8ece913eaae15f997') ORDER by test ASC 1

                                                      Es dreht sich wohl immer wider um diesen Punkt

                                                      Warning: Invalid argument supplied for foreach() in /monatskalender-wochen.php on line 222

                                                      Wenn ich das SQL im phpMyAdmin mit dem heutigen Datum ausgeben lasse, bekomme ich Einträge

                                                      Bis bald!
                                                      Bernd

                                                      1. Das ist schon ziemlich heftig, den Code nicht vor mir zu haben, sondern aus den Beiträgen zusammensuchen zu müssen.

                                                        Schick mir den code per Mail. Und komme bitte nicht auf die Idee, meine Maildresse hier ins Forum zu setzen.

                                                        1. Hallo Regina,

                                                          nein, warum sollte ich dir den Code zukommen lassen? Es steht alles hier im Forum.

                                                          Bis bald!
                                                          Bernd

                                                          1. nein, warum sollte ich dir den Code zukommen lassen?

                                                            Weil Du Hilfe brauchst.

                                                            Es steht alles hier im Forum.

                                                            Ich zitiere mich selbst:

                                                            Das ist schon ziemlich heftig, den Code nicht vor mir zu haben, sondern aus den Beiträgen zusammensuchen zu müssen.

                                                            Du willst und brauchst Hilfe? Dann mach es mir nicht unnötig schwer.

                                                            1. Hallo Regina,

                                                              ich verschicke nichts über Webseite wo ich nicht weiß was auf mich zukommt und wo ich die Person nicht kenne.

                                                              Dann danke ich dir für die Hilfe bis hierher.

                                                              Bis bald!
                                                              Bernd

                                                              1. Hallo,

                                                                mir ist hier

                                                                function formatiere_tag($thisMonth, $day_count, $day, $today, $mysqli, $teile25 {}

                                                                und hier

                                                                function erzeuge_kalenderwochen($firstOfMonth, $mysqli, $teile25) {}

                                                                aufgefallen, dass $mysqli nicht ganz am Anfang steht. Ist dieses richtig? Ich schreibe dieses immer an erster Stelle.

                                                                Wenn ich dieses an die erste Stelle setzt erhalte ich folgende Meldung

                                                                Warning: date() expects parameter 2 to be integer, object given in /monatskalender-wochen.php on line 144 Warning: date() expects parameter 2 to be integer, object given in /monatskalender-wochen.php on line 145 Warning: date() expects parameter 2 to be integer, object given in /monatskalender-wochen.php on line 146 Warning: date() expects parameter 2 to be integer, object given in /monatskalender-wochen.php on line 153 Warning: date() expects parameter 2 to be integer, object given in /monatskalender-wochen.php on line 160

                                                                In den Zeile steht folgendes

                                                                $thisMonth = date("Y-m", $firstOfMonth); $showYear = intval(date('Y', $firstOfMonth)); $showMonth = intval(date('m', $firstOfMonth));

                                                                und

                                                                $weekDayBeforeFirst = (6 + intval(date('w', $firstOfMonth))) % 7; $day = 1 - $weekDayBeforeFirst;

                                                                liegt das ganze Problem vielleicht daran?

                                                                Bis bald!
                                                                Bernd

                                                                1. liegt das ganze Problem vielleicht daran?

                                                                  Das fehlen vollständigen oder zusammemnhängenden Quelltextes verhindert zuverlässig, dass Dir geholfen werden kann.

                                                                  Wenn ich dieses an die erste Stelle setzt erhalte ich folgende Meldung

                                                                  Generell gilt: Mehr Fehlermeldungen/Warnungen Art weisen auf mehr Fehler hin.

                                                                  1. Hallo Regina,

                                                                    Das fehlen vollständigen oder zusammemnhängenden Quelltextes verhindert zuverlässig, dass Dir geholfen werden kann.

                                                                    ich kann dir nicht mehr zeigen wie hier im Forum steht, denn ich habe nicht mehr. Ich weiß nicht warum du immer wieder auf diesem Thema herumhackst?

                                                                    $admin_kalenderarten = admin_kalenderarten($mysqli); // Monate auf Deutsch $monate = array( 1=>"Januar", 2=>"Februar", 3=>"März", 4=>"April", 5=>"Mai", 6=>"Juni", 7=>"Juli", 8=>"August", 9=>"September", 10=>"Oktober", 11=>"November", 12=>"Dezember" ); // Anzuzeigenden Monat aus $_GET["ym"] laden und auf 1. des Monats einstellen $timestamp = get_anzeigemonat_timestamp(); $showYear = date('Y', $timestamp); $showMonth = date('m', $timestamp); // H3 Title $html_title = sprintf("%04d / %02d", $showYear, $showMonth); // Prev & Next / Monat Link $nextMonth = date('Y-m', mktime(0, 0, 0, $showMonth+1, 1, $showYear)); $prevMonth = date('Y-m', mktime(0, 0, 0, $showMonth-1, 1, $showYear)); // <tr>...</tr> Zeilen für die Kalenderausgabe konstruieren $weeks = erzeuge_kalenderwochen($timestamp, $mysqli, $teile25); /** * Ermittle den Timestamp für den 1. des anzuzeigenden Monats. Der Monat wird * im Query-Parameter ym übergeben. Fehlt der oder hat falsches Format, wird * der aktuelle Monat verwendet. * * @return int Unix-Timestamp des ersten Tages im Anzeigemonat */ function get_anzeigemonat_timestamp() { $ym = filter_input(INPUT_GET, "ym", FILTER_VALIDATE_REGEXP, [ 'options' => [ 'regexp'=>'/\d{4}-\d{1,2}/' ] ]); // Parameter fehlt oder die Validierung ist gescheitert if (is_null($ym) || $ym === false) { $ym = date('Y-m'); } // $ym ist jetzt immer im Format yyyy-mm. // Entweder durch Regex bestätigt, oder von date geliefert. $parts = explode("-", $ym); // Monat Jahr return mktime(0,0,0,intval($parts[1]),1,intval($parts[0])); } /** * Generiert Table Rows mit Kalendereinträgen. Daten werden automatisch beschafft. * * @return array Ein Array mit fertigen HTML Fragmenten pro Row */ function erzeuge_kalenderwochen($firstOfMonth, $mysqli, $teile25) { $thisMonth = date("Y-m", $firstOfMonth); $showYear = intval(date('Y', $firstOfMonth)); $showMonth = intval(date('m', $firstOfMonth)); // date('w') liefert 0:So 1:Mo 2:Di usw... // Finde Wochentag des Monatsersten, +6, %7, ergibt Wochentag des Tages zuvor. // Diese Tagesnummer ist die Anzahl von leeren Feldern vor dem 1. des Monats // $day wird die auszugebende Tagesnummer sein, d.h. um N Felder leerzulassen, // wird $day auf 1-N initialisiert. $weekDayBeforeFirst = (6 + intval(date('w', $firstOfMonth))) % 7; $day = 1 - $weekDayBeforeFirst; // Kalender zusammenbauen // Tagesdatum und YYYY-MM Form des aktuellen Monats ermitteln $today = date('Y-m-d', time()); // Anzahl der Tage im Anzeigemonat ermitteln $day_count = intval(date('t', $firstOfMonth)); // $weeks: Ein Eintrag pro Anzeigewoche $weeks = []; while ($day <= $day_count) { // Negative Werte oder zu große Werte für $day sind kein Problem, die werden // von mktime in den passenden Monat verschoben. $weekNr = date('W', mktime(0,0,0,$showMonth, $day, $showYear)); $weekParts = [ "<td class='kw'>$weekNr</td>" ]; // Die 7 Tage einer Woche aufbereiten for ($i=0; $i<7; $i++) { $weekParts[] = formatiere_tag($thisMonth, $day_count, $day, $today, $mysqli, $teile25); $day++; } $weeks[] = "<tr>".implode('', $weekParts)."</tr>"; } return $weeks; } /** * Formatiere das HTML Fragment für einen Kalendertag * * @param \mysqli $mysqli mysqli-Objekt für Datenbeschaffung * @param string $date Anfragedatum, yyyy-mm-tt * @param bool $aktuellerTag True um Tag als aktuelles Datum zu formatieren * @return string */ function formatiere_tag($thisMonth, $day_count, $day, $today, $mysqli, $teile25) { if ($day < 1 || $day > $day_count) { return "<td class='emptyDay'></td>"; } $date = $thisMonth . sprintf('-%02d', $day); // Daten beschaffen $datumTermine = kalender_termine($mysqli, $date, $teile25, 3); ##### Debugging ##################################################### echo "<pre>Testausgabe:\n\n"; echo '$datumTermine: '; print_r( $datumTermine ); echo "\n" . '$date: '; print_r( $date ); echo "\n" . '$teile26: '; print_r( $teile25 ); //exit; ##################################################################### $anzTermineGesamt = count_alle_kalender_termine($mysqli, $date, $teile25); var_dump($datumTermine); $dayClasses = ($date == $today ? "today " : ""); $dayHtml = "<td class='$dayClasses calendarDay'>" . formatiere_tag_header($date, $day, $anzTermineGesamt); foreach ($datumTermine as $termin) { $dayHtml .= formatiere_termin($termin); } return $dayHtml . '</td>'; } /** * Ermittle alle Kalendereinträge zu einem Datum und einer Liste von Empfängern * * @param \mysqli $mysqli Eine MySQLI Connection * @param string $datum Das Abfragedatum im Format yyyy-mm-dd * @param string[] $teile25 Komma-getrennte Liste der möglichen Kalenderarten (k_art) * * @return Array */ function kalender_termine($mysqli, $datum, $teile25, $limit = false) { $values = $teile25; $empfaengerListe = "'".implode("','", $values)."'"; $select = "SELECT kt_id, kt_kalenderID, kt_datum, test, k_code, k_art, k_jobNr, k_bezeichnung, k_auto, k_farbe, k_datum_von, k_ganztags, k_von, k_bis, f_bezeichnung, f_kennzeichen, ka_farbe, kf_farbe, kf_color FROM kalender_termine LEFT JOIN kalender ON kalender.k_code = kalender_termine.kt_kalenderID LEFT JOIN fuhrpark ON fuhrpark.f_id = kalender.k_auto LEFT JOIN kalender_arten ON kalender_arten.ka_code = kalender.k_art LEFT JOIN kalender_terminfarbe ON kalender_terminfarbe.kf_farbe = kalender_arten.ka_farbe WHERE kt_datum=? AND k_art IN (" . $empfaengerListe . ") ORDER by test ASC"; if ($limit != false) { $stmt = $mysqli->prepare($select . " LIMIT ?" ); $stmt->bind_param("ss", $datum, $limit); } else { $stmt = $mysqli->prepare($select ); $stmt->bind_param("s", $datum); } echo "<pre>". print_r( $select ); echo "</pre>" ; $stmt->execute(); ######### temporär Einfügen ############################################# if ( $mysqli -> error ) { echo "<pre>"; printf("Errormessage: %s\n", $mysqli -> error); echo "<hr>"; echo $select; exit; } ######################################################################## $stmt->bind_result( $kt_id, $kt_kalenderID, $kt_datum, $test, $k_code, $k_art, $k_jobNr, $k_bezeichnung, $k_auto, $k_farbe, $k_datum_von, $k_ganztags, $k_von, $k_bis, $f_bezeichnung, $f_kennzeichen, $ka_farbe, $kf_farbe, $kf_color ); } /** * Zähle die Kalendereinträge zu einem Datum und einer Liste von Kalenderarten * * @param \mysqli $mysqli Eine MySQLI Connection * @param string $datum Das Abfragedatum im Format yyyy-mm-dd * @param string[] $teile25 Komma-getrennte Liste der möglichen Kalenderarten (k_art) * * @return int Anzahl Einträge */ function Count_Alle_Kalender_Termine($mysqli, $datum, $teile25) { // Bis eine bessere Abfrage bereitstelt, auf die alte Technik der unlimitierten // Abfrage zurückfallen $termine = Kalender_Termine($mysqli, $datum, $teile25); return count($termine); } function formatiere_tag_header($date, $day, $anzTermine) { $dailyLink = '<a href="tageskalender.php?date='.$date .'">'; if ($anzTermine > 3) { $header = "$day - {$dailyLink}Alle $anzTermine anzeigen</a>"; } else { $header = $dailyLink.$day."</a>"; } return "<div class='dayHeader'>$header</div>"; } function formatiere_termin($termin) { // Formatiere_Datenblatt_Link wählt k/f-Bezeichnung automatisch aus. // Formatiere_JobNr_und_Zeit gibt nur ein <span> aus wenn die JobNr // gefüllt oder ein Zeitraum angefordert ist. Sonst kommt '' zurück. if ($termin["kt_datum"] == $termin["k_datum_von"]) { if ($termin["k_ganztags"] == "0") { $terminHoehe = ''; $terminInhalt = formatiere_datenblatt_link($termin) . formatiere_jobNr_und_zeit($termin, true); } else { $terminHoehe = 'min-height: 37px;'; $terminInhalt = formatiere_datenblatt_link($termin) . formatiere_jobNr_und_zeit($termin, false); } } else { $terminHoehe = 'height: 37px;'; // Wochentag des Termindatums prüfen $datum = getdate(strtotime($termin["kt_datum"])); if ($datum['wday'] == 1) // Montag { $terminInhalt = formatiere_datenblatt_link($termin) . formatiere_jobNr_und_zeit($termin, false); } else { $terminInhalt = ''; } } return '<div style="background:'.$termin["ka_farbe"].'; margin-bottom:5px; padding-left:8px;'.$terminHoehe.'">' . $terminInhalt . '</div>'; } function Formatiere_Datenblatt_Link($termin) { $text = ($termin["k_auto"] == "") ? $termin["k_bezeichnung"] : $termin["f_bezeichnung"]; $url = '/kalender-datenblatt.php?code='.$termin["k_code"]; $farbe = 'color:'.$termin["kf_color"]; return '<a href="'.$url.'" style="'.$farbe.'">'.shortText($text, 15).'</a>'; //return '<span style="color:'.$termin["kf_color"].'"><a href="'.$url.'" style="'.$farbe.'">'.shortText($text, 15).'</a></span>'; } /** * Formatiere JobNr und Zeitraum eines Termineintrags. * * Ist die JobNr leer und kein Zeitraum gefordert, wird ein Leerstring zurückgegeben. * * Ist die JobNr bestückt und ein Zeitraum gefordert, werden beide durch " - " getrennt. * * Das Ergebnis wird in einen span mit style-Attribut eingehüllt, das die Farbe gemäß * Datenbank setzt. TODO: Unnötige Styles ins CSS verlegen! * * @param array $termin Terminzeile aus dem SQL Ergebnis * @param bool $mitZeitraum true übergeben um auch den Zeitraum auszugeben * * @return string HTML-Text mit span Element, das die Werte enthält */ function Formatiere_JobNr_und_Zeit($termin, $mitZeitraum) { $parts = []; if ($termin['k_jobNr'] != '') { $parts[] = $termin['k_jobNr']; } if ($mitZeitraum) { $parts[] = $termin['k_von'].' bis '.$termin['k_bis'].' Uhr'; } if (count($parts) == 0) { return ''; } return '<span style="color:'.$termin["kf_color"].'; font-size:10px; display: block; padding-bottom: 2px;">' . implode(' - ', $parts) . '</span>'; }

                                                                    Bis bald!
                                                                    Bernd

                                                                    1. So. Ein paar kleine Änderungen:

                                                                      define ('AnzahlPrevievTermine', 3); // Wie viele Termine pro Tag sollen angezeigt werden? define ('TerminHoehe', '37px;' ); // Höhe des Termins??? define ('DEBUG', true ); // Kontrollausgaben? if ( DEBUG ) { error_reporting( E_ALL ); } else { error_reporting( E_ALL & ~E_NOTICE ); } $admin_kalenderarten = admin_kalenderarten($mysqli); // Monate auf Deutsch $monate = array( 1 => "Januar", 2 => "Februar", 3 => "März", 4 => "April", 5 => "Mai", 6 => "Juni", 7 => "Juli", 8 => "August", 9 => "September", 10 => "Oktober", 11 => "November", 12 => "Dezember" ); // Anzuzeigenden Monat aus $_GET["ym"] laden und auf 1. des Monats einstellen $timestamp = get_anzeigemonat_timestamp(); $showYear = date( 'Y', $timestamp ); $showMonth = date( 'm', $timestamp ); // H3 Title $html_title = sprintf( "%04d / %02d", $showYear, $showMonth ); // Prev & Next / Monat Link $nextMonth = date( 'Y-m', mktime( 0, 0, 0, $showMonth+1, 1, $showYear ) ); $prevMonth = date( 'Y-m', mktime( 0, 0, 0, $showMonth-1, 1, $showYear ) ); // <tr>...</tr> Zeilen für die Kalenderausgabe konstruieren $weeks = erzeuge_kalenderwochen( $timestamp, $mysqli, $teile25 ); /** * Ermittle den Timestamp für den 1. des anzuzeigenden Monats. Der Monat wird * im Query-Parameter ym übergeben. Fehlt der oder hat falsches Format, wird * der aktuelle Monat verwendet. * * @return int Unix-Timestamp des ersten Tages im Anzeigemonat */ function get_anzeigemonat_timestamp() { $ym = filter_input(INPUT_GET, "ym", FILTER_VALIDATE_REGEXP, [ 'options' => [ 'regexp'=>'/\d{4}-\d{1,2}/' ] ]); // Auf aktuellen Monat setzen wenn Parameter fehlt oder die gescheitert Validierung ist if ( is_null( $ym ) || $ym === false ) { $ym = date('Y-m'); } // $ym ist jetzt immer im Format yyyy-mm. // Entweder durch Regex bestätigt, oder von date geliefert. $parts = explode( "-", $ym ); // Monat Jahr return mktime( 0, 0, 0, intval( $parts[1] ), 1, intval($parts[0] ) ); } /** * Generiert Table Rows mit Kalendereinträgen. Daten werden automatisch beschafft. * * @return array Ein Array mit fertigen HTML Fragmenten pro Row */ function erzeuge_kalenderwochen( $firstOfMonth, $mysqli, $teile25 ) { $thisMonth = date( "Y-m", $firstOfMonth ); $showYear = intval( date( 'Y', $firstOfMonth ) ); $showMonth = intval( date( 'm', $firstOfMonth ) ); // date('w') liefert 0:So 1:Mo 2:Di usw... // Finde Wochentag des Monatsersten, +6, %7, ergibt Wochentag des Tages zuvor. // Diese Tagesnummer ist die Anzahl von leeren Feldern vor dem 1. des Monats // $day wird die auszugebende Tagesnummer sein, d.h. um N Felder leerzulassen, // wird $day auf 1-N initialisiert. $weekDayBeforeFirst = ( 6 + intval( date( 'w', $firstOfMonth ) ) ) % 7; $day = 1 - $weekDayBeforeFirst; // Kalender zusammenbauen // Tagesdatum und YYYY-MM Form des aktuellen Monats ermitteln $today = date( 'Y-m-d', time() ); // Anzahl der Tage im Anzeigemonat ermitteln $day_count = intval( date( 't', $firstOfMonth ) ); // $weeks: Ein Eintrag pro Anzeigewoche $weeks = array(); while ( $day <= $day_count ) { // Negative Werte oder zu große Werte für $day sind kein Problem, die werden // von mktime in den passenden Monat verschoben. $weekParts = array(); $weekNr = date( 'W', mktime( 0, 0, 0, $showMonth, $day, $showYear ) ); $weekParts[] = "<td class='kw'>$weekNr</td>"; // Die 7 Tage einer Woche aufbereiten for ( $i=0; $i<7; $i++ ) { $weekParts[] = formatiere_tag( $thisMonth, $day_count, $day, $today, $mysqli, $teile25 ); $day++; } $weeks[] = "<tr>".implode( '', $weekParts )."</tr>"; } return $weeks; } /** * Formatiere das HTML Fragment für einen Kalendertag * * @param \mysqli $mysqli mysqli-Objekt für Datenbeschaffung * @param string $date Anfragedatum, yyyy-mm-tt * @param bool $aktuellerTag True um Tag als aktuelles Datum zu formatieren * @return string */ function formatiere_tag( $thisMonth, $day_count, $day, $today, $mysqli, $teile25 ) { if ( $day < 1 || $day > $day_count ) { return "<td class='emptyDay'></td>"; } $date = $thisMonth . sprintf( '-%02d', $day ); // Daten beschaffen $datumTermine = kalender_termine( $mysqli, $date, $teile25 ); if ( DEBUG ) { echo '<pre><hr>$datumTermine (' . $date . ') <hr>'; print_r ( $datumTermine ); echo '/<pre>'; } $anzTermineGesamt = count($datumTermine ); $dayClasses = ( $date == $today ? "today " : "" ); $dayHtml = "<td class='$dayClasses calendarDay'>" . formatiere_tag_header( $date, $day, $anzTermineGesamt ); // Begrenzen der Anzahl der gezeigten Termine auf höchstens "3" ( Konstante: AnzahlPrevievTermine) $end = $anzTermineGesamt; if ( $end > AnzahlPrevievTermine ) { $end = AnzahlPrevievTermine; } for $i=0; $i < $end; $i++) { $dayHtml .= formatiere_termin( $datumTermine[$i] ); } return $dayHtml . '</td>'; } /** * Ermittle alle Kalendereinträge zu einem Datum und einer Liste von Empfängern * * @param \mysqli $mysqli Eine MySQLI Connection * @param string $datum Das Abfragedatum im Format yyyy-mm-dd * @param string[] $teile25 Komma-getrennte Liste der möglichen Kalenderarten (k_art) * * @return Array */ function kalender_termine( $mysqli, $datum, $teile25 ) { $values = $teile25; $empfaengerListe = '"' . implode( '", "', $values ) . '"'; $select = 'SELECT kt_id, kt_kalenderID, kt_datum, test, k_code, k_art, k_jobNr, k_bezeichnung, k_auto, k_farbe, k_datum_von, k_ganztags, k_von, k_bis, f_bezeichnung, f_kennzeichen, ka_farbe, kf_farbe, kf_color FROM kalender_termine LEFT JOIN kalender ON kalender.k_code = kalender_termine.kt_kalenderID LEFT JOIN fuhrpark ON fuhrpark.f_id = kalender.k_auto LEFT JOIN kalender_arten ON kalender_arten.ka_code = kalender.k_art LEFT JOIN kalender_terminfarbe ON kalender_terminfarbe.kf_farbe = kalender_arten.ka_farbe WHERE kt_datum=" . $datum . " AND k_art IN (' . $empfaengerListe . ') ORDER by test ASC'; $stmt = $mysqli->prepare($select ); $stmt -> execute(); if ( $mysqli -> error ) { if ( DEBUG ) { echo "<pre>"; printf( "Errormessage: %s\n", $mysqli -> error ); echo "<hr>$select</hr>"; exit; } else { echo "<h1>Sorry</h1><p>Leider ist bei der Datenbankabfrage ein Fehler aufgtreten.</p>"; exit; } } $stmt -> bind_result ( $kt_id, $kt_kalenderID, $kt_datum, $test, $k_code, $k_art, $k_jobNr, $k_bezeichnung, $k_auto, $k_farbe, $k_datum_von, $k_ganztags, $k_von, $k_bis, $f_bezeichnung, $f_kennzeichen, $ka_farbe, $kf_farbe, $kf_color ); $Kalender_Termine = array(); if ( $stmt -> num_rows() > 0 ) { while ( $stmt -> fetch() ) { $arTemp = array(); $arTemp['kt_id'] => $kt_id; $arTemp['kt_kalenderID'] => $kt_kalenderID; $arTemp['kt_datum'] => $kt_datum; $arTemp['test'] => $test; $arTemp['k_code'] => $k_code; $arTemp['k_art'] => $k_art; $arTemp['k_jobNr'] => $k_jobNr; $arTemp['k_bezeichnung'] => $k_bezeichnung; $arTemp['k_auto'] => $k_auto; $arTemp['k_farbe'] => $k_farbe; $arTemp['k_datum_von'] => $k_datum_von; $arTemp['k_ganztags'] => $k_ganztags; $arTemp['k_von'] => $k_von; $arTemp['k_bis'] => $k_bis; $arTemp['f_bezeichnung'] => $f_bezeichnung; $arTemp['f_kennzeichen'] => $f_kennzeichen; $arTemp['ka_farbe'] => $ka_farbe; $arTemp['kf_farbe'] => $kf_farbe; $arTemp['kf_color'] => $kf_color $Kalender_Termine[] = $arTemp; } } $stmt -> close(); if ( DEBUG ) { echo '<pre><hr>$Kalender_Termine vor Rückkgabe:<hr>'; print_r( $Kalender_Termine ); echo '<hr></pre>'; } return $Kalender_Termine; } function formatiere_tag_header($date, $day, $anzTermine) { $dailyLink = '<a href="tageskalender.php?date='.$date .'">'; if ( $anzTermine > 3 ) { $header = "$day - {$dailyLink}Alle $anzTermine anzeigen</a>"; } else { $header = $dailyLink.$day . "</a>"; } return "<div class='dayHeader'>$header</div>"; } function formatiere_termin($termin) { // Formatiere_Datenblatt_Link wählt k/f-Bezeichnung automatisch aus. // Formatiere_JobNr_und_Zeit gibt nur ein <span> aus wenn die JobNr // gefüllt oder ein Zeitraum angefordert ist. Sonst kommt '' zurück. if ( $termin["kt_datum"] == $termin["k_datum_von"] ) { if ( $termin["k_ganztags"] == "0" ) { $terminHoehe = ''; $terminInhalt = formatiere_datenblatt_link( $termin ) . formatiere_jobNr_und_zeit( $termin, true ); } else { $terminHoehe = 'min-height: ' . TerminHoehe; $terminInhalt = formatiere_datenblatt_link( $termin ) . formatiere_jobNr_und_zeit( $termin, false ); } } else { $terminHoehe = 'height: ' . TerminHoehe; // Wochentag des Termindatums prüfen $datum = getdate( strtotime( $termin["kt_datum"] ) ); // Montag = 1 if ( $datum['wday'] == 1 ) { $terminInhalt = formatiere_datenblatt_link( $termin ) . formatiere_jobNr_und_zeit( $termin, false ); } else { $terminInhalt = ''; } } return '<div style="background:' . $termin["ka_farbe"] . '; margin-bottom:5px; padding-left:8px;' . $terminHoehe . '">' . $terminInhalt . '</div>'; } function Formatiere_Datenblatt_Link( $termin ) { $text = ( $termin["k_auto"] == "" ) ? $termin["k_bezeichnung"] : $termin["f_bezeichnung"]; $url = '/kalender-datenblatt.php?code=' . $termin["k_code"]; $farbe = 'color:' . $termin["kf_color"]; return '<a href="' . $url . '" style="' . $farbe . '">' . shortText( $text, 15 ) . '</a>'; //return '<span style="color:' . $termin["kf_color"] . '"><a href="' . $url . '" style="' . $farbe . '">' . shortText( $text, 15 ) . '</a></span>'; } /** * Formatiere JobNr und Zeitraum eines Termineintrags. * * Ist die JobNr leer und kein Zeitraum gefordert, wird ein Leerstring zurückgegeben. * * Ist die JobNr bestückt und ein Zeitraum gefordert, werden beide durch " - " getrennt. * * Das Ergebnis wird in einen span mit style-Attribut eingehüllt, das die Farbe gemäß * Datenbank setzt. TODO: Unnötige Styles ins CSS verlegen! * * @param array $termin Terminzeile aus dem SQL Ergebnis * @param bool $mitZeitraum true übergeben um auch den Zeitraum auszugeben * * @return string HTML-Text mit span Element, das die Werte enthält */ function Formatiere_JobNr_und_Zeit( $termin, $mitZeitraum ) { $parts = array(); if ( $termin['k_jobNr'] != '' ) { $parts[] = $termin['k_jobNr']; } if ( $mitZeitraum ) { $parts[] = $termin['k_von'] . ' bis '.$termin['k_bis'] . ' Uhr'; } if ( count( $parts ) == 0 ) { return ''; } return '<span style="color:' . $termin["kf_color"] . '; font-size:10px; display: block; padding-bottom: 2px;">' . implode( ' - ', $parts ) . '</span>'; }
                                                                      1. Hallo Regina,

                                                                        danke, was ist hier falsch?

                                                                        if ( $stmt -> num_rows() > 0 ) { while ( $stmt -> fetch() ) { $arTemp = array(); $arTemp['kt_id'] => $kt_id; $arTemp['kt_kalenderID'] => $kt_kalenderID; }

                                                                        Es wird an dieser Stelle gemeckert

                                                                        $arTemp['kt_id'] => $kt_id;

                                                                        Parse error: syntax error, unexpected '=>' (T_DOUBLE_ARROW)

                                                                        Bis bald!
                                                                        Bernd

                                                                        1. Hallo Bernd,

                                                                          ich habe mir viel Arbeit gemacht, Regina auch. Aber diese Rückfrage tut jetzt weh - DIESEN Fehler solltest Du selbst identifizieren können.

                                                                          Gerade Syntaxfehler sind gerne mal Folgefehler durch ein Problem kurz davor.

                                                                          Wie baut man ein Array mit vorbelegten Einträgen auf? Was ist da im Umfeld der bemängelten Zeile nicht so, wie es dafür sein sollte?

                                                                          Rolf

                                                                          -- sumpsi - posui - clusi
                                                                        2. Versuchs an allen diesen Stellen mal mit "=" statt "=>".

                                                                          1. Hallo Regina,

                                                                            leider sehe ich noch immer keine Termine.

                                                                            Bis bald!
                                                                            Bernd

                                                                            1. $stmt = $mysqli -> prepare( $select ); ############ Diese Zeilen temporär einfügen# echo "<pre>"; echo "Mysql-Connect-Fehlernuummer: " . mysqli_connect_errno(); echo "Mysql-Connect-Fehlertext: " . mysqli_connect_error(); echo "mysqli:\n"; var_dump( $mysqli ); echo "<hr>$select</hr></pre>"; ########################################### $stmt -> execute();

                                                                              Dann füge das obige mal an der geeigneten Stelle ein. Führe dann die Befehle in PHPmyadmin aus. Ich bezweifle nämlich stark, dass die Datenbank da Datensätze zurück liefert.

                                                                              Grund: Du hast sicherlich auch beim mysqli_connect() keine Fehler abgefangen.

                                                                              1. Hallo Regina,

                                                                                ich verstehe die Welt nicht mehr. Wenn ich folgendes im phpMyAdmin ausführe, was bei der Ausgabe herauskommt

                                                                                SELECT kt_id, kt_kalenderID, kt_datum, test, k_code, k_art, k_jobNr, k_bezeichnung, k_auto, k_farbe, k_datum_von, k_ganztags, k_von, k_bis, f_bezeichnung, f_kennzeichen, ka_farbe, kf_farbe, kf_color FROM kalender_termine LEFT JOIN kalender ON kalender.k_code = kalender_termine.kt_kalenderID LEFT JOIN fuhrpark ON fuhrpark.f_id = kalender.k_auto LEFT JOIN kalender_arten ON kalender_arten.ka_code = kalender.k_art LEFT JOIN kalender_terminfarbe ON kalender_terminfarbe.kf_farbe = kalender_arten.ka_farbe WHERE kt_datum=2018-09-02 AND k_art IN ("385c1689fa43c389c23c296b1b35f5cd", "45c1d715636b9a9e2497d67b8a79b760", "58a32d92f11e310890adc077d0c52d2a", "b8b44273be5ef2df5ce61d9fcb6aa672", "733f9760ca7330cc78ecda3353393dd9", "7e9538479e00ad135a34d6e7a5047706", "1f7a6a2f19572cd8ece913eaae15f997") ORDER by test ASC

                                                                                erscheint nichts.

                                                                                MySQL lieferte ein leeres Resultat zurück (d.h. null Datensätze). (Die Abfrage dauerte 0.0001 Sekunden.)

                                                                                Aber das SQL hat die ganze Zeit funktioniert.

                                                                                Bis bald!
                                                                                Bernd

                                                                                1. Eigentlich hätte da jetzt ein Fehler stehen müssen. Andere das wie folgt:

                                                                                  $select = 'SELECT kt_id, kt_kalenderID, kt_datum, test, k_code, k_art, k_jobNr, k_bezeichnung, k_auto, k_farbe, k_datum_von, k_ganztags, k_von, k_bis, f_bezeichnung, f_kennzeichen, ka_farbe, kf_farbe, kf_color FROM kalender_termine LEFT JOIN kalender ON kalender.k_code = kalender_termine.kt_kalenderID LEFT JOIN fuhrpark ON fuhrpark.f_id = kalender.k_auto LEFT JOIN kalender_arten ON kalender_arten.ka_code = kalender.k_art LEFT JOIN kalender_terminfarbe ON kalender_terminfarbe.kf_farbe = kalender_arten.ka_farbe WHERE kt_datum="' . $datum . '" AND k_art IN (' . $empfaengerListe . ') ORDER by test ASC';
                                                                                  1. Hallo Regina,

                                                                                    das habe ich auch festgestellt, konnte den Beitrag nur nicht mehr editieren:
                                                                                    https://forum.selfhtml.org/self/2018/sep/8/kw-als-spalte-einfuegen/1731837#m1731837

                                                                                    Bis bald!
                                                                                    Bernd

                                                                                2. Hallo Regina,

                                                                                  ich verstehe die Welt nicht mehr. Wenn ich folgendes im phpMyAdmin ausführe, was bei der Ausgabe herauskommt

                                                                                  SELECT kt_id, kt_kalenderID, kt_datum, test, k_code, k_art, k_jobNr, k_bezeichnung, k_auto, k_farbe, k_datum_von, k_ganztags, k_von, k_bis, f_bezeichnung, f_kennzeichen, ka_farbe, kf_farbe, kf_color FROM kalender_termine LEFT JOIN kalender ON kalender.k_code = kalender_termine.kt_kalenderID LEFT JOIN fuhrpark ON fuhrpark.f_id = kalender.k_auto LEFT JOIN kalender_arten ON kalender_arten.ka_code = kalender.k_art LEFT JOIN kalender_terminfarbe ON kalender_terminfarbe.kf_farbe = kalender_arten.ka_farbe WHERE kt_datum=2018-09-02 AND k_art IN ("385c1689fa43c389c23c296b1b35f5cd", "45c1d715636b9a9e2497d67b8a79b760", "58a32d92f11e310890adc077d0c52d2a", "b8b44273be5ef2df5ce61d9fcb6aa672", "733f9760ca7330cc78ecda3353393dd9", "7e9538479e00ad135a34d6e7a5047706", "1f7a6a2f19572cd8ece913eaae15f997") ORDER by test ASC

                                                                                  erscheint nichts.

                                                                                  MySQL lieferte ein leeres Resultat zurück (d.h. null Datensätze). (Die Abfrage dauerte 0.0001 Sekunden.)

                                                                                  Aber das SQL hat die ganze Zeit funktioniert.

                                                                                  EDIT, ein Fehler habe ich gefunden, es muss so heißen:

                                                                                  WHERE kt_datum="'.$datum.'"

                                                                                  Jetzt erhalte ich auch eine Ausgabe im phpMyAdmin

                                                                                  Allerdings auf der Webseite sehe ich noch immer nichts.

                                                                                  Bis bald!
                                                                                  Bernd

                                                                                  Folgende Nachrichten verweisen auf diesen Beitrag:

                                                                                  1. Hallo Barksalot,

                                                                                    offener Punkt: Was kommt bei der Fehlerausgabe heraus die Regina erbeten hat:

                                                                                    echo "<pre>"; echo "Mysql-Connect-Fehlernuummer: " . mysqli_connect_errno(); echo "Mysql-Connect-Fehlertext: " . mysqli_connect_error(); echo "mysqli:\n"; var_dump( $mysqli ); echo "<hr>$select</hr></pre>";

                                                                                    Wenn das keinen Fehler ergibt, müsstest Du mal eigenständig debuggen:

                                                                                    Was die SQL Zugriffsfunktion tun soll, weißt Du. D.h. Du hast eine Vorstellung, was an welcher Stelle erwartet wird. Füge Kontrollausgaben ein und guck, was rauskommt. Prüfe nach jedem Schritt: sollte DAS jetzt herauskommen?

                                                                                    Guck Dir die PHP Doku der verwendeten mysqli-Funktionen an. Was geben die im Erfolgs- und Fehlerfall zurück? Lass Dir ausgeben, ob eine einen Fehler geliefert hat (Achtung: Wenn es heißt, dass eine Funktion im Fehlerfall FALSE zurückgibt, dann musst Du das so testen:

                                                                                    $ergebnis = somefunction(); // SO NICHT if ($ergebnis == FALSE) echo "Somefunction war nicht erfolgreich"; // SO IST ES RICHTIG if ($ergebnis === FALSE) echo "Somefunction war nicht erfolgreich";

                                                                                    Das eine = mehr ist in PHP relevant, siehe dazu das PHP Handbuch zum Thema Type Juggling und Vergleichsoperatoren

                                                                                    Rolf

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

                                                                                      offener Punkt: Was kommt bei der Fehlerausgabe heraus die Regina erbeten hat:

                                                                                      da kommt folgendes raus:

                                                                                      Mysql-Connect-Fehlernuummer: 0Mysql-Connect-Fehlertext: mysqli: object(mysqli)#1 (19) { ["affected_rows"]=> int(-1) ["client_info"]=> string(79) "mysqlnd 5.0.12-dev - 20150407 - $Id: b5c5906d452ec590732a93b051f3827e02749b83 $" ["client_version"]=> int(50012) ["connect_errno"]=> int(0) ["connect_error"]=> NULL ["errno"]=> int(0) ["error"]=> string(0) "" ["error_list"]=> array(0) { } ["field_count"]=> int(19) ["host_info"]=> string(25) "Localhost via UNIX socket" ["info"]=> NULL ["insert_id"]=> int(0) ["server_info"]=> string(15) "5.7.21-nmm1-log" ["server_version"]=> int(50721) ["stat"]=> string(152) "Uptime: 1348945 Threads: 8 Questions: 146347186 Slow queries: 183 Opens: 643629 Flush tables: 1 Open tables: 4089 Queries per second avg: 108.490" ["sqlstate"]=> string(5) "00000" ["protocol_version"]=> int(10) ["thread_id"]=> int(1557456) ["warning_count"]=> int(0) }

                                                                                      Ich kann es einfach nicht verstehen. Mein Script war nicht perfekt, was ich auch nie behauptet habe. Wollte nur die Kalenderwochen davor haben. Jetzt ein kompletter umbau. Verstehe es einfach nicht warum dieses alles sein muss. Hätte man die korrekten Wochen nicht auch bei mir einfügen können?

                                                                                      Bis bald!
                                                                                      Bernd

                                                                                      1. Hätte man die korrekten Wochen nicht auch bei mir einfügen können?

                                                                                        Wieso will die Fachwerkstatt an den PKW mit den offensichtlichen kaputten Bremsen, überbrückten Sicherungen, heraushängenden Scheinwerfern sowie einem riesigen, 4-Tonnen schweren Sofa auf dem Dach keine Anhängerkupplung anbauen?

                                                                                        Folgende Nachrichten verweisen auf diesen Beitrag:

                                                                                        1. Hallo Regina,

                                                                                          ich habe noch 1-2 Jahre zu leben und sehe kaum noch etwas. Es lief, also warum nicht so lassen und nur KW hinzufügen.

                                                                                          Bis bald!
                                                                                          Bernd

                                                                                          1. Hallo Bernd,

                                                                                            das ist sehr traurig und tut mir leid. Ich wünsche Dir, dass diese Zeit für Dich möglichst schön und lang wird.

                                                                                            Vielleicht hast Du das früher schon mal erwähnt worden und ich habe es wieder vergessen. Der Hinweis auf das schlechte Sehen hat bei mir irgendeine Erinnerung klingeln lassen. Es mag auch erklären, warum Dir das Debuggen schwer fällt.

                                                                                            Den Hinweis "Ich will keine Refaktorierung und meinen Code so wie er ist behalten", den hättest Du geben können als Regina oder ich unseren Stand vorgestellt haben. Das hätte Dir und uns dann die Mühe erspart.

                                                                                            Die Frage "Wie geht's weiter" steht unter einem anderen Posting von mir...

                                                                                            Rolf

                                                                                            -- sumpsi - posui - clusi
                                                                                      2. Hallo Bernd,

                                                                                        ok, das sieht erstmal nach "kein Fehler beim Connect" aus. Jetzt taste Dich vor, wie beschrieben. War der Bind erfolgreich? Wieviele Rows kommen? Enthalten die gebundenen Variablen Werte? Entsteht daraus korrekt das Array für einen Termin?

                                                                                        Für Dich problematisch ist vermutlich auch, dass Regina und ich etwas unterschiedlichen Code anbieten. Ich bin bei deinem Bind geblieben, Regina zeigt fetch_row. Das ist kürzer. Auf welcher Version willst Du aufsetzen?

                                                                                        Ich kann es einfach nicht verstehen. (...) Wollte nur die Kalenderwochen davor haben. (...) Hätte man die korrekten Wochen nicht auch bei mir einfügen können?

                                                                                        Deinen Frust musst Du hier aber nicht abladen. Du hast doch selbst über die schlechte Lesbarkeit deines Codes geklagt, und daran wollten wir arbeiten. Das war der Grund, warum Regina und ich viel Code erstellt und gepostet haben. Der komplette Umbau kommt daher, dass dein Code unstrukturiert war. Das ändert sich nun.

                                                                                        Ohne direkten Zugang zu deiner Entwicklungsumgebung war und ist das eine abstrakte Sache, und kann durchaus ein paar Probleme beinhalten. Ich muss ja ungetesteten Code abliefern. Und ich weiß jetzt nicht mehr, welche Varianten aus diesem Thread Du nun aktuell verwendest. Deswegen ist es wichtig, dass Du selbst debuggst und nicht erwartest, dass wir schlüsselfertigen Code abliefern.

                                                                                        Wenn Dir dabei nun schwindelig wird - wir müssen das nicht durchziehen. Hole die alte Version aus der Sicherung und setz dort wieder auf. Grundsätzliche Hinweise, wie Du dort die KW Logik einbauen kannst, waren am Anfang dieses Threadmonsters zu finden. Ich glaube, da war eine Variante dabei die funktionieren sollte.

                                                                                        Was möchtest Du?

                                                                                        Rolf

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

                                                                                          es funktioniert etwas mit diesem:
                                                                                          https://forum.selfhtml.org/self/2018/sep/8/kw-als-spalte-einfuegen/1731850#m1731850

                                                                                          und mit diesem:
                                                                                          https://forum.selfhtml.org/self/2018/sep/8/kw-als-spalte-einfuegen/1731858#m1731858

                                                                                          allerdings nicht so wie mit meinem Ursprünglichem Code. Die Felder sind nicht mehr alle gleich hoch, ich habe zum Rand ein Abstand und es lassen sich nicht alle Einträge anklicken um in die Detailansicht zu kommen. Bei meinem Code hat dieses funktioniert.

                                                                                          Mir wäre sehr geholfen wenn es mit meiner Version gegangen wäre. Dieses kann ich jetzt wohl knicken, es ist zu viel geändert. Muss ich jetzt damit wohl leben.

                                                                                          Bis bald!
                                                                                          Bernd

                                                                                  2. Allerdings auf der Webseite sehe ich noch immer nichts.

                                                                                    Das wundert mich wirklich. Denn da sollten Debug-Ausgaben sichtbar werden. Ich kann aber nicht wissen, ob Du die nicht eingebaut hast oder ob diese durch z-index-Angaben im style-sheet verborgen werden.

                                                                                    Du glaubst gar nicht, wie schwierig Du es uns machst, weil Du Dich weigerst uns den kompletten Code (und übrigens den Datenbank-Dump) zur Verfügung zu stellen. Wir sind komplett blind weil wir das "Drumrum" nicht kennen, schreiben Dir Code, den wir schon deshalb gar nicht testen können - und Du meckerst einfachste Syntax-Fehlerchen an, statt die einfach mal zu beheben.

                                                                                    Und teilweise scheinst Du die Debug-Ausgaben mal eben abzuschalten.

                                                                                    Der Quellcode passt nicht mehr. Hier deshalb nur die Funktion kalender_termine(), die ich jetzt mal stark vereinfacht habe.

                                                                                    /** * Ermittle alle Kalendereinträge zu einem Datum und einer Liste von Empfängern * * @param \mysqli $mysqli Eine MySQLI Connection * @param string $datum Das Abfragedatum im Format yyyy-mm-dd * @param string[] $teile25 Komma-getrennte Liste der möglichen Kalenderarten (k_art) * * @return Array */ function kalender_termine( $mysqli, $datum, $teile25 ) { $values = $teile25; $empfaengerListe = '"' . implode( '", "', $values ) . '"'; $query = 'SELECT kt_id, kt_kalenderID, kt_datum, test, k_code, k_art, k_jobNr, k_bezeichnung, k_auto, k_farbe, k_datum_von, k_ganztags, k_von, k_bis, f_bezeichnung, f_kennzeichen, ka_farbe, kf_farbe, kf_color FROM kalender_termine LEFT JOIN kalender ON kalender.k_code = kalender_termine.kt_kalenderID LEFT JOIN fuhrpark ON fuhrpark.f_id = kalender.k_auto LEFT JOIN kalender_arten ON kalender_arten.ka_code = kalender.k_art LEFT JOIN kalender_terminfarbe ON kalender_terminfarbe.kf_farbe = kalender_arten.ka_farbe WHERE kt_datum="' . $datum . '" AND k_art IN (' . $empfaengerListe . ') ORDER by test ASC'; $Kalender_Termine = array(); if ( $result = $mysqli -> query( $query ) ) { while ( $row = $result -> fetch_row()) { $Kalender_Termine[] = $row; } } else { echo '<pre><hr>MySQL-Fehler:'; print_r ( mysqli_error_list( $mysqli ) ); echo '<hr></pre>'; } if ( DEBUG ) { echo '<pre><hr>$Kalender_Termine vor Rückgabe:<hr>'; print_r( $Kalender_Termine ); echo '<hr></pre>'; } return $Kalender_Termine; }

                                                                                    Folgende Nachrichten verweisen auf diesen Beitrag:

                                                                                    1. Hallo Regina,

                                                                                      soll ich eine DSGVO Abmahnung riskieren weil ich hier alle Daten aus meiner Datenbank zur Verfügung stelle?

                                                                                      Jetzt sind wir aber ein Schritt weiter, siehe Screenshot

                                                                                      Allerdings bekomme ich noch immer zwischen durch die Undefined index: kt_XXX und es werden unten im Kalender keine Termine ausgeben. Die Anzahl wenn mehr als drei (13 - Alle 9 anzeigen) angezeigt.

                                                                                      Bis bald!
                                                                                      Bernd

                                                                                      1. Es ist echt erstaunlich. Du hast ganz offensichtlich KEINERLEI Programmierkenntnisse und schnorrst Dir hier ein gewerbliches Projekt zusammen:

                                                                                        Denn jetzt steht da ein Resultat, bei dem die nachfolgenden Notizen niemanden mit Grundkenntnissen auch nur wundern.

                                                                                        Ersetze:

                                                                                        while ( $row = $result -> fetch_row() ) {

                                                                                        durch

                                                                                        while ( $row = $result -> fetch_assoc() ) {

                                                                                        und zeig die Ausgaben.

                                                                                        Folgende Nachrichten verweisen auf diesen Beitrag:

                                                                                        1. Hallo Regina,

                                                                                          natürlich ist das für mich ein gewerbliches Projekt, ich arbeite schließlich mit dem Kalender.Ganz ehrlich, auf solche dummen Bemerkungen kann ich verzichten, lass mich einfach links liegen und beachte mich überhaupt nicht mehr. Ich schaffe das schon irgendwie, wenn nicht, auch egal, dann gibt es eben keine Kalenderwochen.

                                                                                          Wer hat denn die ersten Grundfunktion gemacht? Ihr oder ich? Mir zu unterstellen ich würde alles nur zusammenschnorren finde ich eine bodenlose Frechheit von dir.

                                                                                          Bis bald!
                                                                                          Bernd

                                                                                          1. Ja und? Hat es damit nun geklappt?

                                                                                            1. Hallo Regina,

                                                                                              ja! Nur ich bin irgendwie noch nicht zufrieden damit. Zwar sehe ich, dass machen Einstellungen einfacher sind wie z.B.

                                                                                              Formatiere_Datenblatt_Link und formatiere_termin

                                                                                              Nur verstehe ich z.B. nicht, was das false in

                                                                                              $terminInhalt = formatiere_datenblatt_link( $termin ) . formatiere_jobNr_und_zeit( $termin, false );

                                                                                              bedeuten soll. Stelle ich es auf true um, passiert nichts.

                                                                                              Das Problem mit den unterschiedlichen Höhen habe ich mitlerweile auch gelöst

                                                                                              if ( $termin["kt_datum"] == $termin["k_datum_von"] ) { if ( $termin["k_ganztags"] == "0" ) { $terminHoehe = 'height: ' . TerminHoehe; $terminInhalt = formatiere_datenblatt_link( $termin ) . formatiere_jobNr_und_zeit( $termin, true ); } else { $terminHoehe = 'height: ' . TerminHoehe; $terminInhalt = formatiere_datenblatt_link( $termin ) . formatiere_jobNr_und_zeit( $termin, false ); } }

                                                                                              wahrscheinlich könnte da jetzt auch das if else weg. Aber ich trau mich schon gar nichts mehr zu fragen, ich fummel es einfach irgendwie rein und schau dass ich die Ausgabe wieder so wie früher hin bekomme.

                                                                                              Ich habe mich jetzt doch entschieden überall den k_bezeichnung anzeigen zu lassen. Aber ich lasse die Funktion drin, falls ich doch mal etwas anderes noch anzeigen lassen möchte.

                                                                                              Bis bald!
                                                                                              Bernd

                                                                                              1. Hallo Barksalot,

                                                                                                wir sprachen über Kommentare. Wenn du wissen willst was der Parameter macht, guck dir die aufgerufene Funktion und den Kommentar davor an. Der Parameter heißt $mitZeitraum. Er aktiviert etwas.

                                                                                                Ob Du das nun im Source Code liest oder ob ich das hier im Forum nochmal vorkaue, ist für dich die gleiche Textmenge. Und aus den Source lernst du mehr.

                                                                                                Rolf

                                                                                                -- sumpsi - posui - clusi
                                                                                              2. if ( $termin["kt_datum"] == $termin["k_datum_von"] ) { if ( $termin["k_ganztags"] == "0" ) { $terminHoehe = 'height: ' . TerminHoehe; $terminInhalt = formatiere_datenblatt_link( $termin ) . formatiere_jobNr_und_zeit( $termin, true ); } else { $terminHoehe = 'height: ' . TerminHoehe; $terminInhalt = formatiere_datenblatt_link( $termin ) . formatiere_jobNr_und_zeit( $termin, false ); } }

                                                                                                wahrscheinlich könnte da jetzt auch das if else weg. Aber ich trau mich schon gar nichts mehr zu fragen, ich fummel es einfach irgendwie rein und schau dass ich die Ausgabe wieder so wie früher hin bekomme.

                                                                                                Nein!

                                                                                                Die Funktion Formatiere_JobNr_und_Zeit hab ich hier gefunden.

                                                                                                In Abhängikeit davon, ob es ein Ganztagstermin (Spalte: k_ganztags) ist oder oder nicht wird die Uhrzeit mit (oder eben nicht mit) ausgegeben, Kann also sein, dass Du das übersehen hast oder dass die Testdaten das eben nicht hergeben.

                                                                                                Hier übrigens das angesprochene Auto - Nur ohne Sofa. (Keine Angst: Die Rechte am Bild habe ich höchstselbst und kann das auch beweisen)

                                                                2. Hallo Barksalot,

                                                                  Aufruf erzeuge_kalenderwochen($mysqli, $firstOfMonth, $teile25) Definition function erzeuge_kalenderwochen($firstOfMonth, $mysqli, $teile25)

                                                                  Das kann nicht funktionieren. Argumente (das, was beim Aufruf in Klammern steht) werden den Parametern (das, was in der FUNCTION-Zeile in Klammern steht) nicht per Name zugeordet, sondern nach der Position. Die Funktion möchte in $firstOfMonth den Unix-Timestamp des Monatsersten sehen, für den ein Kalender erzeugt werden soll (eine ziemlich große Zahl). Wenn Du $mysqli nach vorn ziehst, landet dieses Objekt in $firstOfMonth. Damit fängt die date-Funktion nichts an und sie mault genau deswegen 'rum: date() expects parameter 2 to be integer, object given

                                                                  Ich hatte diese Parameteranordnung GANZ BEWUSST gewählt. Aus meiner Sicht ist dieser prozedurale Code nur ein erster Schritt, irgendwann sollte das in einer Klasse verpackt werden. Und wenn es in einer Klasse ist, brauchst Du $mysqli und $teile25 nicht mehr als Parameter. Sowas wären dann private Eigenschaften der Klasse. D.h. die Parameter, die potenziell entfallen, habe ich ans Ende gesetzt.

                                                                  Ich habe das dummerweise nicht konsequent durchgehalten, kalender_termine und count_alle_kalender_termine passen nicht dazu.

                                                                  Wenn Du das nicht magst, kannst Du es gerne ändern, es muss dann nur zwischen Aufruf und Funktionsdeklaration konsistent sein.

                                                                  Das zentrale Problem ist jetzt, dass aus kalender_termine nichts herauszukommen scheint. Da sind einige Merkwürdigkeiten. Deine Aussagen legen nahe, dass dieser Code

                                                                  $datumTermine = kalender_termine($mysqli, $date, $teile25, 3); $anzTermineGesamt = count_alle_kalender_termine($mysqli, $date, $teile25); var_dump($datumTermine);

                                                                  zu dieser Ausgabe führt:

                                                                  Notice: Undefined variable: datumTermine

                                                                  Wie Regina schon sagte: Das geht nicht.

                                                                  Entweder geht kalender_termine kaputt, und dann gibt's einen fatal error mit Script-Abbruch, oder es geht nicht kaputt, dann kommt ein Wert zurück und $datumTermine ist nicht undefiniert.

                                                                  Es spukt also in deinem Source-Code, und den versuchen wir jetzt zu exorzieren.

                                                                  Bitte lösche an den Stellen, wo $datumTermine steht, alle Leerstellen zwischen $datumTermine und dem nächsten nichtleeren Zeichen. Danach kannst Du sie nach Geschmack neu einfügen. Warum? Es gibt Leerzeichenvarianten, die von PHP nicht als Leerzeichen erkannt werden, z.B. das NO-BREAK SPACE, das manche Editoren bei Shift+Space oder Ctrl+Space erzeugen. Das würde die undefinierte Variable erklären; und foreach gibt bei einer undefinierten Variablen genau deine Fehlermeldung aus. Das Forum ersetzt NBSP durch ein normales Space, deswegen kann ich das von hier aus nicht kontrollieren, was bei Dir ist.

                                                                  Wie kann das entstehen? Es gibt Editoren, die bei Shift+Space ein NBSP erzeugen. Welchen verwendest Du?

                                                                  Wenn's das nicht war, tjaaaa. Dann wird es rätselhaft.

                                                                  Rolf

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

                                                                    wenn ich jetzt var_dump($datumTermine); aufrufe erhalte ich folgendes

                                                                    array(1) { [0]=> array(0) { } }

                                                                    Bis bald!
                                                                    Bernd

                                                                    1. Hallo Barksalot,

                                                                      na immerhin mal etwas.

                                                                      • kalender_termine liefert einen Wert zurück und es gibt keine Meldung mehr über undefinierte Variablen. EXORZISMUS GELUNGEN!
                                                                      • dieser Wert hat ansatzweise die richtige Struktur (array of array)
                                                                      • das innere Array ist leer, d.h. beim Aufbau dieses inneren Arrays (was ja einen einzelnen Termin enthalten sollte) geht etwas schief.

                                                                      Siehe meine Antwort von 17:04 für weiteres.

                                                                      Rolf

                                                                      -- sumpsi - posui - clusi
                3. hi @Rolf B

                  unter Beachtung, daß die 1. KW ins vorherige Jahr gehören könnte, ergibt sich das Array über die darzustellenden Wochen wie folgt:

                  my @weeks = $fstday->kw == 52 ? (52, 1 .. $lastday->kw) : $fstday->kw == 53 ? (53, 1 .. $lastday->kw) : ($fstday->kw .. $lastday->kw);

                  Ansonsten bietet sich über alles ein Template an, der komplette Code:

                  # Template my $tt = q( KW Mo Di Mi Do Fr Sa So %loop_weeks% %kw% %1% %2% %3% %4% %5% %6% %7% %endloop% ); # Gegeben my $year = 2015, my $month = 11; # Ausführung my $fstday = Kalenderwoche->new( date => sprintf("%d.%d.%d", 1, $month, $year)); my $lastday = Kalenderwoche->new( date => sprintf("%d.%d.%d", $fstday->ultimo, $month, $year)); # Daten fürs Template bereitstellen my @stash = (); my @weeks = $fstday->kw == 52 ? (52, 1 .. $lastday->kw) : $fstday->kw == 53 ? (53, 1 .. $lastday->kw) : ($fstday->kw .. $lastday->kw); foreach my $week( @weeks ){ my %modimi = (); foreach my $wd(1..7){ if( $wd == $fstday->wd && $fstday->month == $month){ $modimi{$wd} = sprintf("%02d", $fstday->day); $fstday++; } else{ $modimi{$wd} = '--'; } } push @stash, {kw => sprintf("%02d", $week), %modimi}; } # Daten ins Template rendern print XR::xr($tt, {weeks => @stash}); KW Mo Di Mi Do Fr Sa So 44 -- -- -- -- -- -- 01 45 02 03 04 05 06 07 08 46 09 10 11 12 13 14 15 47 16 17 18 19 20 21 22 48 23 24 25 26 27 28 29 49 30 -- -- -- -- -- --

                  Und genauso kann man das natürlich auch mit PHP machen. So ist die Datumsarithmetik schön getrennt von der Darstellung. Es wäre dann nur das Template zu ändern bzw. anzupassen.

                  MfG

                  1. Hallo pl,

                    ja, hatte ich auch schon überlegt, die Termindaten pro Tag in ein Array zu setzen, unabhängig von der Formatierung. Das wäre im Sinne eines ViewModel wohl die bessere Lösung. Das hätte den Code aber noch weiter umgekrempelt. Vielleicht in einem Folgeschritt.

                    Aber erstmal müssen Jörg und ich mit Bernd die Fehler in den Basics finden.

                    Rolf

                    -- sumpsi - posui - clusi
                    1. hi @Rolf B

                      danke für Dein feedback. Ja, es gibt verschiedene Möglichkeiten, aber über die KW-Woche zu iterieren ist eine gute Idee. Zumal nur 3 Fälle für die 1. darzustellende Woche geprüft werden müssen...

                      Bei der Gelegenheit hab ich noch einen Fehler in meinem Kalendermodul gefunden 😉

                      MfG

                    2. hi @Rolf B

                      ja, hatte ich auch schon überlegt, die Termindaten pro Tag in ein Array zu setzen,

                      Auf jeden Fall. Aber wohin ich eigentlich hinauswollte: Wenn eine Monatstabelle gerendert werden soll, geht das über die Kalenderwoche wesentlich performanter als über den Tag.

                      Zum Vergleich: Über die Woche iteriert und Über den Tag iteriert

                      MfG

          2. Hallo,

            ich habe eine Frage zum Kalender. Ich habe zusammenhängende Termine, es könnte wie folgt aussehen:

            Termin 1: 01.10.2018 - 09.10.2018
            Termin 2: 01.10.2018 - 02.10.2018
            Termin 3: 01.10.2018 - 01.10.2018

            jetzt möchte ich gerne erreichen dass zusammenhängte Termine auch zusammenhängend über die Tage hinweg angezeigt werden. Am besten die Termine die über mehrere Tage gehen an erster Stelle. Lässt sich da etwas machen? Es ist derzeit sehr mühsam Termine zu verfolgen die über mehrere Tage gehen die in unterschiedlichen Zeilen angeordnet sind wenn mehrere Termine pro Tag vorliegen.

            Update 10:52 Uhr:
            Muss ich vielleicht ein weiteres Feld hinzufügen wo ich Termine die über mehrere Tage gehen einen bestimmten Wert zuordne und ich damit dann beim Auslesen das ORDER BY anpassen kann? wäre dieses vielleicht eine Möglichkeit?

            Bis bald!
            Bernd

            1. Hallo,

              ich habe eine Frage zum Kalender. Ich habe zusammenhängende Termine, es könnte wie folgt aussehen:

              Termin 1: 01.10.2018 - 09.10.2018
              Termin 2: 01.10.2018 - 02.10.2018
              Termin 3: 01.10.2018 - 01.10.2018

              jetzt möchte ich gerne erreichen dass zusammenhängte Termine auch zusammenhängend über die Tage hinweg angezeigt werden.

              Die Frage der Anordnung ist doch eher eine Designfrage. Nun, ich habe viele Jahre die Urlubsplanung gemacht. Dafür habe ich mehrere A4 Seiten zusammengeklebt, das Jahr in Tagen von links nach rechts und die Kollegen von oben nach unten.

              Tipp: Vielleicht genügt Dir ja ein kleinerer Zeitausschnitt.

              MfG

              1. Hallo pl,

                Die Frage der Anordnung ist doch eher eine Designfrage. Nun, ich habe viele Jahre die Urlubsplanung gemacht. Dafür habe ich mehrere A4 Seiten zusammengeklebt, das Jahr in Tagen von links nach rechts und die Kollegen von oben nach unten.

                wirklich nur eine Design Frage? Ich meine die Datensätze müssen doch auch irgendwie aus der Datenbank ausgelesen werden um den Zusammenhang zu gewährleisten? Ich würde die Termine schon gerne weiterhin auf meiner Monatsansicht darstellen

                Bis bald!
                Bernd

                1. Hallo Bernd,

                  das ist keine leichte Aufgabe, die Du Dir da stellst, sondern ein kniffliges Optimierungsproblem. Ich bezweifle, dass Du das rein auf DB-Ebene lösen kannst - zumindest würde ich es gar nicht erst probieren.

                  Im Prinzip klingt dein Ansatz schon ok, die längsten Termine zuerst, dann die kürzeren drum herum fummeln, und jeden so hoch oben wie möglich. Möglicherweise ist das ein zu naiver Ansatz und es gibt Datenkonstellationen, wo dadurch Müll herauskommt, aber diese Konstellationen muss man erstmal haben, bevor man sich was besseres überlegen kann. Ein kleines Brainstorming von Rolf und Herrn B. hat erstmal nichts zu Tage gefördert.

                  Mein technischer Ansatz wäre, alle Termine für den darzustellenden Zeitraum erstmal in ein Array zu laden und jedem Termin eine Anzahl Tage zuzuordnen. Das Array sortiere ich dann absteigend nach Anzahl der Tage (mit einem usort oder uasort); bei gleicher Tage-Anzahl aufsteigend nach Beginndatum. Diesen Schritt könnte man noch in der DB realisieren, wenn Du eine SQL-Expression findest die Dir bei zwei gegebenen Timestamps die Anzahl der davon berührten Kalendertage ermittelt (ein Termin vom 2.10. 23:00 bis 03.10. 01:00 müsste nach meiner Vorstellung 2 Tage ergeben. Wenn das schon in der DB klappt, dann brauchst Du dieses Array nicht, dann nimmst Du einfach Row für Row wie der fetch sie liefert und machst damit das Folgende.

                  Die sortierten Termine lädst Du Stück für Stück in ein neues Array. Pro Termin prüfst Du, wieviele andere Termine er überlappt. Und zwar wieder ohne Uhrzeit. Termin A überlappt Termin B, wenn A.Beginntag <= B.Endetag oder A.Endetag >= B.Beginntag ist. Die Anzahl der gefundenen Überlappungen plus 1 ist die Zeile, in die der Termin geschrieben werden muss. Diese Zeilennummer gilt natürlich für alle Tage, an denen der Termin relevant ist, die wird nicht pro Tag neu berechnet.

                  Rolf

                  -- sumpsi - posui - clusi
                  1. hi @Rolf B

                    Idee: Mit fortlaufenden Tagen operieren. Somit ist ein Zeitraum (z.B. ein Monat) infolge zweiter Integer Zahlen exakt beschrieben, Abfrage an Repository also von..bis.

                    Die einzelnen Termine zwischen von bis werden in eine zweckmäßige Datenstuktur gepackt, also jeder Termin ist ein Objekt und auf einen Tag kann es mehrere solche Objekte geben.

                    Dann kann man das auch darstellen und beliebige Views erzeugen (Wochensicht, Monatsicht..). Der Termin als Objekt, sowas ist problemlos anpassungsfähig, insbesondere hinsichtlich Hinzufügen weiterer Eigenschaften, angehängte Dateien usw.

                    MfG

  2. Hallo,

    vielen vielen Dank an @Rolf B und Regina Schaukrug für eure Hilfe.
    Ohne euch hätte ich es nicht hinbekommen.

    Tschüss
    Bernd

    1. Hallo Barksalot,

      d.h. es funktioniert jetzt? Sehr schön :)
      Dann haben sich deine Frustphase und unsere Mühe ja gelohnt.

      Ich hoffe, dass es für Dich nicht zu komplex war und Du ein paar Techniken mitnehmen konntest, die Dich weiterbringen.

      Rolf

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

        ja, bis jetzt kann ich keinen Fehler feststellen. Es funktioniert noch nicht 100%, hat es aber bei meiner Version auch nicht ;) Folgende ToDos stehen noch auf dem Plan:

        • Möglichkeit geben, einen Termin in einen Outlook Kalender zu übergeben
        • Möglichkeit geben, einen Termin in einen Google Kalender zu übergeben, am besten automatisch
        • Push Benachrichtigung im Browser anzeigen, dass ein Termin anstehen. Hier weiß ich nicht ob mein Webhosting dieses kann. Ein eigener Server habe ich nicht, möchte ich auch nicht, da ich diesen nicht pflegen kann.

        Was ich noch gerne hätte, um die Übersicht etwas zu behalten:

        • Hinter jedem Eintrag soll eine Checkbox sein mit "Termin erledigt" wenn ich diese anklicke soll der Termin durchgestrichen werden und in der DB ein Trag hinterlegt werden, dass dieser Termin erledigt ist. Vielleicht auch etwas leicht ausgegraut aber der Übersichtsseite.

        Keine Ahnung ob dieses alles so einfach umzusetzen ist aber ich werde mir dieses in den nächsten Tagen etwas genauer ansehen.

        Was ich noch nicht so recht verstanden habe ist folgendes:

        function kalender_termine( $mysqli, $datum, $teile25 ) { $values = $teile25; $empfaengerListe = '"' . implode( '", "', $values ) . '"'; $query = 'SELECT kt_id, kt_kalenderID, kt_datum, test, k_code, k_art, k_jobNr, k_bezeichnung, k_auto, k_farbe, k_datum_von, k_ganztags, k_von, k_bis, f_bezeichnung, f_kennzeichen, ka_farbe, kf_farbe, kf_color FROM kalender_termine LEFT JOIN kalender ON kalender.k_code = kalender_termine.kt_kalenderID LEFT JOIN fuhrpark ON fuhrpark.f_id = kalender.k_auto LEFT JOIN kalender_arten ON kalender_arten.ka_code = kalender.k_art LEFT JOIN kalender_terminfarbe ON kalender_terminfarbe.kf_farbe = kalender_arten.ka_farbe WHERE kt_datum="' . $datum . '" AND k_art IN (' . $empfaengerListe . ') ORDER by test ASC'; $Kalender_Termine = array(); if ( $result = $mysqli -> query( $query ) ) { while ( $row = $result -> fetch_assoc()) { $Kalender_Termine[] = $row; } }

        Oder zu meiner/deiner Option

        $Kalender_Termine[] = array( 'kt_id' => $kt_id, 'kt_kalenderID' => $kt_kalenderID, 'kt_datum' => $kt_datum, 'test' => $test, 'k_code' => $k_code, 'k_art' => $k_art, 'k_jobNr' => $k_jobNr, 'k_bezeichnung' => $k_bezeichnung, 'k_auto' => $k_auto, 'k_farbe' => $k_farbe, 'k_datum_von' => $k_datum_von, 'k_ganztags' => $k_ganztags, 'k_von' => $k_von, 'k_bis' => $k_bis, 'f_bezeichnung' => $f_bezeichnung, 'f_kennzeichen' => $f_kennzeichen, 'ka_farbe' => $ka_farbe, 'kf_farbe' => $kf_farbe, 'kf_color' => $kf_color );

        Wann nutzt man das eine oder das andere? Gibt es vor oder Nachteile? OK ein Vorteil ist, wenn weitere Felder in der DB hinzukommen muss ich nicht immer alles anpassen?

        Bis bald!
        Bernd

        1. Hallo Barksalot,

          der Unterschied ist, dass die alte Lösung mit data binding arbeitet, und die von Regina vorgeschlagene Lösung die "klassische" Fetch-Technik verwendet.

          Data binding sieht für jede Spalte des Ergebisses eine Variable vor, in der der Inhalt dieser Spalte nach einem fetch() bereitgestellt wird. Du musst natürlich aufpassen, dass dein bind_result genau zum SQL Statement passt. Das Binding ist Tipparbeit, du musst den bind_result-Befehl aufbauen und die gebundenen Variablen ins Ergebnisarray umkopieren. In deinem Fall ist das eigentlich nutzlos, weil deine Array-Indexe genauso heißen wie die Spalten. D.h. das Ergebnis deines Codes ist das gleiche wie ein fetch_assoc und deswegen hat Regina das auch dahin geändert.

          Binding gab es im klassischen mysql/mysqli nicht, da verwendete man fetch_row, fetch_assoc oder fetch_array, um sich die Trefferzeile als Array bereitstellen zu lassen. Unterschied zwischen den Funktionen ist, wie die Indexe des Arrays aussehen. Bei fetch_row ist es die Spaltennummer (erste Spalte ist Nr. 0), bei fetch_assoc der Spaltenname und bei fetch_array kannst Du es aussuchen (bzw. wenn Du nichts festlegst bekommst Du beides).

          "Klassisch" heißen diese Funktionen mysqli_fetch_row, etc, und bekommen ein mysqli_result Objekt als Parameter. Objektorientiert sind es Methoden des mysqli_result Objekts. mysqli_query liefert Dir ein solches Objekt; es repräsentiert das Abfrageergebnis. Wenn Du mit prepare arbeitest, erzeugt stmt->execute() ein solches Objekt. Die stmt->fetch Methode verwendet es implizit; Du kannst es Dir aber mit $stmt->get_result() auch liefern lassen und damit auf Data Binding verzichten. Du solltest versuchen, Dir das alles im mysqli-Bereich der PHP Doku durchzulesen, auch wenn deine Augen streiken. Aber ich mache noch ein Beispiel:

          Sei $sql = "SELECT A, B, C FROM SOMETABLE" das SQL und die Trefferzeile enthalte A="foo", B=17 und C="abcde".

          Das Result-Objekt bekommst Du entweder so:

          // Ohne Prepare $result = $mysqli->query($sql) if ($result === FALSE) { // Fehlerbehandlung }

          oder so:

          // Mit Prepare $stmt = $mysqli->prepare($sql); if ($stmt === FALSE) { Fehlerbehandlung } $ok = $stmt->execute(); if (!ok) { Fehlerbehandlung } $result = $stmt->get_result(); if ($result === FALSE) { Fehlerbehandlung }

          Natürlich kommt in der prepare-Variante noch ein bind_param hinzu, wenn das SQL Parameter braucht. Die Diskussion prepare vs query hatten wir schon öfter; query ist kompakter, dafür kannst Du Dir in den Fuß schießen wenn Du die Parameter unsauber ins Statement einbaust (Kontextwechsel-Problem). Bei prepare hilft Dir mysqli beim Kontextwechsel und es ist (vermutlich) effizienter, wenn Du die gleiche Query mit unterschiedlichen Parameterwerten ausführen musst. Dafür hast Du ein paar Zeilen Code mehr.

          Die Ergebnisse der fetch-Varianten unterscheiden sich dann so:

          $result->fetch_row() ARRAY( 0 => "foo", 1 => 17, 2 => "abcde" ) $result->fetch_assoc() ARRAY( "A" => "foo", "B" => 17, "C" => "abcde" ) $result->fetch_array() ARRAY( 0 => "foo", 1 => 17, 2 => "abcde", "A" => "foo", "B" => 17, "C" => "abcde" ) $result->fetch_array(MYSQLI_NUM) ARRAY( 0 => "foo", 1 => 17, 2 => "abcde" ) // wie fetch_row $result->fetch_array(MYSQLI_ASSOC) ARRAY( "A" => "foo", "B" => 17, "C" => "abcde" ) // wie fetch_assoc

          Deswegen ist dein (äh, Reginas) Code kaputtgegangen, als da noch fetch_row stand. Welche der Aufrufvarianten du nimmst, hängt von deinen Vorlieben und vom Anwendungsfall ab.

          Rolf

          -- sumpsi - posui - clusi
          1. data binding …/… "klassische" Fetch-Technik

            wenn ich nach einer ehrlichen Antwort gefragt würde, was ich vom "data binding" halte, dann wäre meine Antwort ganz klar "Regelmäßig gar nichts!"

            $result -> fetch_assoc() liefert alles, was benötigt wird. Wer unbedingt meint, dass er die Elemente seines Arrays anders benennen muss als die Spalten der Datenbank, der denkt aus meiner Sicht schon an dem Punkt etwas sehr falsches. Auch das Binden von Nicht-Arrays als Variablen ist aus meiner Sicht unnötig und sozusagen "semantisch falsch", weil mir als Progger dann der Sinnzusammenhang zwischen der Zeile einer Tabelle und den Daten in der Variable verloren geht.

            Selbst wenn ich beim Planen was falsch gemacht habe, dann kann ich andere Spaltennamen im SQL bestimmen (SELECT foo AS bar)

            $result -> fetch_row() hat aus meiner Sicht nur dann eine Berechtigung, wenn ich nur einen Wert erwarte - oder aber die Anzahl der Werte in einer Zeile nicht vorher bekannt ist (Man denke an das regelmäßig falsche SELECT * FROM ...) und ich den Spalten-Name nicht brauche. Aber selbst dann braucht man das binden nicht, im letzten Fall funktionierts nicht mal.

            aber erst:

            SELECT foo, bar from

            dann

            $stmt -> bind_result ( $foo, $bar );

            dann

            while ( $stmt -> fetch () ) { $tabelle[] = array( 'foo' => $foo, 'bar' => $bar ); }

            ist aus meiner Sicht eine enorme Verschwendung geistiger Leistung und Fingergelenkhaltbarkeit weil:

            $tabelle = array(); if ( $result = $mysqli -> query( $query ) ) { while ( $row = $result -> fetch_row()) { $tabelle[] = $row; } } else { # Fehlerbehandlung

            es mit ganz wenig Aufwand tut und keine besondere geistige Leistung erfordert.

            Die Diskussion prepare vs query hatten wir schon öfter; query ist kompakter, dafür kannst Du Dir in den Fuß schießen wenn Du die Parameter unsauber ins Statement einbaust (Kontextwechsel-Problem).

            Naja. Das Kontext-Wechsel-Problem kann man eigentlich ausschließen wenn man wie hier das Datum und die Empfängerliste vorher selbst zusammenbaut und also ausschließen kann, dass vergiftetes Zeug in den Parametern vorkommt. Selbst wenn man das nicht ausschließen kann dann gibt es das funktionierende mysqli_real_escape_string(). Das prepare lohnt eigentlich nur, wenn ich eine, bis auf die Parameter identische SQL-Abfrage mehrfach stelle, also nach dem $stmt -> prepare(…) mehrfach mit neuen Parametern versehe und jeweils abschicke.

            Es könnte hier zwar sehr gut eine solche mehrfach gestellte Abfrage geben, nur wird das durch die Funktion gerade nicht so realisiert. Dazu wäre hier ein Objekt optimal gewesen in dem $stmt isoliert ist und erhalten bleibt. (Es gänge funktional auch wenn man alle Abfragen nacheinander stellt und die Ergebnisse "per Day" in einen Array ablegt und sich dann, beim Zusammenbau des Tags, wieder herauszieht.

            Aber selbst dann könnte man sich das Stellen einer mehrfachen Abfrage schenken, weil Jahr, Tag und Monat sich auch gut in die Antwort aufnehmen lassen...

            1. Hallo Regina,

              ich bin bei meiner Bewertung etwas vom konkreten Problem abgehoben und nicht darauf, ob query oder prepare HIER die bessere Lösung ist.

              Dass man den prepare HIER ganz anders gestalten müsste, dass eine OO-Lösung hier Nutzen stiften kann, habe ich schon früher erwähnt. Dass man Kontextwechsel richtig ausführen KANN, und dass er hier nicht sonderlich schwierig ist, ist klar, aber man muss eben auf alle Feinheiten achten. Prepare schließt diese Footgun in den Schrank ein.

              Vom mysqli-Databinding halte ich auch nicht viel. Es könnte in Fällen nutzbringend sein, wo man andernfalls die Variablen aus dem Fetch-Array in Variablen umkopiert. Ich denke genau wie Du, dass das der seltenere Anwendungsfall ist. Eher wird man da noch die Billig-ORM Lösung mit fetch_object einsetzen und vielleicht sogar eine eigene Klasse verwenden (z.B. TerminView), dann kann man einige Aufgaben, die Bernd jetzt als Funktion gelöst hat, in Methoden verpacken.

              Angesichts des Umstandes dass Bernd kurz davor stand, die Brocken hin und sich selbst hinterher zu schmeißen, bin ich darauf aber nicht mehr eingegangen. Solange er nicht selbst nachhakt, würde ich es an diesem Punkt gut sein lassen.

              Rolf

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

                Solange er nicht selbst nachhakt, würde ich es an diesem Punkt gut sein lassen.

                was soll ich denn nachhaken? Derzeit läuft alles so wie ich es früher auch hatte. Meine Änderungen habe ich ja schon erwähnt, die ich im laufe der Zeit vielleicht noch einbauen werden, wenn ich es hinbekommen.

                1. was soll ich denn nachhaken?

                  Ach! Nur wegen der Theorie…

                  Derzeit läuft alles so wie ich es früher auch hatte.

                  Nönö. Wenn Du unseren Vorschlägen gefolgt bist läuft es besser. Freilich brauchst Du aber eine gute Stoppuhr um das zu merken.

                  1. Hallo Regina,

                    Freilich brauchst Du aber eine gute Stoppuhr um das zu merken.

                    Zur Laufzeit - ja.

                    Bei Programmänderungen: Hoffentlich nicht. Es sollte jetzt übersichtlicher sein, bausteinmäßiger, und damit änderungsfreundlicher. Setzt natürlich voraus, dass die Änderungen verstanden wurden 😉

                    Rolf

                    -- sumpsi - posui - clusi
                    1. Freilich brauchst Du aber eine gute Stoppuhr um das zu merken.

                      Zur Laufzeit - ja.

                      Bei Programmänderungen: Hoffentlich nicht.

                      Wieso? Die gehen doch jetzt auch viel schneller. Das bisher benötigte Paket aus 24h-Sanduhr und Strichliste tut es jedenfalls nicht mehr… ist im relevanten Minutenbereich schlicht zu ungenau.