[Apache, phpmyadmin, html, PHP, ...] Datenbank mit webbasiertem Zugriff erstellen

  • Ersteller Ersteller boss3D
  • Erstellt am Erstellt am
Warum bindest du Formular.php denn überhaupt ein wenn du exportieren willst? oder anders gefragt was hat Formular.php mit Export.php zu tun?
 
wochenanfangs-timestamp als bsp. wenn man in auswerten.php sich zu einer anderen kalenderwoche bewegt, wie die aktuelle...
ach, als bsp:
jetzt grad haben wir kw31, ich will mir die kw30 anschauen und als xls exportieren lassen
-> mit formular.php werden die hiddenfields mit den daten zur kw30 ausgewertet und die timestamps korrekt berechnet, mit denen die sql-anfrage gefüttert wird um die zeiten zu filtern (eben nur zeiten aus der gewünschten woche ausgeben).
-> ohne kann man auf auswerten.php sonstwas für ne woche einstellen, er wird IMMER nur den default (aktuelle woche) ausgeben

wegen dem fehlenden user:
- eigentlich passiert das "wieder aufnehmen" der session in der config.php -> hier sollte dann auch der username gesetzt werden (müsste was ala if isset session ip sein). also eigentlich sollte der auch ohne login.php bekannt sein *grübel*

wegen dem td...
also grundsätzlich soll es so funktionieren:
er ließt erstmal alle spalten-werte einer tabellenzeile (also quasi den zellenwert - spalte/zeile kombiniert ergibt ne tabellen zelle -> ein <td> -> $td als varname ^^) ein und wenn er die hat, gibt er sie aus. weil eben nicht alle tage eine zeit haben und somit manche td[]'s ungesetzt wären, baut er diese "" werte rein - also rein vom prinzip her sollte es keine ungesetzten td's geben *grübel* jedenfalls wird dann am ende einfach das td-array per festem index durchlaufen um es auszugeben. wieso fester index (anstelle von foreach)? wenn ich sage td = array, dann td[2] = 2; und td[1] = 1; dann spielt hier die reihenfolge der erstellung eine rolle (array ist intern glaube eher eine liste). gebe ich das per foreach aus, so wird das array in der reihenfolge der erstellung ausgegeben -> 2 1. da ich aber 1 2 als ausgabe möchte, muss ichs per festem index machen.

das problem hatte ich ursprünglich, weil ich die tätigkeit, dann die beschreibung und DANN erst das produkt ins td gespeichert hatte. somit hätten wir bei ner foreach ausgabe die falsche reihenfolge gehabt (tatigkeit, beschreibung, produkt). im jetzigen stand sollte es auch so gehen. aber is eh nur ne seiten notiz.

poste mir bitte nochmal den row-collector codeteil. btw: wieso is beim exportieren immernoch das td zeugs drin? dachte das macht nur probleme?
 
Trotzdem braucht man Formular.php nicht für den Export.

1. Du befindest dich "auf" Formular.php und navigierst zur passenden Woche.
2. Du klickst auf den Button EXPORT STARTEN (Du befindest dich ja schon am richtigen Ort und kannst die benötigten Daten daher an Export.php übergeben)
3. Im Hintergrund wird nur die Datei Export.PHP aufgerufen, die die Daten von der vorherigen Seite übergeben bekommt. Als Ergebnis bekommst du dann einen Download der DB der aktuellen Kalenderwoche/des Users als .xls
4. Export.php leitet dich im Anschluss (automatisch) zurück auf Formular.php in der Woche in der du dich befunden hast.

Oder habe ich irgendwas übersehen?
 
Den Offset-Fehler verursacht diese Schleife in export.php:
PHP:
for ($i = 0; $i < count($td); $i++) {
    echo '    <td>'.$td[$i].'</td>';
}
Aber da kann ich mir selbst nicht helfen, weil die von DarkMo stammt und ich keinen blassen Schimmer habe, was die macht. Irgendwie Tage zählen?! Deswegen kriege ich wahrscheinlich auch zuwenige angezeigt?

