根据需要实例化PHP类中定义为属性的对象(延迟加载)

根据需要实例化PHP类中定义为属性的对象(延迟加载),php,lazy-loading,magic-methods,proxy-pattern,Php,Lazy Loading,Magic Methods,Proxy Pattern,为了简单起见,假设我有两个类,User和UserStatus,用于Web应用程序 <?php // library code: class UserStatus { protected $_status = NULL; private function fetchDataFromDB() { // regular DB stuff $this->_status = ... // result will be something like 'onli

为了简单起见,假设我有两个类,User和UserStatus,用于Web应用程序

<?php

// library code:
class UserStatus {
  protected $_status = NULL;

  private function fetchDataFromDB() {
    // regular DB stuff
    $this->_status = ...
    // result will be something like 'online', 'away', etc. 
  }

  public function getIcon() {
    global $icon_array;

    if (is_null($this->_status)) {
      $this->fetchDataFromDB()
    }
    return $icon_array[$this->_status];
  }
}

class User {
  protected $user_id;
  public $user_name;
  protected $status;

  public function __construct() {}

  public static function getAll() {
    // some DB stuff
    return $users;
  }
}

// and now, in index.php:
$users = User::getAll();

// echoes the icon to use to reflect the current user status

foreach ($users as $user) {
  echo <img src="$user->status->getIcon()"/>;
}

?>

您可以将status类放在不同的文件中,然后利用php的自动加载机制:

在访问该文件之前不加载该文件

有传言说,自动加载(或者实际上只是任何类型的条件加载)对字节码缓存和优化器来说都很麻烦,但不幸的是,我对其影响不太了解


注:本手册并未明确说明rhis:您也可以使用spl_autoload_register(),而不仅仅是定义magic__自动加载函数。这稍微更强大。

您可以将status类放在不同的文件中,然后利用php的自动加载机制:

在访问该文件之前不加载该文件

有传言说,自动加载(或者实际上只是任何类型的条件加载)对字节码缓存和优化器来说都很麻烦,但不幸的是,我对其影响不太了解


注:本手册并未明确说明rhis:您也可以使用spl_autoload_register(),而不仅仅是定义magic__自动加载函数。这稍微更强大。

也许我遗漏了一些东西,但在这种情况下,似乎最简单的解决方案是让状态的getter在不存在的情况下创建对象

public function getStatus()
{
  if(!isset($this->status))
  {
     // or however you creat this object..
     $this->status = new UserStatus($this->user_id);
  }

  return $this->status;
}

public function __get($property)
{
   $method = 'get'.ucfirst($property); // getStatus
   if(method_exists($this, $method)) 
   {
      return $this->$method();
   }
}
通过使用
\u get
魔术方法,只要您执行
$user->status
操作,它就会调用
$user->getStatus()
。当然,您也可以像这样访问它:
$user->getStatus()->getIcon()


无论您决定如何设置访问属性,我都建议您在整个模型中以一致的方式进行设置。

也许我遗漏了一些东西,但在这种情况下,最简单的解决方案似乎是让您的getter for Status在对象不存在的情况下创建对象

public function getStatus()
{
  if(!isset($this->status))
  {
     // or however you creat this object..
     $this->status = new UserStatus($this->user_id);
  }

  return $this->status;
}

public function __get($property)
{
   $method = 'get'.ucfirst($property); // getStatus
   if(method_exists($this, $method)) 
   {
      return $this->$method();
   }
}
通过使用
\u get
魔术方法,只要您执行
$user->status
操作,它就会调用
$user->getStatus()
。当然,您也可以像这样访问它:
$user->getStatus()->getIcon()


无论您决定如何设置访问属性,我建议您在整个模型中以一致的方式进行设置。

这确实是一种方法,但是
UserStatus
类提供了几种方法,其中一种方法是
getIcon()
,如上所示。根据您的建议,我必须在两步过程中调用icon方法:
$user->getStatus()$用户->状态->获取图标()
。我想让它更聪明,但嘿,它起作用了。谢谢。不,你不能。你可以使用magiv
\uu get
我以为你会这么做,因为
状态
是受保护的,不是公共的-否则你不能直接从用户类之外访问它。。。所以我没有包括它。。。查看我的更新。是的,我的想法是使用
\uu get()
,我故意让
状态处于保护状态,但我没有编写
\uu get()
,只是因为我不知道最好的方法。你的更新解决了我的疑问,这是一个非常好的方法,我很乐意接受。再次感谢。关于以一致的方式做这件事,这是一个很好的建议,我现在不尊重:(我正在考虑使用诸如DependencyInjection和EventDispatcher之类的Symfony组件重写我的自制框架,但我仍然对如何布局它们感到困惑。这确实是一种方法,但
UserStatus
类提供了几种方法,其中一种是
getIcon()
如上所示。根据您的建议,我必须在两步过程中调用icon方法:
$user->getStatus();$user->status->getIcon()
。我想让它变得更聪明,但是,嘿,它很管用。谢谢。不,你不能。你可以使用magiv
\uu get
我假设你会这样做,因为
状态是受保护的,不是公共的-否则你不能直接从你的用户类之外访问它…所以我没有包括它…查看我的更新。是的,这个想法是使用
\uu get()
我故意让
状态处于受保护状态,但我没有编写
\uu get()
仅仅是因为我不知道如何做到这一点的最佳方法。您的更新解决了我的疑问,这是一个非常好的方法,我很乐意接受。再次感谢。关于以一致的方式做到这一点,这是一个很好的建议,我现在并不尊重:(我正在考虑使用诸如DependencyInjection和EventDispatcher之类的Symfony组件重写我的自制框架,但我仍然对如何布局它们感到有点困惑。我有几个小类,每个类都放在一个文件中并不是我想做的事。我将尝试用类似于prodigita的东西来解决这个问题lson建议,如果不起作用,请回到这里。谢谢。我有几个小班,每个班都放在一个文件中,这不是我想做的。我将尝试按照prodigitalson的建议解决这个问题,如果不起作用,请回到这里。谢谢。