簡體   English   中英

根據需要實例化定義為PHP類中的屬性的對象(延遲加載)

[英]Instantiate object defined as property in a PHP class as needed (lazy loading)

為簡單起見,假設我有2個類,即Web應用程序中使用的User和UserStatus。

<?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()調用並即時創建該對象?

一個重要的注意事項是, 我需要UserStatus類中的$user_id可用 ,否則fetchDataFromDB()方法將不知道應該向哪個用戶讀取數據。 應該怎么做?

我已經看過一些有趣的東西,例如Fabien Potencier的《 什么是依賴注入? Pimple-一個PHP 5.3依賴項注入容器,以及一些有關Proxy Pattern的文章,但是要實現它們,看起來我不得不對當前的代碼感到困惑。 有沒有更簡單的方法?

也許我錯過了一些東西,但是在這種情況下,最簡單的解決方案似乎是讓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();
   }
}

通過在__get執行$user->status時使用__get magic方法,它將調用$user->getStatus() 當然,您也總是可以像這樣訪問它: $user->getStatus()->getIcon()

但是,您決定設置訪問屬性的權限,因此建議您在整個模型中以一致的方式進行操作。

您可以將狀態類放在其他文件中,然后利用php的自動加載機制:

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

在您訪問該文件之前不要加載該文件。

有傳言說自動加載(或實際上只是任何一種條件加載)對於字節碼緩存和優化器來說都是麻煩的,盡管不幸的是,我對此影響不甚了解。

PS:手冊在這一點上並沒有明確指出:您還可以使用spl_autoload_register()而不是僅定義魔術__autoload函數。 這稍微更強大。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM