【问题标题】:PHP PDO - what is the proper usage for multiple connecting classes?PHP PDO - 多个连接类的正确用法是什么?
【发布时间】:2018-02-13 19:32:11
【问题描述】:

我正在尝试学习 PDO,所有资源都说“使用 PDO,您只需每个脚本连接一次。”

我如何确保这一点?我一定要吗?最佳做法是什么?

假设我有一个名为 DatabaseConnection 的 PHP 文件和类,其中包含我的凭据等,以及建立连接的方法:

我是否确保在每个页面/副作用脚本的开头连接到 mySQL?

//homepage.php
//create header, body, etc, whatever
//$pdoConnection = DatabaseConnection::CREATE_CONNECTION;
//new Avatar($pdoConnection)

还是在课堂上?

//avatar.php
//class Avatar { ...
//$this->pdoConnection = DatabaseConnection::CREATE_CONNECTION;

换句话说,连接将如何流动?

database.php -> homepage.php -> avatar.php?
database.php -> avatar.php?

关于这个主题的任何其他资源?许多人深入了解 PDO,但我找不到广泛的使用示例。

【问题讨论】:

标签: php oop pdo


【解决方案1】:

不是每个人都喜欢单例样式类,但这是一种解决方案。在每个页面中包含一个应用程序对象/类。

这样做的好处是,它仅在您使用连接时才连接,并非所有页面都可能需要数据库连接

class App {

   private static $PDO_INSTANCE;

   public static function getPdoInstance() {
      if (!self::$PDO_INSTANCE) {
         self::$PDO_INSTANCE= // TODO build pdo connection
      }

      return self::$PDO_INSTANCE;
   }

}

然后使用它

$pdo = App::getPdoInstance();
// do db logic here

原始答案的补充

我尝试将我的所有数据库访问权限保留在一组类中,其通用名称将是“数据访问层”或“数据存储库”。

这些类是唯一需要了解 pdo 连接的类。

例如

class calendar_page {

    function index() {
        $dal_calendar = new DalCalendar();
        $events = $dal_calendar->getEvents();
        // render html using data 
    }
}


class DataAccessLayer {

 private $pdo;

 function __construct() {
    $this>pdo = App::getPdoInstance();
 }

class DalCalendar extends DataAccessLayer  {

    function getEvents() {
          $this->pdo-> // query for events
          return $events;
    }

}

另一种传递连接的方法是使用依赖注入,你必须在谷歌上搜索更多信息,我不能给你一个简单的例子。

【讨论】:

  • 嘿嘿,领先我一分钟。 :)
  • 谢谢。我有点理解这部分,我最关心的是什么时候使用它。那么,您会说在每个页面脚本中都包含它,而不是在其他类中?类实例如何访问连接?我应该在创建它们时将其作为参数传递吗?那些总是需要连接的类呢?
  • 我在回答中添加了更多信息
  • 再次感谢您。那么,可以为每个类/页面建立多个连接吗?假设您在 DalCalendar 中获得一个连接来获取所有事件,并且在 Avatar 中打开一个连接来获取用户的头像,并且您在 page.php 中使用这两个类。可以吗?
  • 是的,没关系,因为它是一个单例结构,每次你调用 App::getPdoInstance() 时,它都会返回相同的 1 连接给你。它只会在您第一次调用它时创建一个新连接。
【解决方案2】:

最简单的解决方案是使用单例模式。 ¹

这个想法是你有一个带有一个静态方法的类,它返回你的数据库连接的一个实例。连接将在静态方法的第一次调用中被实例化,然后被重用。例如:

class MyPDO
{
    private static $inst;

    public static getInstance()
    {
        if (!self::$inst)
            self::$inst = new PDO(/* your connection details */);

        return self::$inst;
    }
}

当你想在上下文中使用单例时,包括类文件(如果你不使用自动加载器),你可以立即使用 PDO 实例:

require_once "/path/to/MyPDO.php"; // it’s important to use require_once
$pdo = MyPDO::getInstance();

¹ 请注意,如今,Singleton 更多地被认为是一种反模式,如果可能的话,更倾向于使用依赖注入。

【讨论】:

  • 也感谢您的回答。尽管它在某种程度上反映了其他答案,但依赖注入位看起来很有趣。请向我解释一件事。我在哪里包括连接。可以在另一个类中使用 Database::INSTANCE() 吗,比如 Avatar?这意味着每页可能有多个 PDO 实例(如果有多个头像)。那样行吗?还是应该只在每一页的开头声明?那我怎么把它传给班级呢?论据?谢谢
  • 不,PDO 连接本身只在MyPDO 内管理。其他类可以访问它,但不应对其进行操作。
  • @DwarfVader 如果您在一个类中使用 Database::INSTANCE()(例如 Avatar,例如),那么您正在使该类依赖于 Database 类。当您尝试使用new 在另一个类(如 Avatar)中创建一个类(如 PDO)的实例时,同样适用。此外,通过做这些事情,从外部看到,一个类需要和使用连接的事实将被完全隐藏。 依赖注入解决了这些问题。无论您选择什么来创建数据库连接:将其作为参数注入到需要的地方。
  • 谢谢。这实际上澄清了我最想知道的。因此,每当创建新的类实例 ($av1 = new Avatar(Database::INSTANCE())) 时,我都希望将连接作为参数传递下去。你会这样做吗?也许在文件开头给它一个变量($conn = Database::INSTANCE(); [...] $av1 = new Avatar($conn))?
  • 不,使用Singleton时不需要注入实例。 (谷歌“Singleton”查看实际示例)。只需从几乎任何地方调用静态方法即可获取 PDO 实例并使用它。如果你在谈论 DI,你应该使用 DI 框架,比如 Symfony,因为你当然不想自己重新实现所有的复杂性。
猜你喜欢
  • 2015-08-13
  • 2015-09-27
  • 1970-01-01
  • 2011-07-05
  • 2014-08-12
  • 2014-10-05
  • 1970-01-01
  • 2014-05-08
  • 1970-01-01
相关资源
最近更新 更多