hui, dann mal stück für stück ^^
1) das <> ist im endeffekt nur ne andere schreibweise für !=. auf deutsch: wenn beide verschieden sind

wenn du dir die dokumentation zu date anschaust, dann stellste ja fest, dass date('Y'); die jahreszahl zurückgibt. was ich hier geprüft habe ist schlicht und ergreifend, ob die jahreszahl des wochenanfangs dem des wochenendes entspricht. weil? jahreswechsel

eine woche schert sich nicht um nen glatten jahresabschluss ^^ zum bsp ist 2013 zu 2014 der wochenanfang (wie immer ein montag) der 30.12. gewesen. das wochenende hingegen war der 05.01. - nun gibts 2 einfache möglichkeiten: ich lasse die jahreszahl immer weg, dann stände hier "30.12. - 05.01.", oder ich zeige sie immer an. dann wäre das ein "30.12.2013 - 05.01.2014" .> finde ich schonmal deutlich besser. jedoch hat man eben bei der 2. anzeige das ganze jahr über dann 2mal 2014 stehn. die nächste woche gleich sähe in dem format so aus: "06.01.2014 - 12.01.2014". sicherlich richtig, aber ich finds halt störend. daher hab ich das über diese if-else gelöst gehabt. sind die jahreszahlen verschieden, zeige beide an, ansonsten nur die hintere. so steht mit diesem konstruckt beim jahreswechsel also immernoch "30.12.2013 - 05.01.2014", bei der darauffolgenden woche aber nur noch eine gekürzte fassung: "06.01. - 12.01.2014"
also als fazit: reine optik ^^
2 überspringe ich mal fix, das mach ich am ende...
3) tID und pID sind unsere aliasnamen ausm sql-string

da steht nachm select irgendwo was ala "t.ID AS tID" und "p.ID AS pID". deswegen nutze ich sie ja hauptsächlich, da man in php leider sonst probleme bekommt. beide spalten heißen ID - wie greift man nun auf die gewünschte zu - hatte ich ja schonmal lang und breit erwähnt. data, desc, time... sind schlicht selbstgewählte schlüssel für die arrays.
4) wegen dem sinn von ->... du fragst hier sicherlich per fetch_object ab. das sagts dir doch schon. OBJECT! ^^ was ist ein objekt? eine instanz(-variable) einer klasse. mit -> greifst du nun eben auf die klassen-variablen zu

