Delphi-PRAXiS
Seite 4 von 7   « Erste     234 56     Letzte »    

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   [PHP] Klassenstruktur für Adressdatenbank (https://www.delphipraxis.net/166235-%5Bphp%5D-klassenstruktur-fuer-adressdatenbank.html)

ibp 11. Feb 2012 14:30

AW: [PHP] Klassenstruktur für Adressdatenbank
 
Zitat:

Zitat von Luckie (Beitrag 1150285)
Zitat:

Wie wär's wenn du erstmal schaust, dass du die statischen Methoden klar machst? Wenn du magst kann ich dir heute Nachmittag ein Beispiel dazu schreiben. :)
OK. Und ich bin keine Frau, ich mag immer. ;)

5 Bit in das Chauvi Register!

Valle 11. Feb 2012 14:35

AW: [PHP] Klassenstruktur für Adressdatenbank
 
Ups, jetzt hab ich dich fast vergessen. :?

Zum mysql_select_db: Schau doch einfach selbst nach wie das geht? Wink mit Zaunpfahl.

Jedenfalls hab ich hier mal eine kleine Herausforderung für dich. Sag Bescheid wenn du etwas nicht verstehst. Der schöne Teil des Codes sind die zwei letzten Zeilen unten. Diese zeigen, wie man später mit Datenbanken (im Controller) arbeiten kann. Selbstverständlich lässt sich das alles noch erweitern. Die Save Methode ist nicht vollständig und auch nicht getestet, da ich jetzt leider weg muss. Ich wollte dir den Code nur nicht vorenthalten. :) Du brauchst mindestens PHP 5.3 für das "Late static Binding" (get_called_class).

PHP-Quellcode:
abstract class DB_Table
{

    static protected $table = NULL;

    protected $fields = array();
    protected $changed = array();
    protected $exists = false;

    public function __construct(array $fields, $exists = false)
    {
        $this->fields = $fields;
        $this->exists = $exists;
    }

    public function __get($name)
    {
        return $this->fields[$name];
    }

    public function __set($name, $value)
    {
        if ($name == "id")
            throw Exception("Cannot changed ID. Yet.");
        array_push($this->changed, $name);
        return $this->fields[$name] = $value;
    }

    public function save()
    {
        if ($this->exists and count($this->changed) > 0) {
            $sql = array();
            foreach ($this->changed as $column) {
                $sql[] = "`" . $key . "` = '" . mysqli_real_escape_string($this->fields[$column]) . "'";
            }
            $sql = "UPDATE `" . $this->table . "` SET " . implode(", ", $sql) . " WHERE `id` = " . intval($this->fields['id']);
            print($sql);
        } else {
            // TODO Insert
        }
    }

    /**
     * Returns one instance with primary key = $id
     */
   
    public static function get($id)
    {
        $class = get_called_class();

        if ($class == __CLASS__)
            throw new Exception("Cannot call get() directly.");

        $result = mysql_query("SELECT * FROM `" . $class::$table . "` WHERE `id` = " . intval($id));
        return $class::getOne($result);
    }

    protected static function getOne($result)
    {
        $class = get_called_class();

        if ($result === false)
            throw new Exception("Query faild. " . mysql_error() . " (" . mysql_errno() . ")");
        if (mysql_num_rows($result) == 0)
            throw new Exception("No object matching id " . str($id));
        if (mysql_num_rows($result) > 1)
            throw new Exception("Too many results. Please check table schema.");

        return new $class(mysql_fetch_assoc($result), true);
    }

    protected static function getMultiple($result)
    {
        $class = get_called_class();

        if ($result === false)
            throw new Exception("Query faild. " . mysql_error() . " (" . mysql_errno() . ")");
        if (mysql_num_rows($result) == 0)
            throw new Exception("No object matching id " . str($id));

        $list = array(); // TODO Verwaltungsklasse für mehrere Reihen!
        while ($row = mysql_fetch_assoc($result)) {
            $list[] = new $class($row, true);
        }
        return $list;
    }


}

class DB_Adressen extends DB_Table
{   
   
