php:类延迟加载?

php:类延迟加载?,php,Php,我这里有个问题,这几天我一直在想。 在php应用程序中,要对对象执行某些操作,您需要: 定义它 使用它运行函数 像这样: (带自动加载和注册表对象) $registry->obj=newmathclass($var1,$var2)//例如,创建一个对象,其中$var1保存数据库对象的值,而$var2保存值1 $registry->obj->calculate('value')//获取产品行并返回其总值。 这样,在脚本中的任何时候,我都可以简单地运行预先定义的计算函数(或其他函数) 想象一下,一个

我这里有个问题,这几天我一直在想。 在php应用程序中,要对对象执行某些操作,您需要:

  • 定义它
  • 使用它运行函数 像这样: (带自动加载和注册表对象)
  • $registry->obj=newmathclass($var1,$var2)//例如,创建一个对象,其中$var1保存数据库对象的值,而$var2保存值1
  • $registry->obj->calculate('value')//获取产品行并返回其总值。 这样,在脚本中的任何时候,我都可以简单地运行预先定义的计算函数(或其他函数)
  • 想象一下,一个web应用程序有数百个类,这些类对于这个特定的页面加载可能是必需的,也可能不是必需的,但只能在应用程序开始时定义。 理想的解决方案是我只需运行

    $obj->calculate('price'); 
    
    不创建对象,例如

    mathclass::calculate('price'); 
    
    然后根据需要自动加载mathclass,而不会产生主要开销,这里的问题是,我不能再在开始时为mathclass提供任何变量

    ($var1,$var2).
    
    我想要的是能够在不自动加载类的情况下伪创建对象,这样就不会增加开销,而是对象使用变量创建自己,但仅当我实际需要使用它时

    我的意思是,php真的希望我在一开始就定义每个类,以便以后使用它们吗? 这是延迟加载吗?急装

    我可能解释得很糟糕,所以请给我指出正确的方向

    编辑2015:简单伪代码示例解决方案:
    如果您使用自动加载功能,它将仅在实例化数学类时加载它,1个选项是在需要时实例化它,另一个选项是使用某种包装类,该类将包含并调用该类。

    在PHP中可以使用的是静态类。虽然这是你可能不考虑的高流量网站所做的事情。 这样声明一个类:

    class Something
    {
        private static $var = "something";
    
        public static function PrintVar()
        {
            echo self::$var;
        }
    }
    
    现在,您可以包含该类并在任何地方执行代码,而无需初始化对象

    像这样:

    Something::PrintVar();
    
    印刷品

    something
    

    祝你好运

    类对象需要使用
    new()
    定义的部分原因是它们消耗内存。通常情况下,如果您还没有这样做,PHP将在脚本末尾执行内存清理,但通常在构造函数/析构函数面向对象的环境中,您希望
    unset()
    该类对象以释放内存。由于这些原因,PHP的早期版本(在php4之前)存在内存泄漏问题

    如果要避免整个初始化过程,您可能只想尝试一个简单的包含库,例如:

    <?
    if (!function_exists("calculate"))
     {
     function calculate($var1={default},$var2={default}) 
       {
       ...routine...
       }
     }
    ?>
    
    
    

    这样,您就不必为一个简单的例程定义一个完整的类了。它允许您从配置文件配置类,当您需要一个类时,只需通过service builder调用它。

    您可以使用延迟加载工厂,即

    class Registry
    {
      private $registeredClasses;
      private $loadedClasses;
      private $objects;
    
      public function RegisterClass($className, array $parameters)
      {
        // ... store class ...
      }
    
      private function Load($className)
      {
         // Load the class via some sort of autoloader
      }
    
      private function CreateInstance($className)
      {
        $parameters = $this->GetParametersFor($className);
        $this->CreateNewInstanceWithParameters($className, $parameters);
      }
    
      public function GetObject($className)
      {
         if (!$this->IsAvailable($className))
         {
           $this->Load($className);
           $this->CreateInstance($className);
         }
         return $this->GetInstanceOf($className);
      }
    }
    
    在以后的代码中,您可以这样使用它:

    $registry = new Registry();
    $registry->RegisterClass("math", array("var1" => $var1, "var2" => $var2));
    ...
    
    $registry->GetObject("math")->calculate($x1, $x2);
    ...
    

    Ofc您需要添加我懒得添加的部分,即自动加载。

    您能给出一个更好的示例吗。您的
    calculate()
    只是添加了输入参数,因此它没有说明类中实际需要
    $var1
    $var2
    的原因。好的,我编辑了它,很抱歉我的解释不准确,但通常我的问题是因为我不能正确定义问题。如何在加载其他类之前预定义该类加载其他类的方式?您必须专门为该类(或某个可扩展类)创建一个包装类。检查类是否实例化为成员变量,如果不需要,则需要一次_并实例化。注意这个解决方案对我来说是次优。同意,这也是我遇到的问题之一。这更像是一个注册,不是吗?它主要是两者的混合。我之所以称之为Registry,是因为这个问题似乎使用了注册表,而且(取决于实现和使用情况)注册表和ServiceLocator是非常相关的。只是觉得服务定位器模式将是一个更合适的类名,因为它“不仅仅”是一个注册表。这是最接近解决方案的,我仍然在思考我的问题,所以请容忍我。这基本上与Gordon的答案相同,但没有解释如何使用它。最后,我将使用的是A.加载主配置文件B.配置文件导入类开始选项C.我调用类并根据需要加载,可惜没有2个最佳答案按钮。优秀的阅读,你一直在哪里找到这些选项。但它怎么也解决不了我的问题!(我的解释可能要怪我)@Yuri你可以在网站上找到这些文章的大部分。很抱歉,我没有得到你剩下的评论。你是说,它帮助解决了问题还是没有?如果没有,你需要什么帮助?谢谢戈登的帮助,我真的很感激。这里更好地描述了我遇到的问题:问题是:如何延迟加载依赖类。@Yuri如果使用DI容器,则需要配置类的实例化方式。当您需要它们时,您只需告诉容器获取一个特定的类,然后容器就会为您实例化它。这是相当懒惰的加载。这与@dbemerlin的解决方案非常相似。对不起,Gordon,我真的很想了解依赖项注入如何帮助延迟加载,以及如何配置类的实例化方式,你能更详细地解释一下吗?谢谢你的运气,但是静态类不是我想要的,因为即使不打算使用它们,也必须事先加载它们。
    $registry = new Registry();
    $registry->RegisterClass("math", array("var1" => $var1, "var2" => $var2));
    ...
    
    $registry->GetObject("math")->calculate($x1, $x2);
    ...