如何正确设置PDO连接
 有时我会看到有关连接到数据库的问题。 
 大多数答案不是我做的方式,或者我可能只是不正确地得到答案。 无论如何; 我从来没有想过,因为我这样做的方式适用于我。 
但是这是一个疯狂的想法。 也许我这样做是完全错误的,如果是这样的话; 我真的想知道如何正确连接到使用PHP和PDO的MySQL数据库,并使其易于访问。
以下是我如何做到这一点:
首先,我的文件结构(剥离) :
public_html/ * index.php * initialize/ -- load.initialize.php -- configure.php -- sessions.php   的index.php 
 在最顶层,我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'); 
  我知道有一个更好或更正确的方法来包含类,但不记得它是什么。  还没有时间来看看它,但我认为这是autoload东西。  像那样的东西… 
  的configure.php 
 在这里,我基本上只是重写一些php.ini-属性,并为网站做一些其他的全局configuration 
  connect.php 
 我把连接放到一个类中,所以其他类可以扩展这个… 
 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(); // 
  在这里,我相信自从我最近开始学习OOP,并使用PDO而不是使用mysql之后,还有很大的改进余地。 
  所以我刚刚跟着几个初学者教程,尝试了不同的东西… 
  sessions.php 
 除了处理常规会话之外,我还将一些类初始化为这样的会话: 
 if (!isset($_SESSION['sqlQuery'])){ session_start(); $_SESSION['sqlQuery'] = new sqlQuery(); } 
 这样这个class就可以到处都是。 这可能不是好的做法(?)… 
 无论如何,这是这种方法可以让我从任何地方做到这一点: 
 echo $_SESSION['sqlQuery']->getAreaName('county',9); // outputs: Aust-Agder (the county name with that id in the database) 
 在我的sqlQuery – 类中 , extends我的connect_pdo – 类 ,我有一个名为getAreaName的公共函数处理对我的数据库的请求。 
 我觉得很整齐。 
  奇迹般有效 
 所以这基本上是我如何做的。 
 另外,无论何时我需要从不在一个类中的数据库中获取某些东西,我只需要做类似如下的事情: 
 $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); 
因为我把连接放到connect_pdo.php里面的一个variables中,所以我只是提到它,我很好。 有用。 我得到了我的预期的结果…
但不pipe那个 如果你们能告诉我我是否在这里,我会很感激。 我应该做的,我可以或应该改善的地方,以改善等…
我渴望学习…
目标
正如我所看到的,你在这种情况下的目标是双重的:
- 创build并维护每个数据库的单个/可重用连接
- 确保连接已正确设置
解
我会build议使用匿名函数和工厂模式来处理PDO连接。 它的使用看起来像这样:
 $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 ); 
然后在不同的文件或更低的相同的文件中:
 $something = $factory->create('Something'); $foobar = $factory->create('Foobar'); 
工厂本身应该是这样的:
 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 ); } } 
这样可以让你有一个集中的结构,确保只在需要的时候才build立连接。 这也会使unit testing和维护的过程变得更容易。
在这种情况下的提供者将在引导阶段被find。 这种方法也会给出一个明确的位置来定义configuration,用于连接到数据库。
请记住,这是一个非常简单的例子 。 您还可以通过观看以下两个video获益:
- 全局状态和单身
- 不要找东西!
另外,我强烈推荐阅读关于使用PDO 的正确教程 (在线有错误的教程日志)。
 我build议不要使用$_SESSION全局访问你的数据库连接。 
你可以做一些事情(按照从最差到最佳的方式):
-  在函数和类中使用global $dbh访问$dbh
- 
使用一个单一的registry,并访问全局,如下所示: $registry = MyRegistry::getInstance(); $dbh = $registry->getDbh();
- 
将数据库处理程序注入到需要它的类中,如下所示: class MyClass { public function __construct($dbh) { /* ... */ } }
我会强烈推荐最后一个。 它被称为dependency injection(DI),控制反转(IoC),或简单的好莱坞原则(不要打电话给我们,我们会打电话给你)。
但是,它稍微先进一些,需要更多的“布线”而没有框架。 所以,如果dependency injection对你来说太复杂了,那么使用一个单例registry而不是一堆全局variables。
最近我自己也来了一个类似的回答/问题。 这就是我所做的,如果有人感兴趣:
 <?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); } } 
要调用它,你只需要修改这一行:
 $DB = new \Library\PDO(/* normal arguments */); 
而types暗示,如果你正在使用它(\ Library \ PDO $ DB)。
这与被接受的答案和你的答案非常相似。 然而它有一个显着的优势。 考虑这个代码:
 $DB = new \Library\PDO( /* args */ ); $STH = $DB->prepare("SELECT * FROM users WHERE user = ?"); $STH->execute(array(25)); $User = $STH->fetch(); 
 虽然它可能看起来像正常的PDO(它只是由\Library\而改变),但实际上它不会初始化对象,直到您调用第一个方法(无论哪一个)为止。 这使得它更加优化,因为PDO对象创build稍微昂贵。 这是一个透明的类,或者叫做Ghost ,一种延迟加载的forms。 您可以将$ DB视为普通的PDO实例,传递给它,执行相同的操作等。 
 $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(); }