php 用于数据库连接的全局或单例?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/130878/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Global or Singleton for database connection?
提问by Imran
What is the benefit of using singleton instead of global for database connections in PHP? I feel using singleton instead of global makes the code unnecessarily complex.
在 PHP 中使用单例而不是全局进行数据库连接有什么好处?我觉得使用单例而不是全局会使代码不必要地复杂。
Code with Global
全球代码
$conn = new PDO(...);
function getSomething()
{
global $conn;
.
.
.
}
Code with Singleton
单例代码
class DB_Instance
{
private static $db;
public static function getDBO()
{
if (!self::$db)
self::$db = new PDO(...);
return self::$db;
}
}
function getSomething()
{
$conn = DB_Instance::getDBO();
.
.
.
}
If there's a better way of initializing database connection other than global or singleton, please mention it and describe the advantages it have over global or singleton.
如果有比 global 或 singleton 更好的初始化数据库连接的方法,请提及它并描述它相对于 global 或 singleton 的优点。
回答by Jon Raphaelson
I know this is old, but Dr8k's answer was almostthere.
我知道这很旧,但 Dr8k 的答案几乎就在那里。
When you are considering writing a piece of code, assume it's going to change. That doesn't mean that you're assuming the kinds of changes it will have hoisted upon it at some point in the future, but rather that some form of change will be made.
当您考虑编写一段代码时,假设它会发生变化。这并不意味着您假设它会在未来的某个时间点对它进行各种更改,而是会进行某种形式的更改。
Make it a goal mitigate the pain of making changes in the future: a global is dangerous because it's hard to manage in a single spot. What if I want to make that database connection context aware in the future? What if I want it to close and reopen itself every 5th time it was used. What if I decide that in the interest of scaling my app I want to use a pool of 10 connections? Or a configurable number of connections?
让它成为一个目标可以减轻未来改变的痛苦:全局是危险的,因为它很难在一个地方进行管理。如果我希望将来知道该数据库连接上下文怎么办?如果我希望它每使用 5 次就关闭并重新打开,该怎么办。如果我决定为了扩展我的应用程序我想使用 10 个连接池怎么办?还是可配置的连接数?
A singleton factorygives you that flexibility. I set it up with very little extra complexity and gain more than just access to the same connection; I gain the ability to change how that connection is passed to me later on in a simple manner.
一个单身的工厂为您提供了灵活性。我用很少的额外复杂性来设置它,并且获得的不仅仅是访问相同的连接;我获得了稍后以简单方式更改该连接传递给我的方式的能力。
Note that I say singleton factoryas opposed to simply singleton. There's precious little difference between a singleton and a global, true. And because of that, there's no reason to have a singleton connection: why would you spend the time setting that up when you could create a regular global instead?
请注意,我说的是单例工厂,而不是简单的单例。单身人士和全球人士之间几乎没有什么区别,真的。正因为如此,没有理由有一个单例连接:当你可以创建一个普通的全局时,你为什么要花时间设置它呢?
What a factory gets you is a why to get connections, and a separate spot to decide what connections (or connection) you're going to get.
工厂为您提供的是为什么要获得联系,以及一个单独的地点来决定您将获得什么联系(或联系)。
Example
例子
class ConnectionFactory
{
private static $factory;
private $db;
public static function getFactory()
{
if (!self::$factory)
self::$factory = new ConnectionFactory(...);
return self::$factory;
}
public function getConnection() {
if (!$this->db)
$this->db = new PDO(...);
return $this->db;
}
}
function getSomething()
{
$conn = ConnectionFactory::getFactory()->getConnection();
.
.
.
}
Then, in 6 months when your app is super famous and getting dugg and slashdotted and you decide you need more than a single connection, all you have to do is implement some pooling in the getConnection() method. Or if you decide that you want a wrapper that implements SQL logging, you can pass a PDO subclass. Or if you decide you want a new connection on every invocation, you can do do that. It's flexible, instead of rigid.
然后,在 6 个月内,当您的应用程序非常出名并被挖出和斜线标记并且您决定需要多个连接时,您所要做的就是在 getConnection() 方法中实现一些池化。或者,如果您决定需要一个实现 SQL 日志记录的包装器,您可以传递一个 PDO 子类。或者,如果您决定在每次调用时都需要一个新连接,则可以这样做。它是灵活的,而不是僵硬的。
16 lines of code, including braces, which will save you hours and hours and hours of refactoring to something eerily similar down the line.
16 行代码,包括大括号,这将为您节省数小时、数小时和数小时的重构时间,以实现极其相似的事情。
Note that I don't consider this "Feature Creep" because I'm not doing any feature implementation in the first go round. It's border line "Future Creep", but at some point, the idea that "coding for tomorrow today" is alwaysa bad thing doesn't jive for me.
请注意,我不考虑这种“功能蠕变”,因为我在第一轮中没有进行任何功能实现。它是“未来蠕变”的边界线,但在某些时候,“今天为明天编码”总是一件坏事的想法对我来说并不合适。
回答by Dr8k
I'm not sure I can answer your specific question, but wanted to suggest that global / singleton connection objects may not be the best idea if this if for a web-based system. DBMSs are generally designed to manage large numbers of unique connections in an efficient manner. If you are using a global connection object, then you are doing a couple of things:
我不确定我能否回答您的具体问题,但我想建议如果对于基于 Web 的系统,全局/单例连接对象可能不是最好的主意。DBMS 通常被设计为以有效的方式管理大量的唯一连接。如果您使用的是全局连接对象,那么您正在做几件事:
Forcing you pages to do all database connections sequentially and killing any attempts at asyncronous page loads.
Potentially holding open locks on database elements longer than necessary, slowing down overall database performance.
Maxing out the total number of simultaneous connections your database can support and blocking new users from accessing the resources.
强制您的页面按顺序执行所有数据库连接并终止任何异步页面加载的尝试。
可能在数据库元素上保持打开锁的时间超过必要时间,从而降低整体数据库性能。
最大化您的数据库可以支持的同时连接总数并阻止新用户访问资源。
I am sure there are other potential consequences as well. Remember, this method will attempt to sustain a database connection for every user accessing the site. If you only have one or two users, not a problem. If this is a public website and you want traffic then scalability will become an issue.
我相信还有其他潜在的后果。请记住,此方法将尝试为每个访问站点的用户维持数据库连接。如果你只有一两个用户,没问题。如果这是一个公共网站并且您想要流量,那么可扩展性将成为一个问题。
[EDIT]
[编辑]
In larger scaled situations, creating new connections everytime you hit the datase can be bad. However, the answer is not to create a global connection and reuse it for everything. The answer is connection pooling.
在更大规模的情况下,每次访问数据时创建新连接可能很糟糕。但是,答案不是创建全局连接并将其重用于所有内容。答案是连接池。
With connection pooling, a number of distinct connections are maintained. When a connection is required by the application the first available connection from the pool is retrieved and then returned to the pool once its job is done. If a connection is requested and none are available one of two things will happen: a) if the maximum number of allowed connection is not reached, a new connection is opened, or b) the application is forced to wait for a connection to become available.
通过连接池,可以维护许多不同的连接。当应用程序需要连接时,将从池中检索第一个可用连接,然后在其工作完成后返回到池中。如果请求连接但没有可用连接,则会发生以下两种情况之一:a) 如果未达到允许的最大连接数,则打开一个新连接,或 b) 应用程序被迫等待连接变为可用.
Note:In .Net languages, connection pooling is handled by the ADO.Net objects by default (the connection string sets all the required information).
注意:在 .Net 语言中,默认情况下连接池由 ADO.Net 对象处理(连接字符串设置所有必需的信息)。
Thanks to Crad for commenting on this.
感谢克拉德对此发表评论。
回答by Dr8k
The singleton method was created to make sure there was only one instance of any class. But, because people use it as a way to shortcut globalizing, it becomes known as lazy and/or bad programming.
创建单例方法是为了确保任何类只有一个实例。但是,由于人们将其用作全球化的捷径,因此它被称为懒惰和/或糟糕的编程。
Therefore, I would ignore global and Singleton since both are not really OOP.
因此,我会忽略 global 和 Singleton,因为它们都不是真正的 OOP。
What you were looking for is dependency injection.
你要找的是依赖注入。
You can check on easy to read PHP based information related to dependency injection (with examples) at http://components.symfony-project.org/dependency-injection/trunk/book/01-Dependency-Injection
您可以在http://components.symfony-project.org/dependency-injection/trunk/book/01-Dependency-Injection查看与依赖注入相关的基于 PHP 的易于阅读的信息(带有示例)
回答by Adam Ness
Both patterns achieve the same net effect, providing one single access point for your database calls.
这两种模式实现了相同的净效果,为您的数据库调用提供一个单一的访问点。
In terms of specific implementation, the singleton has a small advantage of not initiating a database connection until at least one of your other methods requests it. In practice in most applications I've written, this doesn't make much of a difference, but it's a potential advantage if you have some pages/execution paths which don't make any database calls at all, since those pages won't ever request a connection to the database.
在具体实现方面,单例有一个小优势,就是在你的其他方法中至少有一个请求它之前不会启动数据库连接。实际上,在我编写的大多数应用程序中,这并没有太大区别,但是如果您有一些根本不进行任何数据库调用的页面/执行路径,这是一个潜在的优势,因为这些页面不会曾经请求连接到数据库。
One other minor difference is that the global implementation may trample over other variable names in the application unintentionally. It's unlikely that you'll ever accidentally declare another global $db reference, though it's possible that you could overwrite it accidentally ( say, you write if($db = null) when you meant to write if($db == null). The singleton object prevents that.
另一个小区别是全局实现可能会无意中践踏应用程序中的其他变量名称。您不太可能意外地声明另一个全局 $db 引用,尽管您可能会意外覆盖它(例如,当您打算编写 if($db == null) 时,您编写了 if($db = null)。单例对象阻止了这种情况。
回答by Gavin M. Roy
If you're not going to use a persistent connection, and there are cases for not doing that, I find a singleton to be conceptually more palatable than a global in OO design.
如果您不打算使用持久连接,并且在某些情况下不这样做,那么我发现单例在概念上比面向对象设计中的全局更可口。
In a true OO architecture, a singleton is more effective than creating a new instance the object each time.
在真正的 OO 架构中,单例比每次都为对象创建一个新实例更有效。
回答by Dprado
On the given example, I see no reason to use singletons. As a rule of thumb if my only concern is to allow a single instance of an object, if the language allows it, I prefer to use globals
在给定的示例中,我认为没有理由使用单例。根据经验,如果我唯一关心的是允许对象的单个实例,如果语言允许,我更喜欢使用全局变量
回答by RWendi
In general I would use a singleton for a database connection... You don't want to create a new connection everytime you need to interact to the database... This might hurt perfomance and bandwidth of your network... Why create a new one, when there's one available... Just my 2 cents...
一般来说,我会使用单例进行数据库连接......你不想在每次需要与数据库交互时创建一个新连接......这可能会损害网络的性能和带宽......为什么要创建一个新的,当有一个可用的...只是我的 2 美分...
RWendi
温迪
回答by 1800 INFORMATION
It is quite simple. Never use global OR Singleton.
这很简单。永远不要使用全局 OR 单例。
回答by Lenin Zapata
As advice both singletonand globalare valid and can be joined within the same system, project, plugin, product, etc... In my case, I make digital products for web (plugin).
作为建议,singleton和global都是有效的,并且可以在同一个系统、项目、插件、产品等中加入......在我的情况下,我为网络(插件)制作数字产品。
I use only singletonin the main class and I use it by principle. I almost do not use it because I know that the main class will not instantiate it again
我在主类中只使用单例,我原则上使用它。我几乎不使用它,因为我知道主类不会再次实例化它
<?php // file0.php
final class Main_Class
{
private static $instance;
private $time;
private final function __construct()
{
$this->time = 0;
}
public final static function getInstance() : self
{
if (self::$instance instanceof self) {
return self::$instance;
}
return self::$instance = new self();
}
public final function __clone()
{
throw new LogicException("Cloning timer is prohibited");
}
public final function __sleep()
{
throw new LogicException("Serializing timer is prohibited");
}
public final function __wakeup()
{
throw new LogicException("UnSerializing timer is prohibited");
}
}
Globaluse for almost all the secondary classes, example:
几乎所有辅助类的全局使用,例如:
<?php // file1.php
global $YUZO;
$YUZO = new YUZO; // YUZO is name class
while at runtime I can use Globalto call their methods and attributes in the same instance because I do not need another instance of my main product class.
而在运行时,我可以使用Global在同一个实例中调用它们的方法和属性,因为我不需要主产品类的另一个实例。
<?php // file2.php
global $YUZO;
$YUZO->method1()->run();
$YUZO->method2( 'parameter' )->html()->print();
I get with the global is to use the same instance to be able to make the product work because I do not need a factory for instances of the same class, usually the instance factory is for large systems or for very rare purposes.
我得到的全局是使用相同的实例来使产品工作,因为我不需要相同类的实例的工厂,通常实例工厂用于大型系统或用于非常罕见的目的。
In conclusion:, you must if you already understand well that is the anti-pattern Singletonand understand the Global, you can use one of the 2 options or mix them but if I recommend not to abuse since there are many programmers who are very exception and faithful to the programming OOP, use it for main and secondary classes that you use a lot within the execution time. (It saves you a lot of CPU).
In conclusion:, 你必须如果你已经很好地理解了反模式Singleton并且理解了Global,你可以使用这两个选项之一或混合它们,但如果我建议不要滥用,因为有很多程序员非常例外并且忠实于编程 OOP,将它用于您在执行时间内大量使用的主要和次要类。(它为您节省了大量 CPU)。