    static protected $table = 'adressen';

    public function findByName($name)
    {
        $name = mysql_real_escape_string($name);
        $result = mysql_query("SELECT * FROM adressen WHERE name = '" . $name . "'");
        return self::getMultiple($result);
    }

}

mysql_connect("127.0.0.1", "", "");
mysql_select_db("test");

var_dump(DB_Adressen::get(1));
var_dump(DB_Adressen::findByName("Puff"));
Liebe Grüße,
Valentin

Luckie 11. Feb 2012 14:50

AW: [PHP] Klassenstruktur für Adressdatenbank
 
Hm, sieht sehr gut aus. Muss ich mir nur noch mal genauer angucken. Besten Dank.

Luckie 11. Feb 2012 21:25

AW: [PHP] Klassenstruktur für Adressdatenbank
 
OK, ich glaube, ich habe es verstanden.

Nur, wie muss ich das Formular abschicken, um die Methode save() nutzen zu können? Ich gehe mal davon aus, dass die Eingabefelder genauso benannt sein müssen, wie die Felder in der Datenbank. Aber wie geht es weiter?

Valle 11. Feb 2012 21:29

AW: [PHP] Klassenstruktur für Adressdatenbank
 
Guggst du hier. ;-)

Du kannst oben auf "Diff" klicken wenn dich die genauen Unterschiede interessieren. (Auch wenn das bei mir i.M. nicht funktioniert :-? )

Edit:// Ups, ich glaube ich habe deine Frage eben missverstanden. Wenn du das per Formular machen möchtest, dann kannst du der DB_Table Klasse eine Methode "update" verpassen, welche ein assoziatives Array an Daten bekommt und entsprechend setzt. Normalerweise macht man auch für jedes Formular eine Klasse, die entsprechend von einer Basisklasse "Form" erbt. Dort definiert man die Felder des Formulars und welche Datentypen sie besitzen. Man macht dann eine Methode "validate", welche prüft ob alle Ints tatäschlich Ints sind usw.

Liebe Grüße,
Valentin

Luckie 11. Feb 2012 22:07

AW: [PHP] Klassenstruktur für Adressdatenbank
 
Hm hm, hm. Ok, machen wir langsam.

PHP-Quellcode:
public function save() {
         if ($this->exists and count($this->changed) > 0) {
            $sql = array();
            foreach ($this->changed as $column) {
               $sql[] = "`" . $key . "` = '" . mysqli_real_escape_string($this->fields[$column]) . "'";
            }
            $sql = "UPDATE `" . $this->table . "` SET " . implode(", ", $sql) . " WHERE `id` = " . intval($this->fields['id']);
            print($sql);
         } else {
            // TODO Insert
         }
      }
Also wenn ich das richtig verstehe, dann wird für jedes geänderte Feld der Schleifenrumpf aufgerufen. Die geänderten Felder kommen in ein Array (__set). OK. Das Array ist ein assoziatives Array. Der Schlüssel ist der Feldname und der Wert, die Eingabe in dem entsprechendem Edit aus dem Formular. In meinem Fall würde das Array dann alle Felder der Tabelle enthalten. Soweit richtig?

Ich müsste für jedes Eingabefeld __set aufrufen und dann save.

Mal sehen, ob ich das hinbekomme.

Valle 11. Feb 2012 23:19

AW: [PHP] Klassenstruktur für Adressdatenbank
 
Schau doch mal meinen Link an, da habe ich nochmal einiges am Code geändert.

Ansonsten ruft man nicht __set auf, sondern macht einfach
PHP-Quellcode:
$instanz->feld = "wert";
. Das ruft automatisch __set auf. :)

Liebe Grüße,
Valentin

Luckie 12. Feb 2012 10:18

AW: [PHP] Klassenstruktur für Adressdatenbank
 
Ja, habe ich schon gesehen. Da ist ja auch schon der INSERT Zweig implementiert.

Aber habe ich es richtig verstanden, wie ich die save Methode anwenden muss?

Luckie 6. Mär 2012 15:10

AW: [PHP] Klassenstruktur für Adressdatenbank
 