Da bist du auf der richtigen Spur.
So funktioniert for: Zuerst wird der erste Befehl in Klammern ($i = 0) ausgeführt, $i enthält also zunächst 0. Dann läuft es nach dem Prinzip: "Mache alles was zwischen den geschweiften Klammern {} steht solange, wie die Bedingungen (in diesem Fall $i < count($td)) erfüllt ist, also so lange wie der Wert in $i kleiner ist als count($td).
Nach jedem Durchlauf wird das $i++; ausgeführt, was nichts anderes bedeutet als $i = $i + 1;, das heißt nach jedem Durchlauf wird $i eins mehr.
count() kannst du im Handbuch nachschlagen, es zählt etwas (allermeistens, wie auch in diesem Fall, die Anzahl der Elemente in einem Array).
Also auf deutsch:
1. Setze $i auf 0.
2. So lange $i kleiner ist, als die Anzahl der Elemente im Array $td, gib folgendes aus: '<td>'.$td[$i].'</td>'.
3. Erhöhe nach der Ausgabe $i um eins.

Jetzt stellt sich die Frage, warum $td[3] nicht gesetzt ist.
Hier sollte das gesetzt werden:
PHP:
if (isset($row_collector[$taet_id]['data'][$prod_id]['time'][$ts])) {
   $td[$i+3] = $row_collector[$taet_id]['data'][$prod_id]['time'][$ts];
}
Es wird aber nur dann gesetzt, wenn $row_collector[$taet_id]['data'][$prod_id]['time'][$ts] auch gesetzt ist (if(isset(...), isset() findest du im Handbuch). Ein Vorschlag wäre folgende Änderung:
PHP:
if (isset($row_collector[$taet_id]['data'][$prod_id]['time'][$ts])) {
   $td[$i+3] = $row_collector[$taet_id]['data'][$prod_id]['time'][$ts];
} else $td[$i+3] = '';


EDIT: Was den Usernamen betrifft, kann es sein, dass die Variable $user und nicht $username heißen müsste? So sieht das zumindest in dem Code, den ich hier vorliegen habe aus.
 
ich weis leider nich genau, wie das dann tatsächlich abläuft. wenn dem so wäre jops. weil das wäre mein weitergehender gedanke gewesen: völlige entkopplung der export.php als eigenständige "seite" die man über target="_blank" aufruft, alles an daten per get oder so mitgibt (username und timestamps - wobei das auch nen sicherheitsrisiko is *grübel*) und dort rödeln lässt. aber wenn das eh die "aufrufende" seite garnich ändert/neu lädt, is ja gut. dann haste recht. ich habs halt selber noch nich getestet und mir vorgestellt, dass der browser die seite neulädt, man dieses excelfile sieht und speichern kann und dann aber nirgends mehr zurück kommt >< hab mir das schon reichlich unschön vorgestellt.
 
ich weis leider nich genau, wie das dann tatsächlich abläuft. wenn dem so wäre jops. weil das wäre mein weitergehender gedanke gewesen: völlige entkopplung der export.php als eigenständige "seite" die man über target="_blank" aufruft, alles an daten per get oder so mitgibt (username und timestamps - wobei das auch nen sicherheitsrisiko is *grübel*) und dort rödeln lässt. aber wenn das eh die "aufrufende" seite garnich ändert/neu lädt, is ja gut. dann haste recht. ich habs halt selber noch nich getestet und mir vorgestellt, dass der browser die seite neulädt, man dieses excelfile sieht und speichern kann und dann aber nirgends mehr zurück kommt >< hab mir das schon reichlich unschön vorgestellt.


edit: ah thx ben ^^ hast recht!
dieser lange kryptische wert fragt ab, ob der gewünschte tag einen wert hat, dann bekommt td diesen wert. allerdings bekommt er im fehlerfale eben keinen, is richtrig. deine lösung stimmt also. und genau hier kann man auch wegen dem datums-fehler ansetzen:
Code:
if (isset($row_collector[$taet_id]['data'][$prod_id]['time'][$ts])) {
   $td[$i+3] = [COLOR="red"]str_replace('.', ',', $row_collector[$taet_id]['data'][$prod_id]['time'][$ts][COLOR="red"]); // ersetze . durch ,
} else $td[$i+3] = '';

edit: ach damn, sollte nen edit werden ><
 
Wie ne Schleife funktioniert, weiß ich schon ... ;)
Aber das essentielle, wie das mit dem td[] läuft, habt ihr ja auch erklärt. Danke.
Das hier hätte mir schon gereicht:
dieser lange kryptische wert fragt ab, ob der gewünschte tag einen wert hat

