0

为简单起见,假设我有 2 个类,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()"/>;
}

?>

在大多数 HTTP 请求中,不会使用状态对象,因此我正在寻找一种仅根据需要实例化它的方法(称为延迟加载)。我应该如何拦截status->method()呼叫并即时创建该对象?

一个重要的注意事项是我需要$user_id在 UserStatus 类中可用,否则该fetchDataFromDB()方法将不知道它应该向哪个用户获取数据。这应该怎么做?

我看过一些关于这个问题的有趣的东西,比如 Fabien Potencier 的什么是依赖注入?Pimple - 一个 PHP 5.3 依赖注入容器以及一些关于代理模式的文章,但要实现它们,看起来我必须对当前代码进行很多处理。有没有更简单的方法?

4

2 回答 2

3

也许我错过了一些东西,但似乎在这种情况下最简单的解决方案是让你的状态获取器简单地创建对象,如果它不存在......

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();
   }
}

通过在__get任何时候使用魔法方法,$user->status它都会调用$user->getStatus(). 当然,您也可以总是像这样访问它:$user->getStatus()->getIcon()以及。

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

于 2011-02-06T04:58:46.680 回答
1

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

http://php.net/manual/de/language.oop5.autoload.php

在您访问它之前不要加载该文件。

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

PS:手册在这一点上没有明确说明:您也可以使用 spl_autoload_register() 而不是仅仅定义神奇的 __autoload 函数。这个功能稍微强大一些。

于 2011-02-06T04:57:07.083 回答