würdest du fetch_assoc nehmen (was ein assoziatives array erstellt), dann hast du eben ein array und kein objekt, daher ist die zugriffsmethode auch anders. jut, wieso manchmal aus der db und manchmal aus der variable? das is eigentlich völlig bumms. hier isses nu so gelöst, dass NUR das aus der db bezogen wird, was so im code noch nich bekannt ist. die ip adresse wird nie gespeichert und im code ermittelt. der username wird per formular übergeben und in $username gespeichert. genau nach diesem wird in der db gesucht. die db wird dir also nie was anderes als usernamen zurückliefern, wie das was eh in der $username variable steht. wie gesagt -> es is völlig egal welchen wert du nimmst, sind eh die gleichen.
2) sow, jetzt dazu...
grundproblem für uns war doch deine wochenansicht. also prinzipiell ne schöne sache, umsetzungstechnisch aber eben verzwickt. wir speichern die daten ja nicht wochenweise, sondern die zeiten (die einzelnen tage) für sich. und zu allem überfluss noch in 2 verschiedenen tabellen (projektdaten und zeiten getrennt). nun haben wir zu EINEM projekt (eine zeile aus projekte) bis zu 7 daten (7 zeilen aus zeiten) die in EINE tabellenzeile zusammengefasst werden müssen. ich hab hier also einen "zeilen-zusammen-sammler" gebaut. eben einen "row-collector" ^^
unser großer sql-string bewirkt ja nun folgendes: zu jeder zeit, kopiert er vorne dran quasi noch die projektdaten (mal arg bildlich gesprochen, ob vorn oder hinten is bugi). unsere ergebniszeilen sehen also grob runtergerissen so aus:
((projekt-daten #1) (zeit-daten #1))
((projekt-daten #1) (zeit-daten #2))
((projekt-daten #1) (zeit-daten #3))
((projekt-daten #2) (zeit-daten #4))
...
hier haben wir also 3 verschiedene zeitdaten die immer die selben projektdaten "vorn dran" haben. in jedem durchgang von while ($row = mysqli_fetch_assoc($db_erg)) {} haben wir also immer ALLE daten. eigentlich sieht es ja noch nen stück verzwickter aus ^^ weil ein projekt ist ja eine tätigkeit/produkt kombination. also in projekt 1 UND projekt 2 kann die tätigkeit dennoch die selbe sein, nur das produkt ist verschieden. aber dieses verschiedene produkt macht es eben auch zu verschiedenen projekten.
in der letzten zeile siehst du bt den "maximal-ausbau" des mehrdimensionalen arrays. ich kann dir die struktur ja mal versuchen aufzuschlüsseln:
Code:
row_collector
|
|_ (tätigkeiten) // -> per id der tätigkeit (also für jede tätigkeit wird hier ein arrayfeld angelegt. bei 3 tätigkeiten, hat row_collector also 3 elemente.
|
|_ 'taet' // -> hier wird der klartext für die tätigkeit gespeichert. also die tätigkeit mit der id 1 heißt im klartext "hochschlafen" :ugly:
|_ 'data' // -> das wird ein weiteres subarray und hierrein sollen dann die produkte
|
|_ (produkte) // -> wieder wie bei tätigkeiten, nur diesmal für alle produkte, die mit dieser tätigkeit in zusammenhang stehen (also nicht stehen können, sondern tatsächlich stehen)
|
|_ 'prod' // -> wieder der name des produkts als klartext
|_ 'desc' // -> die projektbeschreibung (genau hier ist es nämlich das projekt, weil eben produkt UND tätigkeit bekannt sind - beide kombiniert -> projekt. also auch die beschr speichern)
|_ 'user' // -> den kerl halt auch speichern, ist glaube der klartext, weil das wäre zum ausgeben gedacht (sofern mans braucht - admin, wenn er die daten mehrerer user abfragt)
|_ 'time' // -> und hier nun schlussendlich das letzte subarray für unsere (bis zu 7) zeiten die zu diesem projekt in dieser woche gehören.
|
|_ (timestamp) = zeit // -> schlussendlich wird die eigentliche zeit mit dem timestamp des tages noch im array abgelegt
so erkennt mans wohl am ehesten, was ich da für eine datenstruktur aufgebaut hab ^^
kleine randbemerkung: sollte man mehrere wochen anzeigen wollen, müsste man bei 'time' ansetzen und die struktur hier weiter verfeinern. statt time dann ein week und gespeichert werden dann nicht die einzelnen zeiten, sondern weitere subarrays, die per kw als key gespeichert werden (die kw bekommt man ja easy aus dem timestamp des tages). innerhalb des kw-key-array-elements würde dann wieder das row datum = row zeit kommen. auf 'time' als zwischenkey kann man hier dann getrost verzichten. aber wie gesagt, das ist nur eine randbemerkung für zukünftige ausbau maßnahmen ^^
so, was wird innerhalb der while-schleife nun gemacht? es wird IMMER die zeit gespeichert. und zwar nach $row_collector[$row['tID']]['data'][$row['pID']]['time'][$row['Datum']] = $row['Zeit']; was für probleme treten da höchstwarscheinlich auf? nuja, index-fehler noch und nöcher

wir müssen also VORHER dafür sorgen, dass die ganzen indexe auch existieren. dazu sind die if's da. wenn der erste schritt garnich existiert, also die tätigkeit noch garnich angelegt ist, dann tu eben dies -> leg die tätigkeit an. wir erinnern uns an mein (projekt) (zeiten) konstrukt da. wobei projekt ja wie gesagt aus tätigkeit und id besteht. es kann also durchaus sein, dass bei einem weiteren durchlauf die selbe tätigkeit kommt, dann wäre dieser erste schritt schon gesetzt und diese erste if würde geskipped werden. ändert sich die tätigkeit aber, wird sie ggf wieder neu angelegt (also ein row_collector[2] angehängt meinetwegen). zeitgleich werden noch die grunddaten gespeichert - hier eben der klartext-name.
in der 2. if wird dann eben auf das produkt geprüft. mehrere zeiten können zum selben produkt der selben tätigkeit gehören. gibts dieses produkt für diese tätigkeit noch nicht, wird es hiermit angelegt und gleichzeitig wieder mit den anderen daten gefüttert. da haben wir dann also ein row_collector[2]['data'][1] (also tätigkeit mit id 2 und produkt mit id 1).
genau JETZT ist sichergestellt, dass die benötigte struktur für den letzten befehl auch wirklich vorhanden ist. row-tID ist vorhanden, data wurde da gleich mit angelegt. row-pID gibts auch und auch hier wurde time gleich mit angelegt. und genau an dieses ...time-(sub)array hängen wir nun unser timestamp = zeit an.
weitere randnotiz: für den ausbau auf mehrere wochen müsste eine 3. if angefügt werden. nach der 2. if erstellt man aus dem aktuellen datum (row[datum]) per date('W', datum); die KW und fragt in besagter 3. if dann einfach ab, ob es ...[week][KW] schon gibt. wenn nicht, wird es angelegt und als weiteres subarray gebastelt. man bedenke: week ersetzt in diesem falle time ^^ die letzte zeile müsste dann nur noch wie folgt abgeändert werden. aus ...[time][timestamp] = zeit; wird dann eben ein ...[week][KW][timestamp] = zeit;
zum abschließenden verständnis: du hast insofern recht, dass es nicht eindimensional ist. tatsächlich hast du am ende ein *zähl* 5-dimensionales array (mit der optionalen week erweiterung sogar 6 ^^).