Ich habe noch ein Problem. Wie bekomme ich die Daten aus dem Formular in die DB_Table Klasse?

Mein Formular sieht so aus:
PHP-Quellcode:
public function showForm() {
         echo "<form action='index.php?action=save' method='GET'>\n";
            echo "<input type=\"hidden\" name=\"action\" value=\"save\">\n";
            echo "Name: <input name=\"name\" type=\"text\"></input><br>\n";
            echo "Vorname: <input name=\"vorname\" type=\"text\"></input>\n";
            echo "<br><br>\n";
            echo "<input type=\"submit\" value=\"Speichern\"></input>\n";
         echo "</form>\n";
      }
Nach dem Abschicken wird in den "save" Zweig der index.php gesprungen:
PHP-Quellcode:
case "save":
               echo "Name: ".$name;
               DB_Adressen::save();
               break;
Aber wie fülle ich jetzt das $fields Array aus meiner DB_Adressen Klasse und wie geht die Zuordnung Tabellenfeld und Wert?
PHP-Quellcode:
class DB_Adressen extends DB_Table { 
      
      static protected $table = 'adressen_data';
      
      protected $fields = array();
      protected $changed = array();
      protected $exists = false;

      public function __construct(array $fields = array(), $exists = false)
      {
         $this->fields = $fields;
         $this->exists = $exists;
      }
      
      public function __get($name)
      {
         return $this->fields[$name];
      }

      public function __set($name, $value)
      {
         if ($name == "id")
            throw Exception("Cannot change ID. Yet.");
         array_push($this->changed, $name);
         return $this->fields[$name] = $value;
      }

      public function save() {
         echo "Speichern";
         
      }

Valle 6. Mär 2012 15:32

AW: [PHP] Klassenstruktur für Adressdatenbank
 
Dafür macht man sich eine "Form" Klasse und erbt dann eine "Form_NewAddress" Klasse davon. Man könnte das dann so anwenden:

PHP-Quellcode:
if ($_SERVER['REQUEST_METHOD'] == "POST") {
    $form = new Form_NewAddress($_POST); // Formular mit Daten
    if ($form->is_valid()) { // geht interne Felder durch: is_email(...) && is_plz(...) && ...
        $new = new DB_Adressen();
        $new->set_data($form->cleaned_data); // cleaned_data: Array mit bereinigten Werten (zB "echte" Ints)
        $new->save();
    } else {
        echo $form->render(); // gibt Fehlermeldung + vorher ausgefüllte Felder aus
    }
} else {
    $form = new Form_NewAddress(); // leeres Formular
    echo $form->render();
}
Ohne mir jetzt genauer Gedanken über die Implementation gemacht zu haben, würde ich die NewAddress-Form-Klasse ungefähr so machen:

PHP-Quellcode:
class Form_NewAddress extends Form
{

    // wird von der Vaterklasse im __construct aufgerufen
    protected function init_fields()
    {
        $this->add_field("name", new FormField_VarChar(255));
        $this->add_field("email", new FormField_Email());
        $this->add_field("irgendwas_mit_regex", new FormField_Regex(".*hier kranken Regex einfügen.*"));
    }

    // Weitere Methoden werden alle geerbt. is_valid() geht die Felder durch und füllt
    // cleaned_data. render() ruft alle render() Methoden der FormField-Instanzen auf
    // die wiederum den HTML Code zurückgeben. __construct prüft speichert eventuell
    // mitgegebene Daten in raw_data. Vaterklasse sollte übrigens abstract sein.

}
Ich hoffe du verstehst was ich meine. Ansonsten sag Bescheid, dann mach ich gern ein detaillierteres Codebeispiel. :thumb:

DB_Adressen::save() macht übrigens allgemein wenig Sinn. Eine Instanz repräsentiert einen Datensatz der Tabelle. Die Klasse selbst repräsentiert die ganze Tabelle. Speichern kann man eigentlich nur einen Datensatz.

Liebe Grüße,
Valentin


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:20 Uhr.
Seite 4 von 7   « Erste     234 56     Letzte »    

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz