it-swarm.com.de

So richten Sie eine PDO-Verbindung richtig ein

Von Zeit zu Zeit sehe ich Fragen zur Verbindung mit der Datenbank.
Die meisten Antworten sind nicht die Art, wie ich es mache, oder ich bekomme die Antworten vielleicht nicht richtig. Sowieso; Ich habe nie darüber nachgedacht, weil meine Arbeitsweise für mich funktioniert.

Aber hier ist ein verrückter Gedanke. Vielleicht mache ich das alles falsch, und wenn das der Fall ist; Ich würde wirklich gerne wissen, wie man mit PHP und PDO eine Verbindung zu einer MySQL-Datenbank herstellt und sie leicht zugänglich macht.

So mache ich es:

Zunächst einmal meine Dateistruktur (abgespeckt):

public_html/

* index.php  

* initialize/  
  -- load.initialize.php  
  -- configure.php  
  -- sessions.php   

index.php
Ganz oben habe ich require('initialize/load.initialize.php');

load.initialize.php  

#   site configurations
    require('configure.php');
#   connect to database
    require('root/somewhere/connect.php');  //  this file is placed outside of public_html for better security.
#   include classes
    foreach (glob('assets/classes/*.class.php') as $class_filename){
        include($class_filename);
    }
#   include functions
    foreach (glob('assets/functions/*.func.php') as $func_filename){
        include($func_filename);
    }
#   handle sessions
    require('sessions.php');

Ich weiß, es gibt eine bessere oder korrektere Möglichkeit, Klassen einzubeziehen, kann sich aber nicht daran erinnern, was es war. Ich habe noch nicht die Zeit, um nachzusehen, aber ich denke, es war etwas mit autoload.) Das...

configure.php
Hier überschreibe ich einfach einige php.ini- -Eigenschaften und nehme andere globale Konfigurationen für die Site vor

connect.php
Ich habe die Verbindung auf eine Klasse gesetzt, sodass andere Klassen erweitert diese ...

class connect_pdo
{
    protected $dbh;

    public function __construct()
    {
        try {
            $db_Host = '  ';  //  hostname
            $db_name = '  ';  //  databasename
            $db_user = '  ';  //  username
            $user_pw = '  ';  //  password

            $con = new PDO('mysql:Host='.$db_Host.'; dbname='.$db_name, $db_user, $user_pw);  
            $con->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
            $con->exec("SET CHARACTER SET utf8");  //  return all sql requests as UTF-8  
        }
        catch (PDOException $err) {  
            echo "harmless error message if the connection fails";
            $err->getMessage() . "<br/>";
            file_put_contents('PDOErrors.txt',$err, FILE_APPEND);  // write some details to an error-log outside public_html  
            die();  //  terminate connection
        }
    }

    public function dbh()
    {
        return $this->dbh;
    }
}
#   put database handler into a var for easier access
    $con = new connect_pdo();
    $con = $con->dbh();
//

Hier bin ich der Meinung, dass es Raum für massive Verbesserungen gibt, seit ich vor kurzem angefangen habe, OOP zu lernen und PDO anstelle von Mysql zu verwenden).
Also habe ich ein paar Anfänger-Tutorials verfolgt und verschiedene Sachen ausprobiert ...

sessions.php
Abgesehen von regelmäßigen Sitzungen initialisiere ich auch einige Klassen in einer Sitzung wie dieser: 

if (!isset($_SESSION['sqlQuery'])){
    session_start();
    $_SESSION['sqlQuery'] = new sqlQuery();
}

Auf diese Weise ist diese Klasse überall verfügbar. Dies ist möglicherweise keine gute Praxis (?) ...
Jedenfalls erlaubt mir dieser Ansatz von überall aus:

echo $_SESSION['sqlQuery']->getAreaName('county',9);  // outputs: Aust-Agder (the county name with that id in the database)

In meinem sqlQuery-class, der extends mein connect_pdo-class ist, habe ich eine öffentliche Funktion namens getAreaName, die die Anforderung an meine Datenbank verarbeitet.
Ziemlich ordentlich, denke ich.

Klappt wunderbar
So mache ich es im Grunde.
Wenn ich etwas aus meiner Datenbank abrufen muss, das nicht innerhalb einer Klasse liegt, mache ich einfach etwas Ähnliches:

$id = 123;

$sql = 'SELECT whatever FROM MyTable WHERE id = :id';
$qry = $con->prepare($sql);
$qry -> bindParam(':id', $id, PDO::PARAM_INT);
$qry -> execute();
$get = $qry->fetch(PDO::FETCH_ASSOC);

Da ich die Verbindung in eine Variable in connect_pdo.php gesteckt habe, beziehe ich mich nur darauf und ich kann loslegen. Es klappt. Ich bekomme meine erwarteten Ergebnisse ...

Aber ungeachtet dessen; Ich würde mich wirklich freuen, wenn ihr mir sagen könntet, ob ich hier weg bin. Was ich stattdessen tun sollte, Bereiche, die ich ändern könnte oder sollte, um Verbesserungen vorzunehmen usw. 

Ich bin gespannt zu lernen ...

87
ThomasK

Das Ziel

Meiner Ansicht nach ist Ihr Ziel in diesem Fall ein zweifaches: 

  • erstellen und verwalten Sie eine einzelne/wiederverwendbare Verbindung pro Datenbank
  • stellen Sie sicher, dass die Verbindung ordnungsgemäß eingerichtet wurde

Lösung