Damit bleibt nur noch der &username-"Fehler". Vielleicht lässt sich's wirklich über die SESSION richten, muss ich gleich ausprobieren.

Und dann hätte wir noch "03. Mai" statt bspw. 3.5 h ... tja, K. A. Vermutlich macht Excel selbst das?! Eigentlich hätte ich aber gedacht, dass bei unserer "Schummelei" nach wie vor die Website selbst exportiert wird, und da stimmt's ja auch?!

[EDIT]
Ach, das letzte hattest du auch schon. Stimmt jetzt. :)
--------------

Was mache ich jetzt bis 16:00? Irgendwelche Vorschläge? $salt per Zufallszahlengenerator erstellen wäre vielleicht noch interessant. Das schaue ich mir an ...
Ah ja, $username nicht vergessen.
 
Zuletzt bearbeitet:
Damit bleibt nur noch der &username-"Fehler". Vielleicht lässt sich's wirklich über die SESSION richten, muss ich gleich ausprobieren.
wie gesagt, eigentlich sollte bei der config.php wo er nach der session fragt bei einer erfolgreichen aufnahme der existierenden session doch auch den usernamen wieder aus der session holen.
also bei btnLog in formular.php wird bei erfolgreichem login doch $_SESSION['name'] = $username; gespeichert (also sinngemäß, weis jetz ned, ob er den post-wert nimmt oder so) und darauf folgend wird in der config.php eben auf diese session geprüft und dann gesagt $username = $_SESSION['name']; is natürlich blöde, wenn man nen timeout hat ^^ als müsste man ggf die index.php nochmal anpassen (für genau diesen fall):
Code:
<?php
    session_start();
    session_regenerate_id();

    include('config.php');
    include('formular.php');

    [COLOR="blue"][B]if(isset($_POST['export'])[COLOR="red"] and isset($_SESSION['name'])) {
        include('export.php');
    } else {[/B]        include('html_header.php');

        if (!isset($_SESSION['name'])) {
            if (isset($_POST['btnRegForm']) or $section == "register") {
                include('registrieren.php');
            } else {
                include('login.html');
            }
        } else {
            if (isset($_POST['auswerten']) or $section == "output") {
                include('auswerten.php');
            } elseif (isset($_POST['auswertenadmin']) or $section == "output_admin") {
                include('auswerten2.php');
            } elseif (isset($_POST['export'])) {
                unset($_POST['auswerten']);
                unset($_POST['auswertenadmin']);
                include('export.php');
            } else {
                include('projektzeiterfassung.php');
            }
        }
    
        include('html_footer.php');
    [B][COLOR="blue"]}[/B]
hier das rote noch anfügen. dann sollte er die export nur in eingeloggtem zustand "betreten".


Und dann hätte wir noch "03. Mai" statt bspw. 3.5 h ... tja, K. A. Vermutlich macht Excel selbst das?!
genau meine vermutung (der erkennt 3.5 eben als den dritten fünften -> autoumwandlung zu nem datum. daher auch mein verunglückter edit zur beachtung ;) das rot markierte (also äh im post über deinem, 2 vor dem hier ^^). probier das mal bitte. dann steht da nämlich nich mehr 3.5 sondern 3,5.
 
^^ Deine Änderung + das hier funktioniert:
PHP:
header("Content-Disposition: attachment; filename='".$_SESSION['name']."'.xls");
Zum anderen, siehe mein EDIT im Vorposting. ;)
 
