【问题标题】:PHP static variables and old dataPHP静态变量和旧数据
【发布时间】:2018-08-16 10:39:11
【问题描述】:

我从事的项目是由其他开发人员启动的。该项目有一个帮助类,它将接受输入并从一些异地注册表中获取数据。

这个类很简单,它唯一要做的就是获取数据。 我的老板让我使用这个帮助类来创建另一个接口。

所以我做到了。我得到了这个类,围绕它构建了我的界面并处理了结果。只要我给出单个输入,一切都可以,例如“用户”。当我将辅助函数放入一个循环中时,一切都会崩溃。

我必须通知你,帮助类中的函数是一个静态函数,它对某些注册表有一个循环。每个注册表的返回通过注册表函数写入一个通用静态变量。每次调用注册表后,静态变量都会返回到接口。

结果是在循环的某些迭代中我得到了错误的数据,更具体地说,我得到了前一个用户的数据。

如果每次迭代我都将静态变量预设为“[]”,那么一切都按预期工作。

例如:

class Helper {
    private static $results = [];

    public static askRegistries ($userId) {
        $registries = ['registry1','registry2','registry3'];

        foreach($registries as $registry) {
            self::callRegistry($userId, $registry);
        }

        return self::$results;
    }

    private static callRegistry($userId, $registry) {
        self::$results[] = getData($userId)
    }
}

通过上面的例子,我试图向你解释如何将数据设置为静态变量并返回到接口。

问题 #1

这个静态函数每次调用静态变量是否正常 保留旧数据?

问题 #2

如果正常,能解释一下原因吗?

问题 #3

再次如果正常,解决此问题的正确方法是什么 无需对代码进行任何重大更改,因为它被禁止 我的老板?

编辑#1

问题 #4 如果我将对静态方法 callRegistry 的调用更改为附加到静态变量的注册表类,还有什么我应该记住的吗?

例如

class Helper {
    public static $results = [];

    public static askRegistries ($userId) {
        $registries = ['Registry1','Registry2','Registry3'];

        foreach($registries as $registry) {
            $registryClass = new {$registry}();
            $registryClass->query($userId);
        }

        return self::$results;
    }
}

class Registry1{   
    public query($userId) {
        Helper::results = doSomething();
    }
}

在本例中,静态变量是公共的。

【问题讨论】:

  • 我认为这是正常行为,因为静态变量是保持状态的手段。 electrictoolbox.com/php-static-variables
  • 谁是getData,为什么在callRegistry 中还需要registry
  • @Edwin 这是一个示例,展示了用于将数据从帮助程序类返回到接口的逻辑。它所写的任何东西都没有真正的意义。
  • @hanishsingla 我会看看你给我的链接,因为我必须向我的主管报告这个问题。
  • 一个接口不能保存任何数据,什么意思?

标签: php static static-methods


【解决方案1】:

首先,静态函数和静态变量属于类而不是类对象。

上面的陈述得出结论,静态变量和方法总是意味着直接从类中调用,例如MyClass::function() 和 MyClass::$var

类中的静态变量从不意味着处理状态。所以你绝不能改变一个类的静态变量。改用常量。

如果要将数据存储在变量中,只需在类中定义一个普通(私有、受保护或公共)变量,然后通过类的对象对其进行更新。

如果您在循环中调用 callRegistry(),明智的做法是将 Helper::$results 重置为空数组,因为您在循环中传递的每个用户都将添加到 Helper::$results。这反过来会影响您的 RAM,因为所有这些数据都作为状态存储,直到您的脚本结束。 https://alanstorm.com/php-meminfo-and-memory-leaks/

我认为它应该可以解决您的问题

class Helper {
    private $results = [];

    public static askRegistries ($userId) {
        $registries = ['registry1','registry2','registry3'];

        foreach($registries as $registry) {
            self::callRegistry($userId, $registry);
        }

        return self::$results;
    }

    private callRegistry($userId, $registry) {
        $this->results[] = getData($userId)
    }
}

$helper = new Helper();

foreach($userIds as $userId){
    $helper->callRegistry($userId, $registry);
}

【讨论】:

    【解决方案2】:

    这个静态函数每次调用静态变量保留旧数据是否正常?

    如果正常,能解释一下原因吗?

    这很正常。静态变量存储在类中,而不是类的特定实例中。使用 1 个实例更新静态变量将为所有实例更新它。

    由于此帮助程序类与静态变量的唯一交互是附加到它,因此它会在您每次使用它时构建并构建并构建此静态变量。

    再次如果正常,在不对代码进行任何重大更改的情况下解决此问题的正确方法是什么,因为我的老板禁止这样做?

    我个人会将private 属性和方法的范围更改为protected

    我会将callRegistry 的行为更改为:

    1. 将来自 getData($userId) 的响应分配给局部变量
    2. 将此局部变量附加到self::$results
    3. 返回局部变量

    然后我会编写一个类来扩展Helper,并使用一个函数来覆盖askRegistries 的行为以返回一个本地数组。像这样:

    // Give the class a real name of course
    class ExtendedHelper extends Helper {
    
        public static function askRegistries ($userId) {
            $output = array();
            $registries = ['registry1','registry2','registry3'];
    
            foreach($registries as $registry) {
                $output[] = self::callRegistry($userId, $registry);
            }
    
            return $output;
        }
    
    }
    

    您可能希望在父类中也将$registries 存储为静态变量,这样您就不会在子类中重新定义它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-11
      • 2020-07-13
      • 2012-11-23
      • 1970-01-01
      • 1970-01-01
      • 2011-06-25
      相关资源
      最近更新 更多