【问题标题】:I need a PHP object in global scope. How do I do that, or is there a better way?我需要一个全局范围内的 PHP 对象。我该怎么做,或者有更好的方法吗?
【发布时间】:2015-05-27 23:31:12
【问题描述】:

我正在尝试创建我的第一个面向对象的 Web 应用程序,并且对如何全局引用对象有疑问。不确定是否有必要,但这里有一些背景知识。该应用是单页应用。

Index.php 创建一个“Page”类的新实例。此实例检查 url 参数(page=???),然后检查是否存在适当的内容类并调用其中的函数。如果该页面类不存在,它会调用另一个 404 类并显示它。

每个页面内容类都是从 BasePage 类扩展而来的。所以例如index.php?page=Home 会像这样工作

+---------+                              +----------+
|         | creates instance of Page.php |          |
|index.php|----------------------------->| page.php |  
|         |                              |          |
+---------+     +----------+             +----------+
                |          |            /
                | base.php |           /
                |          |          / "Page" loads the relevant class
                +----------+         /  and calls a function within it
 home.php                  |       |/_
 extends base.php       +----------+
                        |          |
                        | home.php |
                        |          |
                        +----------+

希望到目前为止这是有道理的。我现在遇到的问题是我需要一个从“用户”类的实例创建的“用户”对象。这个 User 对象将在几乎每个页面、Index.php、page.php 和 home.php 中被引用。到目前为止,我已经在其他每个类中创建了 User 类的实例。这可行,但通常会导致多次调用数据库并创建多个用户对象。我认为最好的方法是使 User 类成为单例类,但是我在哪里创建该单例对象。如果我在 base.php 中创建实例,home.php 会引用它,但 page.php 和 index.php 没有。如果我在 index.php 中创建实例,除非我将它传递给每个类,否则没有其他页面可以访问它——这会变得混乱。 (我知道,我试过了)。

所以我的问题是,如何制作每个页面都可以访问的单例对象?我认为将它放在全局范围内会有所帮助,但是 a)我不知道该怎么做,并且 b)我已经阅读了很多关于为什么全局变量是坏东西的文章。

任何人都可以提供任何建议吗?我应该如何创建我的用户对象?

谢谢

【问题讨论】:

  • What has been happening up to now is I have created instances of the User class in every other class. 你不能从你的类中创建用户并用用户对象作为参数来构造它们吗?这将防止多个用户被实例化
  • 将用户对象作为参数传递给其他类的构造函数是比使用单例更简洁的解决方案。另外,您确定每个页面都必须扩展基本页面类吗?
  • 我鼓励您了解autoloading in PHPdependency injection。这两者都将在您的解决方案中发挥作用。
  • 是的,我已经尝试将用户对象传递给其他类的构造函数,但实际上,还有很多其他类被使用。将 User 对象作为参数传递变得非常混乱,并且感觉不是正确的做法。其他一些类包含静态方法,因此我不仅需要将对象传递给构造函数类,还需要传递给其中的每个方法
  • 除了不使用静态方法之外,将对象传递给您的类是可行的方法。不过,您可以在大多数较新的 PHP 版本中使用 $myClassInstance::staticMethod()

标签: php class oop globals


【解决方案1】:

您正在寻找的是单例。但是单例模式被认为是非常糟糕的做法,应该不惜一切代价避免。您应该尽量避免任何需要您拥有全局内容的解决方案。

一个非常简单的应用程序结构的更好方法是为您的应用程序创建某种主类,并将您的组件类作为属性分配给这个主类。这已经是一个不错的小依赖注入的一半了。

关于为什么单例不好的一些小文章:

【讨论】:

  • 您能否提供一些参考资料说明为什么singleton pattern不好的做法
  • @JonSurrell examples are numerous.
  • 它基本上归结为:您必须使用一个实例化不在您手中的类,并且无论未来发生什么都无法更改或替换。如果您有多个共享此类的应用程序,则他们无法使用自己的版本。这也使得嘲笑东西几乎不可能。
  • @FélixGagnon-Grenier 提供参考以支持答案中提出的声明对每个人来说都是一个巨大的胜利,IMO。
【解决方案2】:

如果您选择尝试实现单例,这将是如何确保您的用户始终相同的示例:

class User {
    private static $instance = null;
    private $name;
    public function __construct($name) {
        $this->name = $name;
    }
    public static function get($name) {
        if (self::$instance === null) self::$instance = new self($name);
        return self::$instance;
    }
    public function sayHello() {
        echo 'Hello my name is '.$this->name;
    }
}

$user = User::get('Bob');
$user->sayHello(); // Hello my name is Bob

请注意,由于混合了静态类和动态实例,此类做法很容易出错、愤怒和仇恨。

如果你想了解依赖注入,pimple 是我对它的介绍,通过复制他们的代码,我能够创建更可靠的代码;这是可访问的对象,无论您在何处访问它们,都使用它们相关的良好依赖项创建。

这种容器的原理是定义你的对象然后检索它们,只构造那些必要的。假设你正在使用疙瘩:

$cnt = new Pimple();
$cnt['page'] = function($c) { 
// the class pimple passes the container itself to the functions you define
    return new page($c['session']); 
// defines the page key to return a new page
};
$cnt['session'] = function() {
    return new session();
};
$page = $cnt['page']; 
// constructs the session because it is called to construct the page

【讨论】:

  • 谢谢大家。这里有很多好的建议。看起来共识是依赖注入,所以我会进一步研究。我已经使用过自动加载器,并且对 DI 很熟悉,所以也许我只需要稍微完善一下我的知识。再次感谢所有帮助。非常有用。
  • OOP 的有趣方法,但您现在不会从类外部定义类的功能,从而将责任和逻辑从类本身转移到外部因素吗?一个类不应该在它自己的职责/关注点内相当地自我定义吗?
  • 您好,感谢您的跟进!我不确定你是什么意思? wouldnt you now define the functionality of your class from outside the class我没看到我在做这个?第一个代码集中了功能,即使是那些可以由 UserFactory 负责的功能,第二个代码是通过使用闭包的依赖注入定义,并由依赖注入容器(例如 pimple 或在定义 services in angularjs 时使用) .还是不是你的意思?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-31
相关资源
最近更新 更多