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 = 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");
$timestamp = get_anzeigemonat_timestamp();
$showYear = date('Y', $timestamp);
$showMonth = date('m', $timestamp);
$html_title = sprintf("%04d / %02d", $showYear, $showMonth);
$nextMonth = date('Y-m', mktime(0, 0, 0, $showMonth+1, 1, $showYear));
$prevMonth = date('Y-m', mktime(0, 0, 0, $showMonth-1, 1, $showYear));
$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.
function get_anzeigemonat_timestamp() {
$ym = filter_input(INPUT_GET, "ym",
FILTER_VALIDATE_REGEXP,
[ 'options' => [ 'regexp'=>'/\d{4}-\d{1,2}/' ] ]);
if (is_null($ym) || $ym === false)
{
$ym = date('Y-m');
}
$parts = explode("-", $ym);
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!
function erzeuge_kalenderwochen($firstOfMonth, $mysqli, $teile25)
{
$thisMonth = date("Y-m", $firstOfMonth);
$showYear = intval(date('Y', $firstOfMonth));
$showMonth = intval(date('m', $firstOfMonth));
$weekDayBeforeFirst = (6 + intval(date('w', $firstOfMonth))) % 7;
$day = 1 - $weekDayBeforeFirst;
$today = date('Y-m-d', time());
$day_count = intval(date('t', $firstOfMonth));
$weeks = [];
while ($day <= $day_count)
{
$weekNr = date('W', mktime(0,0,0,$showMonth, $day, $showYear));
$weekParts = [ "<td class='kw'>$weekNr</td>" ];
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.
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);
$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