Как получить имя класса PHP
Как в родительском классе получить имя класса, который вызвал действие?
Существуют так называемые «Волшебные константы», о которых можно почитать в официальном мануале.
Для решения вашей задачи определите метод, в котором возвращаете __CLASS__ , либо, как написал Etki — get_class($this) .
Метод вернет полное название класса вместе с пространством имен. Чтобы получить только имя класса, можно разбить строку по \ и взять последний элемент.
Дизайн сайта / логотип © 2023 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2023.3.11.43304
Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.
Узнайте, какой класс вызвал метод в другом классе
Есть ли в PHP способ узнать, какой объект вызвал какой метод в другом объекте.
Могу ли я узнать, что тестовый метод был вызван из объекта foo?
задан 31 июля ’09, 15:07
8 ответы
вы могли бы использовать debug_backtrace , примерно так:
Кстати, взгляните на комментарии на странице руководства: здесь есть несколько полезных функций и советов 😉
Компания var_dump выведет:
Но, как бы хорошо это ни выглядело, я не уверен, что его следует использовать как «нормальную вещь» в вашем приложении . На самом деле это кажется странным: при хорошем дизайне методу не нужно знать, как он его вызвал. , по моему мнению.
Создан 31 июля ’09, 19:07
Рабочие примеры — это всегда приятно. +1. 🙂 — Рандольфо
Спасибо 😉 (Они также являются причиной не получить первый ответ ^^ но, по крайней мере, я тоже получаю удовольствие от этого ;-)) — Паскаль МАРТИН
Спасибо за пример. Да, я в определенной степени согласен с тем, что методы не должны знать, но у меня есть другие люди, которые пишут код поверх того, что я пишу, и я хотел облегчить их жизнь, он же. Я думаю, что использовать отладку немного хакерски, но спасибо, вы дали мне хорошее представление о функции отладки, чего id никогда раньше не делал. — Botto
Добро пожаловать 🙂 и спасибо, что объяснили причину, по которой вам это было нужно! (Другим решением может быть использование отладчика, такого как предоставленный Xdebug, который может быть интегрирован с Eclipse PDT; см., Например, stackoverflow.com/questions/1199342/… и его ответы) — Паскаль МАРТИН
Вот одно решение для лайнера
Начиная с PHP7, это не будет работать на основе документов: http://php.net/manual/en/function.list.php поскольку у нас не может быть пустых свойств, вот небольшое обновление:
Разве вы не хотите написать? . list (, $ caller) = debug_backtrace (false, 2); // Или это пустая трата времени? — JxAxMxIxN
@JxAxMxIxN, что справедливо, сэкономит несколько циклов выполнения, изменилось. — Алексей Рашков
люблю мужчин одного лайнера. Спасибо — Suarsenegger
«Неустранимая ошибка: Uncaught Meets \ Service \ Error \ ErrorException: Undefined offset: 1 in . », если вызывается из основного скрипта или только из одного контекста. Проблема в list (), который ожидает 2 смещения. Если вы поместите результат debug_backtrace () в переменную и распечатаете его, это станет очевидным 🙂 — Коттон
Вы также можете передать вызывающий объект в качестве аргумента
Я получил эту идею из книги Эриха Гаммы и др. «Шаблоны проектирования: элементы объектно-ориентированного программного обеспечения многократного использования» на странице 278 в обсуждении структурного шаблона «Посредник».
Смысл шаблона — уменьшить количество соединений «многие ко многим» между группой объектов / классов. Вы создаете класс-посредник, который все эти классы рассматривают как концентратор. Таким образом, классам не нужно знать друг о друге. Посредник обрабатывает взаимодействия. Чтобы посредник был проинформирован об изменениях в классах, которые он отслеживает, они могут передавать себя в качестве аргументов, или посредник может быть реализован с использованием шаблона «Наблюдатель».
Иногда я использую интерфейсы с приведенным выше кодом, например:
ответ дан 05 мар ’18, в 02:03
Это было самое разумное решение, которое я мог придумать. Debug_backtrace выглядит как взлом, и другого способа навигации по стеку вызовов, о котором я знаю в PHP, нет. — силиконокстар
Вероятно, вы можете добиться этого с помощью отладка обратной трассировки, хотя это кажется хакерским.
Альтернативный вариант — передать параметр этому классу и сообщить ему, откуда он вызывается, когда вы создаете экземпляр класса из другого.
Создан 31 июля ’09, 19:07

