为了账号安全,请及时绑定邮箱和手机立即绑定

是否有PHP中具有数据库访问的单例的用例?

/ 猿问

是否有PHP中具有数据库访问的单例的用例?

跃然一笑 2019-06-01 14:26:59

是否有PHP中具有数据库访问的单例的用例?

我通过PDO访问MySQL数据库。我正在设置对数据库的访问,我的第一次尝试是使用以下方法:

我想到的第一件事是global:

$db = new PDO('mysql:host=127.0.0.1;dbname=toto', 'root', 'pwd');function some_function() {
    global $db;
    $db->query('...');}

这被认为是一种糟糕的做法。经过一次小小的搜索,我得到了单例模式,它

“适用于需要类的单个实例的情况。”

根据手册中的例子,我们应该这样做:

class Database {
    private static $instance, $db;

    private function __construct(){}

    static function singleton() {
        if(!isset(self::$instance))
            self::$instance = new __CLASS__;

        return self:$instance;
    }

    function get() {
        if(!isset(self::$db))
            self::$db = new PDO('mysql:host=127.0.0.1;dbname=toto', 'user', 'pwd')

        return self::$db;
    }}function some_function() {
    $db = Database::singleton();
    $db->get()->query('...');}some_function();

当我能做到这一点的时候,为什么我需要那个相对较大的课程呢?

class Database {
    private static $db;

    private function __construct(){}

    static function get() {
        if(!isset(self::$db))
            self::$db = new PDO('mysql:host=127.0.0.1;dbname=toto', 'user', 'pwd');

        return self::$db;
    }}function some_function() {
    Database::get()->query('...');}some_function();

最后一个很好,我不需要担心$db更多。

我如何创建一个较小的单例类,或者是否存在PHP中缺少的单例用例?


查看完整描述

3 回答

?
慕斯卡3215842

好吧,当我刚开始我的职业生涯时,我一直在想这件事。实现它的方式不同,并提出了选择不使用静态类的两个原因,但它们是相当大的类。

一个是你会发现很多时候你绝对确信你永远不会有超过一个实例,你最终会有第二个实例。你可能会有第二个监视器,第二个数据库,第二个服务器-随便吧。

当发生这种情况时,如果您使用了静态类,那么您将面临比使用单例更糟糕的重构。单例本身是一种不确定的模式,但它很容易转换为智能工厂模式-甚至可以转换为使用依赖注入,而不需要太大的麻烦。例如,如果您的单例是通过getInstance()获得的,您可以很容易地将其更改为getInstance(DatabaseName),并允许多个数据库-没有其他代码更改。

第二个问题是测试(老实说,这和第一个问题是一样的)。有时,您希望用模拟数据库替换数据库。实际上,这是数据库对象的第二个实例。使用静态类要比使用单例要困难得多,您只需模拟getInstance()方法,而不是静态类中的每个方法(在某些语言中可能非常困难)。

这真的可以归结为习惯-当人们说“全球”是坏的时候,他们有很好的理由这么说,但在你自己遇到问题之前,这可能并不总是显而易见的。

你能做的最好的事情就是问(就像你做的那样),然后做出选择,观察你决定的后果。拥有解释代码随时间演变的知识比从一开始就正确处理代码要重要得多。


查看完整回答
反对 回复 2019-06-01
点击展开后面2
?
ABOUTYOU

单例在PHP中几乎没有-如果不是说不使用-的话。

在对象驻留在共享内存中的语言中,可以使用单例来保持较低的内存使用率。不是创建两个对象,而是引用全局共享应用程序内存中的现有实例。在PHP中,没有这样的应用程序内存。在一个请求中创建的Singleton正好存在于该请求中。在同一时间完成的另一个请求中创建的Singleton仍然是一个完全不同的实例。因此,Singleton的两个主要目的之一在这里不适用。

此外,在您的应用程序中,许多在概念上只存在一次的对象不一定需要语言机制来强制执行。如果你需要只有一个实例不要实例化另一个..只有当你可能没有其他实例,例如,当您创建第二个实例时,当小猫死亡时,您可能对Singleton有一个有效的用例。

另一个目的是在同一个请求中拥有一个对实例的全局访问点。虽然这听起来可能是可取的,但实际上并非如此,因为它创建了与全局范围的耦合(就像任何全局和静力学一样)。这使得单元测试更加困难。而您的应用程序的可维护性通常较低。有减轻这种情况的方法,但是通常,如果您需要在许多类中具有相同的实例,请使用依赖注入.

请看我的幻灯片PHP中的单例-为什么它们不好,以及如何从应用程序中消除它们以获得更多信息。

