Как я могу получить имя класса из статического вызова в расширенном классе PHP?

93

У меня два класса: Actionи MyAction. Последний объявлен как:

class MyAction extends Action {/* some methods here */}

Все, что мне нужно, это метод в Actionклассе (только в нем, потому что будет много унаследованных классов, и я не хочу реализовывать этот метод во всех из них), который вернет имя класса из статического вызова. Вот о чем я говорю:

Class Action {
 function n(){/* something */}
}

И когда я это называю:

MyAction::n(); // it should return "MyAction"

Но каждое объявление в родительском классе имеет доступ только к __CLASS__переменной родительского класса , которая имеет значение «Action».

Есть ли способ сделать это?

Антон
источник

Ответы:

176

__CLASS__всегда возвращает имя класса, в котором он использовался, поэтому статический метод не очень помогает. Если бы метод не был статическим, вы могли бы просто использовать get_class ($ this). например

class Action {
    public function n(){
        echo get_class($this);
    }

}

class MyAction extends Action {

}

$foo=new MyAction;

$foo->n(); //displays 'MyAction'

Поздние статические привязки, доступные в PHP 5.3+

Теперь, когда выпущен PHP 5.3, вы можете использовать поздние статические привязки , которые позволяют разрешать целевой класс для вызова статического метода во время выполнения, а не тогда, когда он определен.

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

Class Action {
    public static function n() {
        return get_called_class();
    }
}


class MyAction extends Action {

}


echo MyAction::n(); //displays MyAction
Пол Диксон
источник
Единственная проблема для OP заключается в том, что функция еще не доступна. PHP 5.3 пока находится в стадии бета-тестирования.
Ionuț G. Stan
3
@ Пол, спасибо! Ты только что спас мне день ... или ночь с get_called_class():)
Марекки
1
Я бы хотел, чтобы кто-нибудь помог мне с подобной проблемой . Сценарий PHP молча умирает при выполнении new static();изнутри частного статического метода (с использованием xampp в Windows и php> 5.5). :s
Stphane
$ foo = новое MyAction; эхо get_class ($ foo); Это также печатает MyAction.
Sammry
41

Начиная с версии 5.5 вы можете использовать classключевое слово для разрешения имени класса , что будет намного быстрее, чем выполнение вызовов функций. Также работает с интерфейсами.

// C extends B extends A

static::class  // MyNamespace\ClassC when run in A
self::class    // MyNamespace\ClassA when run in A
parent::class  // MyNamespace\ClassB when run in C
MyClass::class // MyNamespace\MyClass
Ян Бытчек
источник
16

Это не идеальное решение, но оно работает на PHP <5.3.0.

Код скопирован с septuro.com

if(!function_exists('get_called_class')) {
    class class_tools {
        static $i = 0;
        static $fl = null;

        static function get_called_class() {
            $bt = debug_backtrace();

            if (self::$fl == $bt[2]['file'].$bt[2]['line']) {
                self::$i++;
            } else {
                self::$i = 0;
                self::$fl = $bt[2]['file'].$bt[2]['line'];
            }

            $lines = file($bt[2]['file']);

            preg_match_all('/([a-zA-Z0-9\_]+)::'.$bt[2]['function'].'/',
                $lines[$bt[2]['line']-1],
                $matches);

            return $matches[1][self::$i];
        }
    }

    function get_called_class() {
        return class_tools::get_called_class();
    }
}
Jrgns
источник
2
class MainSingleton { 
  private static $instances = array(); 
  private static function get_called_class() {
    $t = debug_backtrace();
    return $t[count($t)-1]["class"];
  }  

  public static function getInstance() { 
    $class = self::get_called_class();
    if(!isset(self::$instances[$class]) ) { 
      self::$instances[$class] = new $class; 
    } 
    return self::$instances[$class]; 
  } 

}

class Singleton extends MainSingleton { 
  public static function getInstance()
  {
    return parent::getInstance();
  }     
  protected function __construct() { 
    echo "A". PHP_EOL; 
  } 

  protected function __clone() {} 

  public function test() { 
    echo " * test called * "; 
  } 
} 

Singleton::getInstance()->test(); 
Singleton::getInstance()->test();
Лулу
источник
0

В доступных версиях PHP нет возможности делать то, что вы хотите. Решение Пола Диксона - единственное. Я имею в виду пример кода, поскольку функция поздних статических привязок, о которой он говорит, доступна с PHP 5.3, которая находится в стадии бета-тестирования.

Ионуй Г. Стан
источник
0

(PHP 5> = 5.3.0, PHP 7)
get_called_class - Имя класса «Поздняя статическая привязка».

<?php

class Model
{
  public static function find()
  {
    return get_called_class();
  }
}

class User extends Model
{
}


echo User::find();

эта ссылка может быть полезна

Бисваджит Бисвас
источник