OOP插件开发。包括外部对象

时间:2019-11-08 作者:ivantxo

我正在使用类和面向对象编程开发一个插件。

在我的插件中,我包含了另一个对象,因为我需要使用这个另一个对象的功能。

我正在插件的构造函数中实例化包含的对象。

require_once (\'path/to/my/IncludedObject\');

class MyPlugin
{
    private $IncludedObject;

    public function __construct()
    {
        $this->IncludedObject = new IncludedObject();
    }
}

class IncludedObject
{
    public $instanceVar = \'defaultValue\';

    public function getInstanceVar()
    {
        return $this->instanceVar();
    }

    public function setInstanceVar($instanceVar)
    {
        $this->instanceVar = $instanceVar;
    }
}
$instaceVar是在我的插件命令我的HTML表单中执行ajax操作后更新的。因此,我从插件中的处理程序调用setInstanceVar($\\u REQUEST[\'newValue\');

我面临的问题是$instanceVar从未更新过,并且始终具有“defaultValue”。

有人能解释一下这个问题吗?

谢谢

2 个回复
最合适的回答,由SO网友:Tom J Nowell 整理而成

问题的根源不是面向对象编程,而是对PHP如何处理请求的根本误解。

例如,如果这是一个Java或节点应用程序,您将在服务器上启动该应用程序,它将接收请求并做出响应。这是一个持续的主动程序。因此,您可以将东西存储在内存中,当您发出另一个请求时,它们仍然存在,因为它们从未消失。

PHP不是这样工作的。

PHP请求与AWS Lamda有更多共同之处,每个请求都会产生一个全新的PHP生命周期。您可以在内存中设置内容,但在请求结束时,它们会消失,所有对象、函数、变量都会消失。

每个新请求都会从头开始加载整个PHP应用程序。你所有的插件,WordPress,你的主题,每次都会被重新加载,然后在请求完成时从内存中消失。

那么你是如何坚持的呢

持久化事物的唯一方法是使用持久化存储,例如数据库、文件、cookie、对象缓存等

备选方案包括:

对于登录的用户特定数据,使用user meta;对于注销的用户特定数据,如果服务器需要访问,则使用Cookie;对于其他所有内容,则使用基于JS的本地存储;对于跨多页表单的持久化信息,则使用隐藏输入;对于站点范围的信息,在提交之前,无需在服务器端持久化任何内容,使用选项和瞬态对于特定于后的数据使用后元和分类术语对于特定于术语的数据,使用术语元请注意$_SESSION PHP会话变量,但:

这些易受会话劫持的攻击,WordPress不使用它们(WP使用cookies)

  • 必须手动设置和清理,不能与许多主机一起使用,与许多CDN和缓存系统不兼容,例如Cloudflare,数据必须存储在服务器的内存中,因此,这可能会导致高流量情况下出现问题。有关OO的一些后续说明使用依赖注入!您的对象无权在其构造函数中创建其他对象。将它们作为参数传入。它将使您的对象更灵活、更容易测试、更容易调试,并节省许多麻烦IncludedObject 也可以只使用公共变量,如果您可以直接访问它,那么使用getter和setter是没有意义的。要么将该变量设为私有变量,要么去掉那些getter/setter,不要调用“->setXYZ()”等。只需调用它->xyz(), 就叫它什么吧。为什么要写$person->getName() 你什么时候可以$person->name()? 简单得多$person->setName() 你什么时候可以$person->rename()?
  • 但最重要的是,这里真的需要对象吗?让东西面向对象并不意味着你在写更好的代码,它只是意味着你在尝试面向对象。如果您的对象没有内部状态,并且没有实现任何抽象接口,那么您从使用类中一无所获,这不是OO。

    不要把函数弄得一团糟,把它们封装在一个类中,假装它是OO,不是,只是给你额外的键入。所以省去你的麻烦吧。插件的入口点可以是一个函数。可以将快速过滤器作为普通函数,您不必将所有内容都放在一个类中。

    你可能正在学习,但不要强迫自己以“OO”为幌子使用课程,这不是OO,你只是在学习坏习惯。

    SO网友:Jess_Pinkman

    编辑:如上所述,这不是wordpress上首选的解决方案,因为wordpress是无状态的。

    您的问题不是外部对象,而是数据持久性。我假设您希望通过用户会话实现数据持久性,因此可以使用$\\u session之类的东西(如果您希望通过用户会话实现持久性)

    所以,你的插件可以有这样的功能

    add_action( \'init\', \'instanciate_object\' );
    
    //Check if object already instanciated, if not, instanciate.
    function instanciate_object()
    {
      if ( !isset( $_SESSION[\'myObject\']) {
        $_SESSION[\'myObject\'] = new includedObject();
      }
    }
    
    然后,您的ajax处理程序将执行以下操作:

    function ajax_handler()
    {
      if ( isset( $_SESSION[\'myObject\'] ) {
          $object = $_SESSION[\'myObject\'];
          $object->setInstanceVar( $_REQUEST[\'newValue\']);
          $_SESSION[\'myObject\'] = $object;
      }
    }
    
    确保具有ajax\\U处理程序的文件确实可以访问类定义。