埃里希·伽玛,单身模式的发明者之一,现在怀疑这种模式:

“我赞成抛弃辛格尔顿。它的使用几乎总是一种设计味”

再读


查看完整回答
反对 回复 2019-06-01
?
慕妹3242003

谁需要PHP中的单身汉?

请注意,几乎所有对单例的反对都来自技术观点-但它们的范围也非常有限。特别是对于PHP。首先,我将列出一些使用单件的原因,然后我将分析反对使用单件的理由。首先,需要它们的人:

-将在许多不同环境中使用的大型框架/代码基的编码人员将不得不使用以前存在的、不同的框架/代码库,必须执行客户/老板/管理/单位领导提出的许多不同的、不断变化的、甚至是异想天开的要求。

看,单例模式是自我包容的。完成后,单例类在包含它的任何代码中都是僵化的,它的作用与您如何创建它的方法和变量完全一样。在给定的请求中,它总是相同的对象。由于不能两次创建为两个不同的对象,所以您知道在代码中的任何给定点上单例对象是什么-即使单例被插入到两个、三个不同的、旧的、甚至是意大利代码基中。因此,它使开发目的变得更容易-即使有许多人在该项目中工作,当您在任何给定的代码基中看到一个单独的人在一个点上被初始化时,您就知道它是什么,它是做什么的,它是如何工作的,以及它所处的状态。如果它是传统类,则需要跟踪该对象最初创建的位置、在其中调用了哪些方法,以及在代码中的特定状态。但是,如果您放弃了正确的调试和信息方法,并在编写代码时跟踪到该单例中,您就会确切地知道它是什么。因此,对于那些必须使用不同的代码库的人来说,这就更容易了,因为有必要集成代码,这是以前用不同的哲学完成的,或者是由您没有接触过的人完成的。(也就是说,供应商-项目-公司-什么都没有了,没有任何支持)。

-需要与第三方合作的人原料药、服务和网站。

如果你仔细看,这和以前的情况没有太大的不同-第三方的api,服务,网站,就像你无法控制的外部的、孤立的代码库。任何事都可能发生。因此,使用单例会话/用户类,您可以管理来自第三方提供程序的任何类型的会话/授权实现,如OpenID脸书推特还有更多的-你可以从同一个单例对象同时完成所有这些-这是很容易访问的,在任何给定的时刻,无论你插入什么代码,它都是一个已知的状态。您甚至可以在您自己的网站/应用程序中为同一个用户创建多个不同的第三方API/服务的多个会话,并对它们做任何您想做的事情。

当然,通过使用普通的类和对象,所有这些也可以是传统方法的基调-这里的问题是,单例更整洁、更整洁,因此与传统的类/对象使用相比,在这种情况下更易于管理/测试。

-需要快速发展的人

单例的类似全局的行为使构建任何类型的代码变得更容易,该框架有一个可以构建的单例集合,因为一旦您很好地构造了您的单例类,那么已经建立的、成熟的和集合的方法将在任何地方,任何时间,以一致的方式很容易获得和使用。要使你的课程成熟需要一段时间,但在那之后,它们是坚如磐石、始终如一、有用的。您可以在单个实例中使用任意的方法,尽管这可能会增加对象的内存占用,但它为快速开发节省了更多的时间-在应用程序的一个给定实例中不使用的方法可以在另一个集成实例中使用,您只需修改一下客户/老板/项目经理所要求的新功能即可。

你知道这个主意。现在让我们继续讨论对单身人士的反对,以及对一些有用的东西进行的邪恶的十字军运动。:

-最主要的反对意见是,它使测试更加困难。

实际上,这在某种程度上确实如此,即使通过采取适当的预防措施并将调试例程编码到您的单例中,可以很容易地缓解这种情况,并意识到您将调试一个单例程序。但是要知道,这和任何其他的编码哲学/方法/模式并没有太大的不同-只是,单例比较新,而且并不普遍,所以目前的测试方法最终都与它们不兼容。但这在编程语言的任何方面都没有不同-不同的风格需要不同的方法。

有一点这一反对意见没有什么意义,因为它忽略了一个事实,即开发应用程序不是为了“测试”,而测试并不是进入应用程序开发的唯一阶段/过程。应用程序是为生产使用而开发的。正如我在“谁需要单用户”一节中解释的那样,单节点可以大大减少许多代码库/应用程序/第三方服务的复杂性,使代码在许多不同的代码基/应用程序/第三方服务中工作。在测试中可能丢失的时间是在开发和部署中获得的时间。在这个第三方认证/应用程序/集成的时代-Facebook、Twitter、OpenID等等-这尤其有用,谁知道接下来会发生什么。

