При необходимости создать объект, определенный как свойство в классе PHP (отложенная загрузка) - PullRequest
0 голосов
/ 06 февраля 2011

Для простоты предположим, что у меня есть 2 класса, 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() и создать этот объект на лету?

Важное замечание: Мне нужно $user_id, доступное в классе UserStatus , в противном случае *Метод 1010 * не будет знать, какому пользователю он должен получить данные.Как это должно быть сделано?

Я рассмотрел некоторые интересные вещи по этому вопросу, такие как Фабьена Потенциера «Что такое Dependency Injection?» * и Pimple - контейнер внедрения зависимостей PHP 5.3 , а также некоторые статьи о Proxy Pattern , но для их реализации, похоже, мне приходится много путаться с текущим кодом.Есть ли более простой способ?

Ответы [ 2 ]

3 голосов
/ 06 февраля 2011

Может быть, я что-то упустил, но, похоже, в данном случае проще всего было бы, чтобы ваш получатель статуса просто создал объект, если он не существует ...

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().

Однако вы решили настроить доступ к своим свойствам, и я бы порекомендовал делать это согласованно для всей вашей модели.

1 голос
/ 06 февраля 2011

Вы можете поместить класс статуса в другой файл, а затем использовать механизм автозагрузки php:

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

чтобы не загружать этот файл, пока вы не получите к нему доступ.

Ходят слухи, что автоматическая загрузка (или фактически любая условная загрузка) является проблематичной для кеша и оптимизаторов байт-кода, хотя, к сожалению, я не слишком много знаю о влиянии.

P.S .: В данном руководстве не говорится об этой простоте: вы также можете использовать spl_autoload_register () вместо того, чтобы просто определять магическую функцию __autoload. Это немного мощнее.

...