首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何正确设置PDO连接

如何正确设置PDO连接
EN

Stack Overflow用户
提问于 2012-07-07 04:37:42
回答 5查看 92.7K关注 0票数 93

我不时地看到有关连接到数据库的问题。

大多数答案都不是我这样做的,或者我可能就是得不到正确的答案。不管怎样,我从来没有想过它,因为我做它的方式对我来说是有效的。

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

我是这样做的:

首先,这是我的文件结构(精简)

代码语言:javascript
复制
public_html/

* index.php  

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

index.php

在最上面,我有require('initialize/load.initialize.php');

load.initialize.php

代码语言:javascript
复制
#   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-properties,并为站点做了一些其他的全局配置

connect.php

我已经将连接放到了一个类上,这样其他类就可以扩展这个类……

代码语言:javascript
复制
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

除了处理常规会话,我还将一些类初始化为会话,如下所示:

代码语言:javascript
复制
if (!isset($_SESSION['sqlQuery'])){
    session_start();
    $_SESSION['sqlQuery'] = new sqlQuery();
}

这样,这个类就可以在任何地方使用了。这可能不是好的做法(?)...

无论如何,这就是这种方法允许我从任何地方做的事情:

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

在我的sqlQuery-class ( extends我的connect_pdo-class )中,我有一个名为getAreaName的公共函数,它处理对数据库的请求。

我觉得很整洁。

的工作方式就像魅力

所以我基本上就是这么做的。

此外,每当我需要从数据库中获取不在类中的东西时,我只需执行类似的操作:

代码语言:javascript
复制
$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中的一个变量中,所以我只需要引用它就可以了。它起作用了。我得到了我想要的结果...

但不管怎样,如果你们能告诉我我是不是离得太远了,我将不胜感激。我应该做什么,我可以或应该改变的地方,以改善等…

我渴望学习...

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2012-07-07 05:09:31

目标

在我看来,你在这种情况下的目的有两个:

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

解决方案

我建议同时使用匿名函数和工厂模式来处理PDO连接。它的用法如下所示:

代码语言:javascript
复制
$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 );

然后在不同的文件中,或者在同一文件中更低的位置:

代码语言:javascript
复制
$something = $factory->create('Something');
$foobar = $factory->create('Foobar');

工厂本身应该看起来像这样:

代码语言:javascript
复制
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 );
    }

}

这种方式将使您拥有一个集中式结构,从而确保仅在需要时才创建连接。它还将使单元测试和维护的过程变得更加容易。

在这种情况下,提供程序将在引导阶段的某个位置找到。这种方法还会给出一个明确的位置来定义配置,用于连接到数据库。

请记住,这是一个极其简化的示例。您还可以从观看以下两个视频中获益:

此外,我强烈建议阅读a proper tutorial关于PDO的使用(有一个糟糕的在线教程日志)。

票数 106
EN

Stack Overflow用户

发布于 2012-07-07 04:48:50

我建议不要使用$_SESSION来全局访问您的数据库连接。

您可以执行以下几项操作之一(从最差到最好的实践):

  • Access $dbh在函数和类中使用global $dbh
  • 使用单例注册表,并全局访问,如下所示:

$registry = MyRegistry::getInstance();$dbh =将数据库处理程序$registry->getDbh();

  • Inject到需要它的类中,如下所示:

类MyClass {公共函数__construct($dbh) { /* ... */ } }

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

然而,它更高级一些,需要更多的“连接”而不需要框架。所以,如果依赖注入对你来说太复杂了,那就使用一个单独的注册表,而不是一堆全局变量。

票数 24
EN

Stack Overflow用户

发布于 2014-01-12 08:21:17

最近,我自己也得到了类似的答案/问题。这就是我所做的,如果有人感兴趣的话:

代码语言:javascript
复制
<?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);
    }
  }

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

代码语言:javascript
复制
$DB = new \Library\PDO(/* normal arguments */);

以及类型提示,如果您使用它(\Library\PDO $DB)。

它与公认的答案和你的答案都很相似;但是它有一个显着的优势。考虑下面的代码:

代码语言:javascript
复制
$DB = new \Library\PDO( /* args */ );

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

虽然它看起来像普通的PDO (它只受该\Library\的影响),但实际上直到您调用第一个方法(无论是哪一个方法)时,它才会初始化对象。这使得它更加优化,因为创建PDO对象的开销稍微大一些。它是一个透明的类,或者叫做Ghost,是Lazy Loading的一种形式。您可以将$DB视为一个普通的PDO实例,传递它,执行相同的操作,等等。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11369360

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档