Я уже рассматривал это раньше, и тогда казалось, что обратная трассировка была единственным вариантом. — UnkwnTech
По крайней мере, вы могли бы использовать debug_backtrace и проанализируйте это, чтобы найти вызывающий метод.
Я думаю, вы тоже сможете это сделать, используя API отражения, но я слишком давно не использовал PHP и не помню, как именно. Однако ссылки должны, по крайней мере, помочь вам начать работу.
Создан 31 июля ’09, 19:07
@Pascal MARTIN: Да, в обычных приложениях это, вероятно, не нужно. Но иногда это могло быть полезно. Рассмотрим пример из моего собственного приложения:
Есть подкласс Controller, который может использовать объект Template для подготовки вывода. У каждого шаблона есть имя, на которое можно ссылаться. Когда контроллеру нужен шаблон, он запрашивает его у TemplateManager, указывая это имя в качестве параметра. Но может быть много файлов шаблонов с таким именем для разных контроллеров. Контроллеры используются как плагины и могут быть написаны разными пользователями, поэтому используемые ими имена нельзя контролировать, чтобы они не конфликтовали друг с другом. Требуются пространства имен для шаблонов. Таким образом, TemplateManager, который является фабрикой для объектов Template, требуется имя шаблона и имя пространства имен, чтобы найти правильный исходный файл шаблона. Это пространство имен связано с именем класса конкретного контроллера.
Но в большинстве случаев каждый контроллер будет использовать шаблоны из своего собственного пространства имен и только в редких случаях из других пространств имен. Так что указывать пространство имен при каждом вызове TemplateManager :: getTemplate () каждый раз было бы беспорядком. Лучше, если пространство имен необязательно и по умолчанию . Контроллер, который вызывает TemplateManager :: getTemplate ()! А вот хорошее место, чтобы узнать звонящего.
Конечно, вызывающий контроллер может передать себя или свое имя в качестве параметра, но на самом деле это не сильно отличается от передачи имени пространства имен. В любом случае это не могло быть необязательным.
Но если вы знаете вызывающего абонента, вы можете использовать эту информацию для автоматического определения пространства имен по умолчанию внутри getTemplate (), даже не беспокоя вызывающего. Ему не обязательно знать, как getTemplate () обрабатывает его внутри и откуда ему известно правильное пространство имен по умолчанию. Ему нужно только знать, что это так, и что он может при желании передать любое другое пространство имен, если это действительно необходимо.
get_called_class
Gets the name of the class the static method is called in.
Parameters
This function has no parameters.
Return Values
Returns the class name. Returns false if called from outside a class.
Examples
Example #1 Using get_called_class()
class foo <
static public function test () <
var_dump ( get_called_class ());
>
>
class bar extends foo <
>
foo :: test ();
bar :: test ();
The above example will output:
See Also
- get_parent_class() — Retrieves the parent class name for object or class
- get_class() — Returns the name of the class of an object
- is_subclass_of() — Checks if the object has this class as one of its parents or implements it
User Contributed Notes 9 notes
As of PHP 5.5 you can also use «static::class» to get the name of the called class.
<?php
class Bar <
public static function test () <
var_dump (static::class);
>
>
class Foo extends Bar <
string(3) «Foo»
string(3) «Bar»
get_called_class() in closure-scopes:
<?PHP
ABSTRACT CLASS Base
<
protected static $stub = [ ‘baz’ ];
//final public function boot()
static public function boot ()
<
print __METHOD__ . ‘-> ‘ . get_called_class (). PHP_EOL ;
array_walk (static:: $stub , function()
<
print __METHOD__ . ‘-> ‘ . get_called_class (). PHP_EOL ;
>);
>
public function __construct ()
<
self :: boot ();
print __METHOD__ . ‘-> ‘ . get_called_class (). PHP_EOL ;
array_walk (static:: $stub , function()
<
print __METHOD__ . ‘-> ‘ . get_called_class (). PHP_EOL ;
>);
>
>
CLASS Sub EXTENDS Base
<
>
// static boot
Base :: boot (); print PHP_EOL ;
// Base::boot -> Base
// Base::
Sub :: boot (); print PHP_EOL ;
// Base::boot -> Sub
// Base::
I think it is worth mentioning on this page, that many uses of the value returned by get_called_function() could be handled with the new use of the old keyword static, as in
<?php
static:: $foo ;
?>
versus
<?php
$that = get_called_class ();
$that :: $foo ;
?>
I had been using $that:: as my conventional replacement for self:: until my googling landed me the url above. I have replaced all uses of $that with static with success both as
<?php
static:: $foo ; //and.
new static();
?>
Since static:: is listed with the limitation: «Another difference is that static:: can only refer to static properties.» one may still need to use a $that:: to call static functions; though I have not yet needed this semantic.
namespace root;
class Factor <
protected static $instance = null;
private function __construct() <
public static function getInstance() <
if (!self::$instance) <
$name = get_called_class();
self::$instance = new $name();
>
class Single extends Factor <
public function abc() <
return ‘abc’;
>
>
class Index <
public function get() <
return Single::getInstance();
>
>
Узнайте, какой класс вызвал метод в другом классе
Но, как как бы хорошо это ни выглядело, я не уверен, что его следует использовать как «нормальную вещь» в вашем приложении . На самом деле это кажется странным: при хорошем дизайне метод не должен знать, как он вызывается в моем приложении. мнение.
Вы также можете сделать так, чтобы вызывающий объект передал себя в качестве аргумента
Я получил эту идею из книги «Шаблоны проектирования: элементы многоразового объектно-ориентированного программного обеспечения» Эриха Гамма и др. На странице 278 в дискуссии о структурном паттерне «Посредник».
Смысл паттерна состоит в том, чтобы уменьшить количество соединений «многие ко многим» между группой объектов / классов. Вы создаете класс-посредник, который все эти классы рассматривают как концентратор. Таким образом, классы не должны знать друг о друге. Посредник обрабатывает взаимодействия. Чтобы посредник был проинформирован об изменениях в отслеживаемых классах, он может передавать себя в качестве аргументов или посредник может быть реализован с использованием шаблона «Наблюдатель».
Я иногда использую интерфейсы с приведенным выше кодом, например:
По крайней мере, вы можете использовать debug_backtrace и проанализировать его, чтобы найти вызывающий метод.
Я думаю, что вы также должны быть в состоянии сделать это с помощью API отражения , но прошло слишком много времени с тех пор, как я использовал PHP, и я точно не помню, как именно. Однако ссылки должны, по крайней мере, помочь вам начать.