Проверить, выполняется ли функция из статического контекста

#php #oop #static

#php #ооп #статический

Вопрос:

Я пишу класс PHP и включил пару статических функций для быстрого доступа, поскольку они обычны в использовании и просты в функционировании. Однако они используют объект в них для доступа к базе данных. Скорее всего, я буду использовать эти статические методы как из статического, так и из нестатического контекста во всем своем коде, поэтому я хочу иметь возможность проверить, была ли функция вызвана из статического или нестатического контекста, чтобы я мог избежать создания дублирующего объекта, если функция была вызвана из нестатического контекста (этот экземпляр объекта и тот, который внутри функции будет использоваться статически). Есть ли какой-либо способ, которым я могу протестировать это в функции, чтобы я мог использовать объект экземпляра, если функция вызывается из нестатического контекста, и создать свой собственный объект, если функция вызывается из статического контекста?

Пример кода:

 class MyClass {
  private $db;

  function __constuct(){
    $this->db = new DBConnect();
  }

  public static function myFunction(){
    if(/* Is static */){
      $db = new DBConnect();
    } else {
      $db =amp; $this->db;
    }
    // Do processing with $db, etc.
  }
}
  

Комментарии:

1. 5 ответов, ни одного голоса за вопрос.

Ответ №1:

Когда метод объявлен как статический, не только недоступна магическая переменная $this (возвращает NULL), но и невозможно определить, действительно ли функция была вызвана из статического контекста. Обратная трассировка подразумевает, что для статического метода вызов $object->method() внутренне преобразуется в className::method() во время выполнения.

http://php.net/manual/en/language.oop5.static.php

Комментарии:

1. Спасибо за это, Шакти, это отвечает на мой вопрос. Мне просто нужно будет создать объект для каждого из статических методов внутри, если я захочу использовать их из статического контекста.

2. Или кажется, что я мог бы просто объявить $db переменную экземпляра как статическую. Использование private static для чего-то просто кажется мне странным.

Ответ №2:

Вы можете проверить наличие нестатического доступа, только если вы не заставляете метод быть только статическим. Исключите static ключевое слово из объявления функции и протестируйте с:

 public function myFunction(){
    if(!isset($this)) {
  

(Она все еще может вызываться как статическая функция, даже если вы не объявляли ее как таковую.)

Комментарии:

1. Не приводит ли статический доступ к функции без ключевого слова static к ошибке?

2. Это действительно генерирует уведомление или предупреждение E_STRICT (не уверен в классификации). По крайней мере, в той версии, которая у меня есть. (Эти вещи, как правило, иногда устаревают и не рекомендуются.)

Ответ №3:

Итог — не создавайте классы, которые содержат только статические функции. Это не ООП, это просто ваш старый процедурный код, маскирующийся под ооп

Если вы выполняете функции статически, $ this отсутствует, поскольку нет объекта. В конечном итоге вы также создадите private $db статическую переменную и будете использовать ее как self::$db .

Тем не менее, я бы рекомендовал отказаться от этого шаблона и написать что-то вроде :

 class Foobar
{

   protected $_connection = null;

   public function __construct( DBConnect $db )  
   {
      $this->_connection = $db;
   }

   public function some_function()
   {
      $db = $this->_connection;
      // Do processing with $db, etc.
   }

}
  

И вы используете этот класс следующим образом :

 $db = new DBConnection(  /* your password , user , host , etc. */);

$stuff = new FooBar( $db );
$stuff->some_function();

$blah = new DifferentClass( $db );
  

Таким образом, вы используете одно и то же соединение со всеми классами, которым это требуется. И теперь класс FooBar не несет ответственности за установление соединения или должен знать ваши данные о соединении.

Ответ №4:

Решение 1. Сделайте $db переменную закрытой и используйте ее через средство получения.

Решение 2. Реализуйте одноэлементный шаблон на стороне dbal.

Ответ №5:

Даже при вызове статического метода из экземпляра (не рекомендуется) у вас нет доступа к $this , поэтому ваш класс будет фатальным.

 class sns {
   public static function moo() {
      var_dump($this->fng);
   }
   public function goo() {
      var_dump($this);
   }
}

sns::moo();
$_ = new sns;
$_->moo();
$_->goo();
  

Как указано в другом постере из руководства по php.

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