Ich würde empfehlen, sowohl anonyme Funktionen als auch Factory-Pattern für die PDO-Verbindung zu verwenden. Die Verwendung davon würde folgendermaßen aussehen:

$provider = function()
{
    $instance = new PDO('mysql:......;charset=utf8', 'username', 'password');
    $instance->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $instance->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
    return $instance;
};

$factory = new StructureFactory( $provider );

Dann in einer anderen Datei oder niedriger in derselben Datei:

$something = $factory->create('Something');
$foobar = $factory->create('Foobar');

Die Fabrik selbst sollte ungefähr so ​​aussehen:

class StructureFactory
{
    protected $provider = null;
    protected $connection = null;

    public function __construct( callable $provider )
    {
        $this->provider = $provider;
    }

    public function create( $name)
    {
        if ( $this->connection === null )
        {
            $this->connection = call_user_func( $this->provider );
        }
        return new $name( $this->connection );
    }

}

Auf diese Weise haben Sie eine zentralisierte Struktur, die sicherstellt, dass die Verbindung nur bei Bedarf hergestellt wird. Dies würde auch den Prozess des Komponententests und der Wartung wesentlich erleichtern.

Der Provider würde sich in diesem Fall irgendwo in der Bootstrap-Phase befinden. Dieser Ansatz würde auch einen klaren Ort angeben, an dem die Konfiguration definiert wird, die Sie für die Verbindung zur DB verwenden.

Beachten Sie, dass dies ein extrem vereinfachtes Beispiel ist. Sie können auch von den folgenden zwei Videos profitieren:

Ich würde auch dringend empfehlen, ein richtiges Tutorial über die Verwendung von PDO zu lesen (es gibt ein Protokoll mit schlechtem Tutorial online).

102
tereško

Ich würde vorschlagen, $_SESSION nicht für den globalen Zugriff auf Ihre DB-Verbindung zu verwenden.

Sie können eine der folgenden Aktionen ausführen (in der Reihenfolge schlechteste bis beste Praktiken):

  • Rufen Sie $dbh mit global $dbh in Ihren Funktionen und Klassen auf
  • Verwenden Sie eine Einzelregistrierungsdatenbank, und greifen Sie wie folgt auf den globalen Zugriff zu:

    $registry = MyRegistry::getInstance();
    $dbh = $registry->getDbh();
    
  • Injizieren Sie den Datenbank-Handler wie folgt in die Klassen, die es benötigen:

    class MyClass {
        public function __construct($dbh) { /* ... */ }
    }
    

Ich kann das letzte wärmstens empfehlen. Es ist bekannt als Abhängigkeitsinjektion (DI), Inversion of Control (IoC) oder einfach als Hollywood-Prinzip (rufen Sie uns nicht an, wir rufen Sie an).

Es ist jedoch etwas fortgeschrittener und erfordert mehr "Verkabelung" ohne Rahmen. Wenn die Abhängigkeitsinjektion für Sie zu kompliziert ist, verwenden Sie eine Einzelregisterregistrierung anstelle einer Reihe globaler Variablen.

22
Ian Unruh

Ich bin vor kurzem zu einer ähnlichen Antwort/Frage selbst gekommen. Das habe ich getan, falls jemand interessiert ist:

<?php
namespace Library;

// Wrapper for \PDO. It only creates the rather expensive instance when needed.
// Use it exactly as you'd use the normal PDO object, except for the creation.
// In that case simply do "new \Library\PDO($args);" with the normal args
class PDO
  {
  // The actual instance of PDO
  private $db;

  public function __construct() {
    $this->args = func_get_args();
    }

  public function __call($method, $args)
    {
    if (empty($this->db))
      {
      $Ref = new \ReflectionClass('\PDO');
      $this->db = $Ref->newInstanceArgs($this->args);
      }

    return call_user_func_array(array($this->db, $method), $args);
    }
  }

Um es anzurufen, müssen Sie nur diese Zeile ändern:

$DB = new \Library\PDO(/* normal arguments */);

Und den Typhinweis, wenn Sie ihn verwenden (\ Library\PDO $ DB).

Es ist der akzeptierten Antwort und der Ihrer wirklich sehr ähnlich; es hat jedoch einen bemerkenswerten Vorteil. Betrachten Sie diesen Code:

$DB = new \Library\PDO( /* args */ );

$STH = $DB->prepare("SELECT * FROM users WHERE user = ?");
$STH->execute(array(25));
$User = $STH->fetch();

Es sieht zwar wie normales PDO aus (es ändert sich nur durch \Library\), es initialisiert das Objekt jedoch erst, wenn Sie die erste Methode aufrufen, je nachdem, um welche es sich handelt. Dadurch wird es mehr optimiert, da die PDO-Objekterstellung etwas teuer ist. Es ist eine transparente Klasse, oder was sie als Ghost bezeichnet, eine Form von Lazy Loading . Sie können den $ DB als normale PDO-Instanz behandeln, weitergeben, dieselben Operationen ausführen, usw.

7
$dsn = 'mysql:Host=your_Host_name;dbname=your_db_name_here'; // define Host name and database name
    $username = 'you'; // define the username
    $pwd='your_password'; // password
    try {
        $db = new PDO($dsn, $username, $pwd);
    }
    catch (PDOException $e) {
        $error_message = $e->getMessage();
        echo "this is displayed because an error was found";
        exit();
}

oder lesen Sie auf http://ask.hcig.co.za/?p=179

0
hi-code