虽然这是可以理解的-程序员的工作环境非常不同,取决于他们的职业。对于那些在相对大的公司工作的人来说,定义的部门倾向于不同的,定义的软件/应用程序以一种舒适的方式,没有即将到来的预算削减/裁员的厄运,以及伴随着以廉价/快速/可靠的方式处理大量不同的东西的需求,单身的人可能并不是那么有必要。这甚至可能会对他们已经拥有的东西造成滋扰/阻碍。

但是对于那些需要在“敏捷”开发的肮脏战壕中工作的人来说,他们必须实现来自他们的客户/经理/项目的许多不同的请求(有时是不合理的),由于前面解释的原因,单身是一种节省的恩惠。

-另一个反对意见是,它的内存占用较高

因为每个客户端的每个请求都会有一个新的单例,这可能是PHP的反对。对于构造糟糕和使用不当的单例,如果应用程序在任何给定的点上为许多用户提供服务,则应用程序的内存占用可能会更高。

不过,这对于编写代码时可以采取的任何方法都是有效的。应该提出的问题是,这些单身人士持有和处理的方法和数据是否没有必要?因为,如果在许多请求应用程序中都需要它们,那么即使您不使用单例,这些方法和数据也会通过代码以某种形式出现在您的应用程序中。因此,当您将传统的类对象1/3初始化到代码处理中,并将其销毁到代码处理中时,这就变成了一个节省多少内存的问题。

要知道,当这样说的时候,这个问题就变得非常不相关了-无论如何,不应该有不必要的方法,在代码中的对象中保存数据-不管您是否使用单例。因此,这种对单例的反对变得非常有趣,因为它假设在您使用的类创建的对象中会有不必要的方法和数据。

-一些无效的反对意见,如“使维护多个数据库连接变得不可能/更困难”

我甚至无法理解这种反对,当一个人需要维护多个数据库连接、多个数据库选择、多个数据库查询、一个给定单例中的多个结果集时,只要需要,就将它们保存在单例中的变量/数组中。这可以像将它们保持在数组中一样简单,尽管您可以发明任何您想要使用的方法来实现这一点。但是让我们看看最简单的情况,在给定的单例中使用变量和数组:

假设下面的内容位于给定的数据库中:

$这个->连接=列阵(); (语法错误,我只是像这样输入它来给您提供图片-变量的正确声明是public$Connections=Array();它的用法是$this->Connections[‘connectionkey’]。)

您可以在任何给定时间以这种方式在数组中设置和保持多个连接。查询、结果集等也是如此。

$这个->查询(QUERYSTRING,‘queryname’,$this->Connections[‘SpecirConnection’]);

它只需使用选定的连接对选定的数据库执行查询,只需将其存储在

$这个->结果

使用键‘queryname’数组。当然,您需要为此编写查询方法-这很简单。

这使您能够维护几乎无限数量的不同数据库连接和结果集(当然,在资源限制允许的范围内)。在任何给定的代码基中,任何给定点的任何代码都可以使用它们,其中已实例化了这个单例类。

当然,您自然需要释放结果集,并在不需要时释放连接-但这是不言而喻的,而且它并不是特定于单例或任何其他编码方法/样式/概念。

此时,您可以看到如何在同一个单例中维护到第三方应用程序或服务的多个连接/状态。没什么不同。

长话短说,最后,单例模式只是另一种编程方法/风格/哲学,当它们在正确的位置和正确的方式使用时,它们与任何其他模式一样有用。这和任何事都没有区别。

你会注意到,在大多数的文章中,单身汉被击打,你也会看到引用‘全球’是‘邪恶’。

让我们面对现实-任何不恰当使用、滥用、误用的东西都是邪恶的。这不仅限于任何语言,任何编码概念,任何方法。每当你看到有人发表像“X是邪恶”这样的总称时,就逃离那篇文章。它很有可能是有限的观点的产物-即使这个观点是多年经验的结果-这通常是在某种特定的风格或方法下工作过多的结果-典型的智力保守主义。

这方面的例子不胜枚举,从“全球都是邪恶的”到“如果是邪恶的”。大约10年前,甚至提议在任何特定的应用程序中使用iframe都是异端。然后Facebook出现了,如果到处都是,看看发生了什么-如果不再是那么邪恶。

仍然有一些人顽固地坚持自己是“邪恶的”-有时也是出于正当理由-但是,正如你所看到的,如果有必要满足这些需求,并发挥良好的作用,那么整个世界就会继续前进。

程序员/软件工程师最重要的资产是自由、开放和灵活的思维。


查看完整回答
反对 回复 2019-06-01

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信