du kanst ja versuchen, die änderungen hier (vergessenes td[i+3] = '';) in die auswerten .php zu übertragen, damit könnte eventuell auch da nen fehler weniger sein. oder das mit dem salt ^^ für jeden user in der db-tabelle noch die salt spalte erstellt in die du den individuellen salt speichern kannst und ab dafür. wie das mit dem zufallsgenerieren geht... am besten mal googlen ^^
 
Wenn du dich fragst, was du bis 16 Uhr machen kannst: Testen, testen, testen!

Zum Beispiel:
- Was passiert, wenn man sich vertippt? (Zum Beispiel einen Buchstaben zwischen die Zeiten haut)
- Läuft es auch, wenn mehrere Leute gleichzeitig dran arbeiten (zugegeben nicht ganz einfach zu testen)?
- Sind alle Exporte und Ausgaben absolut korrekt? Keine verrutschten Zeilen oder so?
- Funktionieren ALLE Buttons, das heißt auch ggf. vorhandene Zurück-Buttons?
- Wie sieht es mit Rechtschreibfehlern in Texten (Fehlermeldungen, Buttonbeschriftungen, Tabellenüberschriften) aus? Dem Programm sind die zwar wurscht, aber sie werfen ggf. ein schlechtes Licht auf dich
- Läuft es auch in unterschiedlichen Browsern gut? Ist vielleicht momentan nicht relevant, weil alle in der Firma den gleichen nehmen, aber was wenn in ein paar Monaten beschlossen wird "Wir wechseln alle Systeme aus obskurem Grund zu Browser X"?
- Ebenfalls eine Überlegung: Frage einen Kollegen von dir mit schwacher Sehkraft, ob Schriftgrößen usw. für ihn in Ordnung sind
 
^^ Jup. Habe bereits einige falsche $titel gefunden. Oder vielleicht hatte DarkMo es so auch einfach "schöner" gefunden, aber ich hab's jetzt so angepasst, wie ich es "logisch" finde.

Ich schaue noch weiter ...

BTW: Nur mal so aus Interesse, weil ich mich schon seit Wochen frage ...
Ist es irgendwie "gefährlich", "variablensparend" zu sagen:
PHP:
$row = mysqli_fetch_object(mysqli_query($mysqli, "SELECT * FROM user WHERE name='".$username."'"));
Bzw. funktioniert sowas überhaupt?
Was ich auch ein paar mal gemacht habe:
PHP:
if (mysqli_query())
^^ "Böse"?
 
rein theoretisch sollte nichts dagegen sprechen. is nur doof, wenn du die ergebnisse der einzelschritte mehrfach benötigst ^^ zudem erhöhen (ordentliche) variablen(namen) durchaus die lesbarkeit/verständlichkeit des codes.
 
PHP:
$row = mysqli_fetch_object(mysqli_query($mysqli, "SELECT * FROM user WHERE name='".$username."'"));

Vom Prinzip funktioniert das schon, es ist aber m.E. einfach unübersichtlich. Die meisten Leute fangen irgendwann an Ihren Code nach einem bestimmten Schema aufzubauen. Ich verwende z.B. bei den Datenbankabfragen grundsätzlich PDO mit prepared Statements.

Das hat dann zur Folge das du ein und dieselbe "Abfrage" immer wieder verwerten kannst. Denn du sagst nur noch "Setze bitte Variable xy anstelle des Platzhalters ein". Du hast also ein "Grundgerüst" das du nur noch mit neuen Daten füttern musst.

Irgendwann schreibst du also keinen "neuen" Code mehr sondern kopierst nur jede menge bereits vorhandene Codestücke und sagst Ihm "nutze bitte variable xy" ;)
 
Prepared Statements sind toll. Wiederverwendbar, schneller und vor allem sicherer, da automatisch escaped wird. Kannst dich beim nächsten Projekt ja da mal einlesen.

EDIT: Und das hier
PHP:
$row = mysqli_fetch_object(mysqli_query($mysqli, "SELECT * FROM user WHERE name='".$username."'"));

ist keine gute Idee. Denn mysqli_query gibt im Fehlerfall false zurück. Das führt dann zu einer Fehlermeldung bei mysqli_fetch_object
 
