php:类懒惰加载?

时间:2010-07-27 11:41:43

标签: php

我有一个问题,这是我过去几天一直在考虑的问题。 在php应用程序中,您需要对对象执行某些操作:

  1. 定义
  2. 用它运行一个函数 像这样: (使用自动加载和注册表对象)
  3. $ registry-> obj = new mathClass($ var1,$ var2); //创建对象,其中$ var1保存数据库对象,$ var2保存值1,例如
  4. $登记处送交> obj->计算( '值'); //获取产品行并返回其总值。 这样在脚本的任何时候我都可以简单地运行我事先定义的计算函数(或其他一些函数)。
  5. 想象一下,这个特定页面加载可能需要或可能不需要数百个类的Web应用程序,但只能在应用程序的开头定义。 理想的解决方案是我只需运行

    $obj->calculate('price'); 
    

    不创建对象,例如像

    mathclass::calculate('price'); 
    

    然后根据需要自动加载数学类而不需要主要开销,这里的问题是我不能再在开始时给mathclass任何变量

    ($var1,$var2).
    

    我想要的是能够伪造对象而不需要对类发生任何自动加载,因为不添加开销,但是对象用变量创建自己,但只有当我实际需要做什么时才它

    我的意思是php真的希望我在开始时定义每个类,以便以后可以使用它们吗? 这是懒人装吗?急切加载?

    我可能会解释这个问题,所以请指出我正确的方向。

    编辑2015:简单的伪代码示例解决方案:

    class Service {
        private $cb, $instance;
        public function __construct($cb){
            $this->cb = $cb;
        }
        public function __invoke() {
            if(!$this->instance){
                $this->instance = call_user_func($this->cb);
            }
            return $this->instance;
        }
    }
    
    // setup autoloading
    set_include_path(__DIR__.'/vendor'. PATH_SEPARATOR .get_include_path()); // optional
    spl_autoload_register(function($c){
        include preg_replace('#\\\|_(?!.+\\\)#','/',$c).'.php';
    });
    
    // simple dependency injection
    $service['db'] = new Service(function(){
        return new Database('sqlite::filename.sqlite');
    });
    $service['config'] = function() use(&$service){
        return new Config($service['db']());
    };
    $service['math'] = function() use(&$service){
        return new Math($service['config']());
    };
    
    // usage
    $service['math']()->calculate('price');
    

5 个答案:

答案 0 :(得分:4)

使用Dependency Injection Framework。它允许您从配置文件配置类,当您需要类时,只需通过服务构建器调用它。

答案 1 :(得分:3)

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

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你需要添加我懒得添加的部分,即自动加载。

答案 2 :(得分:2)

如果使用自动加载功能,它只会在实例化时加载数学类,1选项是在需要时实例化它,另一种选择是使用某种包含并调用类的包装类。

答案 3 :(得分:0)

您可以使用的是PHP中的静态类。虽然您可能认为这不适用于高流量网站。

声明一个类似的类:

class Something
{
    private static $var = "something";

    public static function PrintVar()
    {
        echo self::$var;
    }
}

现在,您可以包含此类并在任何您喜欢的位置执行代码,而无需初始化对象。

像这样:

Something::PrintVar();

打印

something
祝你好运!

答案 4 :(得分:0)

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

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

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

然后你不必处理为一个简单例程定义一个完整类的全部痛苦。