如何正确设置PDO连接

Tho*_*asK 91 php mysql sql pdo class

我不时会看到有关连接数据库的问题.
大多数答案不是我这样做的方式,或者我可能没有正确得到答案.无论如何; 我从来没有想过这个,因为我这样做对我有用.

但这是一个疯狂的想法; 也许我这样做是错的,如果是这样的话; 我真的想知道如何使用PHP和PDO正确连接到MySQL数据库并使其易于访问.

我是这样做的:

首先,这是我的文件结构(剥离):

public_html/

* index.php  

* initialize/  
  -- load.initialize.php  
  -- configure.php  
  -- sessions.php   
Run Code Online (Sandbox Code Playgroud)

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');
Run Code Online (Sandbox Code Playgroud)

我知道有更好或更正确的方法来包含类,但不记得它是什么.还没有时间去研究它,但我认为这是有道理的autoload.类似的东西......

configure.php
这里我基本上只是覆盖一些php.ini -properties并为该站点做一些其他的全局配置

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();
//
Run Code Online (Sandbox Code Playgroud)

在这里,我相信自从我最近开始学习OOP,并使用PDO而不是mysql以来,有大量改进的空间.
所以我只是按照了几个初学者的教程,尝试了不同的东西......

sessions.php
除了处理常规会话之外,我还将一些类初始化为这样的会话:

if (!isset($_SESSION['sqlQuery'])){
    session_start();
    $_SESSION['sqlQuery'] = new sqlQuery();
}
Run Code Online (Sandbox Code Playgroud)

通过这种方式,这个类可以在任何地方使用.这可能不是一个好习惯(?)......
无论如何,这就是这种方法允许我从各处做的事情:

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

在我的sqlQuery- 一流的,这extendsconnect_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);
Run Code Online (Sandbox Code Playgroud)

因为我把连接放在connect_pdo.php里面的一个变量中,所以我只是引用它而且我很高兴.有用.我得到了预期的结果......

但不管怎样; 如果你们能告诉我,如果我离开这里,我真的很感激.我应该做些什么,我可以或应该改变的领域等......

我渴望学习......

ter*_*ško 103

目标

在我看来,你在这种情况下的目标是双重的:

  • 为每个数据库创建和维护单个/可重用连接
  • 确保已正确设置连接

我建议使用匿名函数和工厂模式来处理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 );
Run Code Online (Sandbox Code Playgroud)

然后在同一文件中的不同文件或更低文件中:

$something = $factory->create('Something');
$foobar = $factory->create('Foobar');
Run Code Online (Sandbox Code Playgroud)

工厂本身应该是这样的:

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 );
    }

}
Run Code Online (Sandbox Code Playgroud)

这种方式可以让您拥有一个集中式结构,确保只在需要时才创建连接.它还可以使单元测试和维护过程更加容易.

在这种情况下,提供者将在引导阶段的某处找到.此方法还将提供一个明确的位置,用于定义用于连接到DB的配置.

请记住,这是一个非常简化的示例.您还可以观看以下两个视频:

此外,我强烈建议您阅读有关PDO使用的正确教程(在线有一个糟糕的教程日志).

  • @thelolcat我同意你的看法.它*或多或少是相同的答案.那就是如果你没有看到它完全不同的事实. (5认同)
  • 甚至PHP5.3也接近EOL.过时的PHP版本的大多数网站实际上只是Wordpress的廉价托管.根据我的估计,5.3之前的环境对专业发展的影响(它们有点受益于这样的片段)可以忽略不计. (3认同)
  • 这是一个旧的答案,但是是一个不错的答案-并且在最后是指向Mysql pdo的链接 (2认同)

小智 23

我建议不要$_SESSION全局访问您的数据库连接.

您可以执行以下操作之一(按最差到最佳操作顺序):

我强烈推荐最后一个.它被称为依赖注入(DI),控制反转(IoC),或简称好莱坞原则(不要打电话给我们,我们会打电话给你).

但是,它更先进,需要更多的"布线"而没有框架.因此,如果依赖注入过于复杂,请使用单例注册表而不是一堆全局变量.


Fra*_*cia 7

我最近自己找到了一个类似的答案/问题.这就是我所做的,如果有人有兴趣:

<?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);
    }
  }
Run Code Online (Sandbox Code Playgroud)

要调用它,您只需要修改此行:

$DB = new \Library\PDO(/* normal arguments */);
Run Code Online (Sandbox Code Playgroud)

如果你使用它来打字(<Library\PDO $ DB).

它与你接受的答案和你的答案非常相似; 但它有一个显着的优势.考虑以下代码:

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

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

虽然它可能看起来像普通的PDO(它\Library\只会改变它),但它实际上不会初始化对象,直到你调用第一个方法,无论它是哪个.这使得它更加优化,因为PDO对象创建稍微昂贵.它是一个透明的类,或者它叫做Ghost,一种懒惰加载形式.您可以将$ DB视为普通的PDO实例,传递它,执行相同的操作等.