wie darf man sich das eigentlich vorstellen? mal ganz naiv gesagt sowas hier:
PHP:
function sql($select, $from, $where) {
  return mysqli_query($mysqli, "SELECT ".$select." FROM ".$from." WHERE ".$where."';");
}
sql("*", "user", "name='".$var."'");
sql("id", "zeiten", "datum='".$time."'");

wie gesagt, als naive sehr grobe lösung ^^ weil an sowas hatte ich auch schon öfter mal gearbietet (in klassenform dann), allerdings bekam ich keine gescheite abstraktion/verallgemeinerung hin, da sich sql befehle halt doch sehr individuell bauen lassen ^^
 
Ich würde mir sowas nicht selbst bauen. Sondern PDO und Prepared Statements verwenden.

EDIT: Kann beispielsweise so aussehen:

PHP:
<?php
// Läd einen Benutzer mit einer bestimmten E-Mail-Adresse aus der Datenbank und zeigt seinen Namen an.

class User {
   /**
    * User-ID
    * @var integer
    */
   private $id;

   /**
    * E-Mail
    * @var string
    */
   private $email;

   /**
    * Benutzername
    * @var string
    */
   private $name;

   /**
    * Liefert ein User-Objekt anhand der E-Mail-Adresse zurück
    * @param PDO $database Datenbankverbindung
    * @param string $email E-Mail-Adresse
    * @return User
    */
   public static function getByEmail(PDO $database, $email) {
      $statement = $db->prepare('SELECT `user` WHERE `email`=:email');
      $statement->bindValue(':email',$email,PDO::PARAM_STR);
      if($statement->execute()) {
         return $statement->fetchObject();
      }
      throw new Exception('Benutzer konnte nicht aus der Datenbank gelesen werden.');
   }

   /**
    * @param string $key
    */
   public function __get($key) {
      switch($key) {
         case 'email':
         case 'id':
         case 'name':
            return $this->$key;
      }
   }
}

function logError(Exception $exception) {
   $error = 'Ein Fehler ist aufgetreten: '.$exception->getMessage().' in Zeile '.$exception->getLine().' in Datei '.$exception->getFile();
   print($error);
}

try {
   $database = new PDO('mysql:dbname=testdb;host=127.0.0.1', 'testuser', 'testpasswort');
} catch(PDOException $exception) {
   logError($exception);
}

try {
   $myUser = User::getByEmail($database, 'franz@example.example');
} catch(Exception $exception) {
   logError($exception);
}

require_once('html_header.php');
print('<p>Der Name des Benutzers mit der gewählten E-Mail-Adresse lautet: ');
print(htmlspecialchars($myUser->name, ENT_HTML5));
print('</p>');
require_once('html_footer.php');

Um den Query selbst, also in meinem Beispiel das 'SELECT `user` WHERE `email`=:email' zu bauen, würde ich keine Abstraktion vornehmen, außer man schreibt Code der auf verschiedenen DBMS laufen muss.
 
Zuletzt bearbeitet:
im produktiven einsatz eventuell, joa. aber ich hab immer ein ganz großes problem: ich will alles mal selber gemacht haben :P siehe mein ogl engine projekt ^^ jeder sagt immer "nimm doch ne fertig engine", aber das is doch öde hoch 3. klar, damit bekommt man schneller bessere ergebnisse, aber das bringt mir ja nix >< ich will wissen, wie das geht und es selber mal machen :D

aber gut, wir werden ot.
 
Als kleines Abstraktes Code Beispiel:

PHP:
$value = "name";
$sql = "user";
$key = "id";
$key_2 = "password"; 

$query = $db->prepare('SELECT ´$value´ FROM ´$sql´ WHERE ´$key´ = ? AND ´$key_2´ = ?');
$array = array($id, $password);
$query->execute($array);

Das wäre ein Beispiel für Key Binding.
 
asö, der baut also aus dem where gedöhnse ein array und setzt da dann die werte ein... aber das is ja nich sehr weit entfernt von meiner naiven lösung ^^ und wenn ich mir das hier: PHP: MySQL (PDO) - Manual so ansehe... schön is was anderes. total unleserlich :/
 
Zurück