Beiträge von cottton

    Nutze $result = $sth->fetchAll()

    und dann:

    SQL
    SELECT* FROM 'Databasename'

    Sollte eher so aussehen

    SQL
    SELECT* FROM `Databasename`


    BTW: variablen gehören nicht in die Query.

    Wenn Du unbedingt den Table per var so angeben musst,

    dann bitte mit Whitelist.


    EDIT: whitelist bsp

    Passwörter werden NIEMALS in Klartext gespeichert!

    Sieh Dir das hier an: Loginpasswort richtig hashen - password_hash() & password_verify()


    Ich empfehle Die wirklich PDO statt mysqli zu nuten.

    Das ist mMn einfacher und besser documentiert.

    PDO: https://www.php.net/manual/de/book.pdo.php


    Nutze niemals Variablen in der sql-query! (egal ob mysqli oder PDO).

    Stichwort: "SQL-Injection" (google).


    Zum Ablauf: hier mal ein Rohes Bsp. mit Comments

    1st: Such mal im Netz nach "SQL-Injection". Dabei geht es um Sicherheit.

    Nutze Prepared Statements: https://www.php.net/manual/de/pdo.prepared-statements.php

    Nutze nicht ->query().


    ---

    Du hast 2 Abschnitte:

    - $s3->putObject() , was wohl ein Upload zu Amazon ist

    - INSERT INTO ..., was Dir die Infos zu dem File in Deine db schreibt


    Du kannst den Ablauf (in diesem Fall) umdrehen.

    Was mir als erstes auffällt:

    PHP
    for ($j=1; $j <= $anzahlzeilen; $j++) {
        echo "<button class='tablinks' onclick='wohnungtab(event, '$j')'>Wohnung $j</button>\n";
    }

    die Anführungsstriche.

    Code
    onclick='
        wohnungtab(
            event, 
            '$j' <-------------
        )
    '

    ergibt

    HTML
    onclick='wohnungtab(event, '1')'

    sollte aber zB

    HTML
    onclick='wohnungtab(event, 1)'
    <-- oder -->
    onclick='wohnungtab(event, "1")'
    <-- oder -->
    onclick='wohnungtab(event, \'1\')'
    <-- ungetested =) -->


    Sonst kann ich auch keinen Fehler sehen.

    Stichwort: SQL-Injection


    ->query()würde ich an Deiner Stelle gleich wieder vergessen.


    Nutze prepared statements: https://www.php.net/manual/de/pdo.prepared-statements.php


    PHP
    $dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass);
    // user in users? tabelle sollte `user` heißen, und das feld `name`. Also `user`.`name`
    $stmt = $dbh->prepare("SELECT * FROM `users` where `user` = :uname;");
    $stmt->execute(['uname' => $uname]);
    // siehe https://www.php.net/manual/de/pdostatement.fetch.php 
    // um rows zu ziehen (fetch)

    Eine andere Möglichkeit wird es nicht geben,

    Bestimmte Werte (wie zb die post max size usw) können nur aus der ini kommen.

    Das script läuft bereits und PHP hat schon mit den Werten "gearbeitet".


    Hier schreibt jemand per .htaccess könnte es gehen: https://stackoverflow.com/a/2773543/3411766


    Du kannst auf jeden Fall die Werte lesen.

    Lass Dir doch mal ausgeben, was die MAX-Werte sind.


    Falls Du nicht an die ini ran kommst,

    dann wäre der nächste Schritt um das Problem relativ schnell zu lösen: den Upload (die Datei) aufteilen.

    DUPLICATE - das heißt, dass ein Feld UNIQUE ist|war.


    Aber ohne genauer Fehlermeldung, kann man nur raten.

    Und ein SHOW CREATE TABLE `my_tbl_name` wäre auch nicht verkehrt.


    Ein FK kann n mal vorkommen, solange er keinen UNIQUE INDEX bekommt.

    FK "sagt nur", dass es in der Haupttabelle einen Eintrag mit der Value in der betreffenden Zeile geben muss.


    Im Bsp hat user mit id 1 drei Einträge - also 3 Adressen.

    User 2 nur eine.

    User 3 (noch) keine.


    Mit einem Foreign Key auf user_id wird es nicht möglich sein,

    in tbl user_address eine Zeile mit user_id 4 einzutragen.

    Denn es gibt keinen user mit id 5 in der Tabelle user.

    Ohne den Code, oder was er macht, angesehen zu haben


    Du nutzt eine Variable $New in der Funktion, die nicht existiert (in dieser Funktion --also in diesem Kontext).


    Der Aufruf passiert wohl hier:

    Code
    $New = new ClassProveContakt2();
    $New -> tabelle();

    Ein Fix wäre, das Object $New beim Funktionsaufruf mitzugeben:

    Ändere die Funktion - sie bekommt einen Parameter

    Code
    function tabelle($New) {
        $sb =$New->getMessages();
        // ...
    }
    // oder 
    // function tabelle(ClassProveContakt2 $New) {...}
    // oder (falls es eine abstract class gibt)
    // function tabelle(AbstractClassProveContakt $New) {...} 
    // oder (falls es ein interface gibt)
    // function tabelle(SoUndSoInterface $New) {...}


    Und den Aufruf:

    Code
    $New = new ClassProveContakt2();
    $New -> tabelle($New);

    Sollen User getracked werden, die registriert sind, oder alle User?

    Wenn alle, dann brauchst Du einen Browser-Fingerprint (Hab mich lange nicht mehr damit beschäftigt. Aber such mal im Netz).

    Anhand von dem Fingerprint (was ja am Ende ein Hash ist)

    kannst Du dann pro User n Einträge seines Browsers ect anlegen.


    Bsp.:

    Bei jedem Seitenaufruf prüfst Du, ob der Fingerprint in `anon_user` schon existiert - sonst anlegen.

    Bei jedem Seitenaufruf prüfst Du, ob der Browser in `browser` schon existiert - sonst anlegen.

    ---

    Jetzt könntest Du bei jedem Seitenaufruf in `anon_user_browser` eine neue Zeile einfügen.

    Dann hättest Du eine genaue Übersicht, welcher user mit welchem Browser reinkam.

    ABER das solltet Du nicht!

    Bei einem Angriff bei dem Deine Seite sehr oft aufgerufen wird, ist die Tabelle schnell voll.


    Du könntest das Ganze jetzt auf "pro Minute" oder "pro Stunde" runterdrücken.

    Aber das bedeutet (noch) mehr Aufwand.


    Wenn der Aufwand egal ist, dann:

    So, nu hättest Du also schon mal die Tabellen mit dem Browser und den Usern up-to-date.

    Geht evtl auch nocht sinnvoller.


    Du kannst ja jetzt aber nicht einfach immer wieder eine Zeile in `anon_user_browser` einfügen.

    Das erste, was mir da einfällt: Du brauchst es sicher nicht Sekundengenau.

    Also kannst Du das created_at schon mal runterdrücken auf "Jahr-Monat-Tag Stunde-Minute" (Y-m-d H:i).

    created_at könnte man dann auch umbenennen in ~"interval".


    Dazu kommt jetzt noch ein Feld `count`.

    Das Ziel:

    gibt es zu der momentanen Minute schon einen Eintrag, dann update den count +1.

    sonst insert new row mit count 1.


    Ob das Ganze jetzt Sinn macht (Aufwand<=>Nutzen), weiß ich nicht.

    Außerdem schiebst du Daten in die Datenbank, ohne diese zu escapen

    Falsche Wortwahl und|oder Du hast da evtl. auch was falsch verstanden.

    XSS passiert bei der Ausgabe (Browser).

    Hier ist aber schlimmer, dass er Userdaten direkt in eine SQL Query packt. Das schreit nach SQL-Injections.


    Daten gehören nicht escaped in die db. Aber es sollte auf keinen Fall eine Query "zusammengebastelt" werden.


    ado683 Nutze mysqli_ (oder PDO) mit Prepared Statements https://www.php.net/manual/de/…t.prepared-statements.php .

    Und htmlspecialchars() um die Daten auszugeben https://www.php.net/manual/de/function.htmlspecialchars.php .

    Keine Ausnahmen!


    Nutze === statt == .


    Was zu Hölle ist das: $_SESSION["password"] ?

    Ich hoffe, Du speicherst nicht wirklich pws in der Session. Die landen ungehasht und unverschlüsselt in Dateien auf Deinem Server (default in /tmp/).


    Auch das hier geht gar nicht: $sqlab .= " password = '" . $_POST[ "passwordUser" ] . "',";

    Passwörter gehören gehasht in die db!

    Nutze password_hash() und pasword_verify(). Siehe Loginpasswort richtig hashen - password_hash() & password_verify() .


    ---

    Um doppelte Einträge zu vermeiden, sollte (wie Du schon sagtest) ein unique index genutzt werden.

    Damit man nicht jedes mal in den SQL Fehler rennt (duplicate ...), sollte man vor dem Update ein SELECT ausführen.

    Wird zB der Name gefunden, dann existiert er offensichtlich und man kann einen Fehler ausgeben.

    Naja, Du sendest ja die Form ab, um den User zu bearbeiten -

    dann musst Du schon mitgeben, wen Du bearbeiten willst.


    $dsatz['id'] hast Du noch vom letzen Loop. Und da Du prüfst, ob es nur einen gibt, kannst Du diesen (last) User nutzen.

    Könnte man aber auch schöner aufbauen =)


    EDIT: nutze htmlspecialchars() um Ausgaben zu maskieren!

    EDIT2: Du könntest die ID auch per GET in der URL migeben. Also dann nicht mehr als POST hidden field.

    Ein Increment Script|Tool schreiben ist spannend, weil Du zB beachten musst,

    dass es gleichzeitige Zugriffe auf die Datenbank gibt.


    Mal angenommen Du hast eine normale Website mit Kunden.

    Jeder Kunde bekommt eine Kundennummer - in etwa: T-0001  (T hat hier keine Bedeutung. Soll nur zeigen, dass es einen Prefix geben können muss).


    Zwei Kd kommen gleichzeitig auf Deine Seite und registrieren sich.

    Nun musste Du sicherstellen, dass die Nummer einmalig bleibt.

    Dass machst Du als erstes hart über einen uidx (unique index) in der Datenbank.

    Es ist jetzt also schon mal nicht möglich, die gleiche Nummer "ausversehen" zu speichern.


    Wie stellst Du nun sicher, dass Du eine eeinzigartige Nummer bekommst?

    Ich gehe im Bsp nur von einer Nummer aus - ohne Prefix.

    Code
     
    // pseudocode
    // kunde A registriert sich:
    lastNumber = SELECT MAX(`number`) FROM `increment`; // die größte (zu letzt erstellte) nummber laden
    newNumber = lastNumber + 1; // eine neue nummer für den neuen kd
    
    // neue nummer für den kd einfügen
    INSERT INTO `increment` SET `number` = :new_number; // usw - zB per PHP PDO ...


    Soweit ... easy?

    Nope.

    Der gleiche Ablauf jetzt mit einem dicken fetten Haken:

    Mal angenommen Du hattest als letzte Nummer die 5 in der db,

    dann würdest Du für Kd A auf 6 hochzählen.

    Da aber - bevor Du Kd A gespeichert hast - Kd B sich auch registrieren will,

    bekommst Du für Kd B auch die 6.


    Ich hoffe, ich konnte es einigermaßen verdeutlichen.


    Was kann man da machen?

    Antwort: Die Datenbank hält die Nummer, also zählt die Datenbank die Nummer hoch. Nicht etwa das PHP Script.


    Bsp:

    Per PHP erste Query abschicken, um die Nummer zu erhöhen

    und die neue Nummer in eine Session Variable ablegen (denn UPDATE gibt uns keine Daten zurück):

    SQL
    UPDATE `incremnt` SET `number` = @next_session := `number` + 1;

    Jetzt eine zweite Abfrage, um die Session Variable zu lesen:

    SQL
    SELECT @next_session;


    Ich hab das Problem (umfangreicher natürlich) für meinen Arbeitgeber gelöst.

    Kann aber den fertigen Code nicht posten (klar).


    Aber aus der docu:


    Das war jetzt nur ein einfaches Beispiel.

    Wenn es nun aber noch mehrere Nummern (increments) geben soll - zB für user, invoice, creditmemo, ... - dann brauchst Du:

    - einen Prefix (zB O-xxx für Order, I-xxx für Invoice, ...)

    - im besten Fall eine Tabelle für alle increments

    - options wie zB Länge


    So hättest Du dann eine Tabelle für mehrere increments.

    Code
    beispiele:
    O-00054         prefix: O-    "current" or last_increment": 54    length: 7
    C-0421          prefix: C-    "current" or last_increment": 421   length: 6
    K-0000004631    prefix: K-    "current" or last_increment": 4631  length: 12


    Spannend =)

    ----


    Über Transactions: was @m.scatello meinte.

    Was in dem Link aber per SQL gemacht wird (START TRANSACTION, COMMIT und ROLLBACK) wird dann aber besser per PHP gesteuert.

    Siehe: https://www.php.net/manual/de/pdo.begintransaction.php

    Die Befehle wie zB "START TRANSACTION" übernimmt dann PDO für Dich.

    mit "mehrfach: nein" meinte er,

    dass es für diesen einen user (mit ID x) keine Mehrfachdaten gibt. Also kein Details Table.


    im prinzip habe ich schon bissl zeit, denn ich bin "nur" praktikant und will es vernünftig machen, da dies mein projekt für die IHK ist.

    Na dann ordentlich =)

    Und Du kannst es ja Stück für Stück durchgehen.





    Würde erstal mit dem (logisch) user tbl anfangen,

    dann den address tbl.

    Dann hast Du schon mal ne Basis.

    user.increment (Kundennummer) ist ein spannendes Thema. aber Dazu findest Du recht viel im Netz =)


    Wichtig: egal wie viele Tabellen Du am Ende nutzt - INSERT eines neuen Nutzers (und "größere" UPDATEs) immer per TRANSACTION.

    Yap, was m.scatello sagt.

    Im Prinzip kann man es ja schon lesen, ob es eine extra Tabelle geben wird.


    Z.B. "Kommentare" - Mehrzahl. Also viele :)


    Die erste Fragen sind aber immer:

    - wie schnell muss es fertig sein

    - wie viele Einträge werden erwartet


    Man könnte ja ein richtig schönes System aufbauen. Allerdings musste ich lernen, dass man in keine Zeit für schönen Code hat (weil es Dir keiner bezahlt :D ).


    Bsp:

    Ein Ansprechparter ist ein user.

    Er bekommt eine Rolle als Ansrechpartner.

    Er kann mehrere andere user als Kunden betreuen.

    Er kann mehrere Addressen haben.

    Er kann mehrere Telefonnummern haben.

    (...)


    Hier im Bsp wäre es schön, wenn man viele viele Detail-Tabellen hätte.

    Code
    tbl user                main table
    tbl user_role           1:n (user:user_role)
    tbl user_address        1:n
    tbl user_telefon        1:n

    Usw.


    Muss es also schnell gehen, dann bau Dir erstmal ein funktionierendes System.

    Aber immer im Hinterkopf, dass Du hier und da module relativ einfach erweitrn kannst.


    Beisp.: addresse erstmal direkt in die user table.

    Beim Laden des users dann aber immer eine Methode (function|class|model|helper) benutzen.

    Sollte man dann doch mehrere Addressen benötigen,

    dann kann man die neue Tabelle erstellen, die Daten rüber kopieren, und die Methode zum Laden erweitern (zB per JOIN).

    Nehmen wir an, wir haben eine php welche verschiedene Aufgaben im gleichem Themenbereich erledigt. Um herauszufinden, welche Aufgabe erledigt werden muss, werden post Variablen per AJAX übermittelt. Nun brauche ich die Datei

    Welche Datei?


    Fals Daten gemeint ist, dann verstehe ich das so:

    Kann ich aber nicht empfehlen.

    Was auch immer in der 2ten (b.php) PHP-Datei gemacht werden soll,

    sollte besser in eine Funktion (Helper, ...) gepackt werden und per Parameter aufgerufen werden: