Ankündigung

Einklappen
Keine Ankündigung bisher.

Abfragen so korrekt?

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Abfragen so korrekt?

    Hallo, ich versuche mich gerade an einer Film-Datenbank:
    Ich habe das ganze so begonnen:

    database.class.php
    PHP-Code:
    <?php

    class Database {

        private 
    $host "localhost";
        private 
    $user "user";
        private 
    $pass "password";
        private 
    $dbname "database";
        private 
    $dbh;
        private 
    $error;
        private 
    $stmt;

        public function 
    __construct() {
            
    $dsn 'mysql:host=' $this->host ';dbname=' $this->dbname;
            
    $options = array(
                
    PDO::ATTR_PERSISTENT => true,
                
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
            
    );
            try {
                
    $this->dbh = new PDO($dsn$this->user$this->pass$options);
            } catch (
    PDOException $e) {
                
    $this->error $e->getMessage();
            }
        }

        public function 
    query($query) {
            
    $this->stmt $this->dbh->prepare($query);
        }

        public function 
    bind($param$value$type NULL) {
            
    $this->stmt->bindValue($param$value$type);
            return 
    $this;
        }

        public function 
    execute() {
            return 
    $this->stmt->execute();
        }

        public function 
    resultset() {
            
    $this->execute();
            return 
    $this->stmt->fetchAll(PDO::FETCH_ASSOC);
        }

        public function 
    single() {
            
    $this->execute();
            return 
    $this->stmt->fetch(PDO::FETCH_ASSOC);
        }

        public function 
    rowCount() {
            return 
    $this->stmt->rowCount();
        }

        public function 
    lastInsertId() {
            return 
    $this->dbh->lastInsertId();
        }

    }
    index.php
    PHP-Code:
    <?php
    include 'include/header.php';
    include 
    'include/database.class.php';

    $database = new Database();

    if (!isset(
    $_GET['id'])) {
        
    $database->query("SELECT id, title, teaser, cover FROM entrys");
        
    $stmt $database->resultset();
        foreach (
    $stmt as $row) {
            
    ?>
            <h1><a href="?id=<?php echo $row['id'?>"><?php echo $row['title'?></a></h1>
            <div classs="row">
                <div class="col-md-3">
                    <img src="<?php echo $row['cover'?>" alt ="<?php echo $row['title'?>" title="<?php echo $row['title'?>" class="img-responsive">
                </div>
                <div class="col-md-9">
                    <p><?php echo $row['teaser'?></p>
                </div>
            </div>
            <?php
        
    }
    } else {
        
    $database->query("SELECT id, title, text, date, genre, cover FROM entrys WHERE id = :id");
        
    $database->bind(':id'$_GET['id']);
        
    $stmt $database->resultset();

        foreach (
    $stmt as $row) {
            
    ?>
            <h1><?php echo $row['title'?> <small>(<?php echo date('Y'strtotime($row['date'])) ?>)</small></h1>
            <div classs="row">
                <div class="col-md-6">
                    <img src="<?php echo $row['cover'?>" alt ="<?php echo $row['title'?>" title="<?php echo $row['title'?> " class="img-responsive">
                </div>
                <div class="col-md-6">
                    <p><?php echo $row['text'?></p>
                    <p><?php echo $row['genre'?></p>
                    <a href="javascript:history.back()" class="btn btn-success">Zurück</a>
                </div>
            </div>
            <?php
        
    }
    }

    include 
    'include/footer.php';
    Ich habe eine Datenbankklasse, die ich noch erweitern werde.
    In der Index wird vorerst nur eine Liste angezeigt, die weitere Infos beim Klick auf den Titel liefert.

    Ich wollte nun wissen, ob ich so weitermachen kann oder ob ich einen Fehler habe, welcher mir später das Leben schwer machen wird.

    MfG

  • #2
    Was bringt denn switch(TRUE) ? Also eigentlich solltest du da immer beim selben case-Fall rauskommen, was den Switch dann absolut überflüssig macht ^^

    Warum deklarierst du deine Konstanten nicht in der Klasse? Sondern außerhalb und greifst dann in deiner Klasse darauf zu? Ziemlich unsinnig. Aber ansonsten, sieht es ganz gut (bin aber nur drüber geflogen)
    - Laravel

    Kommentar


    • #3
      Mir wurde hier mal gesagt, dass die Konstanten in der Klasse zu deklarieren ziemlich sinnlos ist
      Ich habe es aber mal abgeändert und auch den switch rausgenommen.

      Kommentar


      • #4
        PHP-Code:
            public function bind($param$value) {
                
        $this->stmt->bindValue($param$value$type);
            } 
        Das wird auch nicht klappen.

        BindValue kann keine Variablen Binden, nur "puren Text". Zudem übergibst du keinen $type an deine Methode, $type in bindValue abzufragen ist also nutzlos. Das was du suchst sollte so aussehn:

        PHP-Code:
        public function bind($key$value$type NULL)
        {
            
        $this->stmt->bindParam($key$value$type);

            return 
        $this;

        - Laravel

        Kommentar


        • #5
          Habs angepasst. funktioniert. wieso ist es sinnvoll, $type = NULL mit anzugeben?

          Kommentar


          • #6
            Wenn du $type = NULL mit übergibst hat $type den Standardwert NULL, heißt also du kannst beim Aufruf der Methode auch nur die ersten zwei Parameter übergeben, der dritte ist optional. Immer wenn man einen optionalen Wert an eine Methode übergeben will muss ihm ein Standardwert zugewiesen werden.

            Alle Parameter die keinen Standardwert besitzen werden von PHP auch verlangt, heißt wenn du keinen Standardwert gesetzt hast, aber nichts an deine Methode übergibst ist PHP dir böse.
            - Laravel

            Kommentar


            • #7
              btw., die Zugangsdaten im Startpost sehen mir nicht gefaked aus, das solltest Du ändern!
              Competence-Center -> Enjoy the Informatrix
              PHProcks!Einsteiger freundliche TutorialsPreComposed Packages

              Kommentar


              • #8
                Zitat von Arne Drews Beitrag anzeigen
                btw., die Zugangsdaten im Startpost sehen mir nicht gefaked aus, das solltest Du ändern!
                $host = "localhost";
                SCNR
                PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

                Kommentar


                • #9
                  Schon klar, würde trotzdem persönliche Daten nicht posten.
                  Competence-Center -> Enjoy the Informatrix
                  PHProcks!Einsteiger freundliche TutorialsPreComposed Packages

                  Kommentar


                  • #10
                    Zitat von tomahawk Beitrag anzeigen
                    Ich wollte nun wissen, ob ich so weitermachen kann oder ob ich einen Fehler habe, welcher mir später das Leben schwer machen wird.
                    Ich denke du wirst früher oder später Probleme bekommen, wenn Du ds Projekt nicht von Anfang an nach dem MVC-Muster umsetzt, da es sicherlich weiter wachsen soll.

                    Kommentar


                    • #11
                      Ich bevorzuge statt MVC eher treffendere Muster wie ADR oder DCI aber sonst kann ich dem uneingeschränkt zustimmen.

                      Kommentar


                      • #12
                        Zitat von tera3yte Beitrag anzeigen
                        BindValue kann keine Variablen Binden, nur "puren Text".
                        Da hst du wohl irgendwas falsch verstanden.

                        bindValue bindet den Wert der Variable zum Zeitpunkt des Aufrufs von BindValue.
                        Der Parameter kann sowohl eine Variable als auch eine konstanter Wert sein.

                        bindParam bindet die Referenz einer Variablen. Es wird letzlich der Wert der Variablen verarbeitet, welcher zum Zeitpunkt des Aufrufs von von execute() vorliegt.
                        Ich kann zum Beispiel die gebundene Variable einfach immer neu belegen und execute() aufrufen, ohne immer bindParam aufzurufen.

                        LG jspit

                        Kommentar


                        • #13
                          Zitat von jspit Beitrag anzeigen
                          Da hst du wohl irgendwas falsch verstanden.

                          bindValue bindet den Wert der Variable zum Zeitpunkt des Aufrufs von BindValue.
                          Der Parameter kann sowohl eine Variable als auch eine konstanter Wert sein.

                          bindParam bindet die Referenz einer Variablen. Es wird letzlich der Wert der Variablen verarbeitet, welcher zum Zeitpunkt des Aufrufs von von execute() vorliegt.
                          Ich kann zum Beispiel die gebundene Variable einfach immer neu belegen und execute() aufrufen, ohne immer bindParam aufzurufen.

                          LG jspit
                          Hab das wie ich es geschrieben habe vor kurzen irgendwo gelesen, hatte mich auch sehr irritiert welchen Sinn das hat, hab aber nicht weiter nachgeforscht, aber danke für den Hinweis.
                          - Laravel

                          Kommentar


                          • #14
                            Die Datenbank-Klasse macht so kein Sinn. Du verrennst dich damit nur. Die ersten Fehler sind schon eingebaut, die nächsten werden folgen und nachdem du die hälfte der PDO Funktionen übernommen hast, wirst du vielleicht merken, dass das alles Misst ist.

                            Das was die Klasse jetzt kann, kann PDO auch von Haus aus.

                            Dein Code:
                            PHP-Code:
                            $database = new Database();
                            $database->query("SELECT id, title, text, date, genre, cover FROM entrys WHERE id = :id");
                            $database->bind(':id'$_GET['id']);
                            $stmt $database->resultset();

                            foreach (
                            $stmt as $row) {



                            PDO:
                            PHP-Code:
                            $pdo = new pdo();
                            $stmt $pdo->prepare("SELECT id, title, text, date, genre, cover FROM entrys WHERE id = :id");
                            $stmt->bindValue(':id'$_GET['id']);
                            $stmt->execute()

                            foreach(
                            $stmt as $row) {



                            oder:

                            PHP-Code:
                            $pdo = new pdo();
                            $stmt $pdo->prepare("SELECT id, title, text, date, genre, cover FROM entrys WHERE id = :id");
                            $stmt->execute(array(':id'$_GET['id']));

                            foreach(
                            $stmt as $row) {



                            Gravierender Unterschied, nicht? Es ist mit PDO sogar weniger Code und das Kind hat den richtigen Namen. Ein Prepared Statment ist aus technischer Sicht ebend was anderes als ein Query. Für dich ist es vielleicht klar, aber für andere Entwickler ist das verwirrend und erfordert nur unnötiges umdenken.
                            Ich find das Interface von PDO an manchen stellen auch nicht schön, aber man kann sich damit arrangieren. Im Fall der Fälle kann auch PDO und PDOStatment erweitert werden. Z.B. solche Dinge wie dein single() lassen sich damit umsetzen. Das Erweitern hat den Vorteil du bleibst kombatibel zu PDO und musst nicht 99% sinnlosen Wrapper Code schreiben.

                            PHP-Code:
                            class myPDO extends PDO {

                                public function 
                            __construct(...) {
                                    
                            $dsn '...';

                                    
                            $options = array(
                                        
                            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
                                        
                            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
                                        
                            PDO::ATTR_STATEMENT_CLASS => array('myPDOStatement')
                                    );

                                    
                            parent::__construct($dsn, ..., ..., $options);
                                }

                            }

                            class 
                            myPDOStatement extends PDOStatement {
                                public function 
                            executeSingle($input_parameters null) {
                                    
                            $this->execute($input_parameters);

                                    return 
                            $this->fetch();
                                }

                            }

                            //anwendung
                            $pdo = new myPDO();
                            $stmt $pdo->prepare("SELECT id, title, text, date, genre, cover FROM entrys WHERE id = :id");
                            $daten $stmt->executeSingle(array(':id'$_GET['id']));

                            var_dump($daten); //<- der erste Datensatz 

                            Und nochmal zu den oben gennanten Fehlern (auch wenn ich ein Teil schon angeschnitten habe):
                            -Verbindungsdaten in der Klasse
                            -das try catch beim Verbindungsaufbau ist einfach nur falsch
                            -damit inkonsistente Fehlerbehandlung
                            -du machst rot zu blau (query <-> prepare)
                            -du kannst nur ein Prepared Statment zur selben Zeit nutzen

                            Fünf Fehler bei Code der nur minimal Mehrwert bringt. Verrennen...

                            Kommentar


                            • #15
                              Zitat von erc Beitrag anzeigen
                              Das Erweitern hat den Vorteil du bleibst kombatibel zu PDO und musst nicht 99% sinnlosen Wrapper Code schreiben.
                              Zustimmung und das obige unterstreiche ich nochmal.

                              Auch auf die Gefahr hin, das dies hier übers Ziel hinausgeht, einige Ergänzungen/Anmerkungen.

                              Alternativ für die Klasse den gleichen Parametersatz wie für PDO verwenden:
                              PHP-Code:
                                public function __construct($dsn=null$user=null$pass=null$options = array()){
                                  
                                  
                              parent::__construct($dsn$user$pass$options);
                                  
                              // :
                                  
                                  //array($this) sind die Parameter, welche dem Konstruktor von PDOdbStatement übergeben werden
                                  
                              $this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('myPDOStatement', array($this)));
                                } 
                              Das Attribut PDO::ATTR_STATEMENT_CLASS kann so wie oben gesetzt werden, wenn in myPDOStatement auch die PDO-Instanz verfügbar sein soll und damit der Zugriff auf Attribute etc.
                              PHP-Code:
                              class myPDOStatement extends PDOStatement{
                                private 
                              $pdo null;
                                  
                                protected function 
                              __construct(PDO $pdo) {
                                  
                              $this->pdo $pdo;
                                } 
                              LG jspit

                              Kommentar

                              Lädt...
                              X