Как проверить класс объекта в среде PHP с пространством имен без указания полного класса пространства имен.
Например, предположим, у меня была библиотека объектов / Entity / Contract / Name.
Следующий код не работает, так как get_class возвращает полный класс пространства имен.
If(get_class($object) == 'Name') {
... do this ...
}
Волшебное ключевое слово пространства имен возвращает текущее пространство имен, которое бесполезно, если у тестируемого объекта есть другое пространство имен.
Я мог бы просто указать полное имя класса с пространствами имен, но это, кажется, блокирует структуру кода. Также не очень полезно, если я хотел динамически изменить пространство имен.
Может кто-нибудь придумать эффективный способ сделать это. Я думаю, что один из вариантов это регулярное выражение.
php
class
namespaces
Greg.Forbes
источник
источник
Ответы:
Вы можете сделать это с отражением. В частности, вы можете использовать
ReflectionClass::getShortName
метод, который получает имя класса без его пространства имен.Сначала вам нужно создать
ReflectionClass
экземпляр, а затем вызватьgetShortName
метод этого экземпляра:Однако я не могу представить много обстоятельств, когда это было бы желательно. Если вы хотите требовать, чтобы объект был членом определенного класса, способ проверить это с
instanceof
. Если вам нужен более гибкий способ сигнализации определенных ограничений, то для этого нужно написать интерфейс и потребовать, чтобы код реализовывал этот интерфейс. Опять же, правильный способ сделать это сinstanceof
. (Вы можете сделать это сReflectionClass
, но это будет иметь гораздо худшую производительность.)источник
Tenant
что не существует в текущем пространстве имен. Попробуйvar_dump($tenant instanceof \Library\Entity\People\Tenant)
вместо этого. Кроме того, исследуйте, как использоватьuse
оператор, и общую концепцию пространств имен PHP!$reflect = new \ReflectionClass($object);
str_replace(__NAMESPACE__ . '\\', '', __CLASS__);
. Это также намного быстрее, с точки зрения производительности.(new \ReflectionClass($obj))->getShortName();
является лучшим решением в отношении производительности.Мне было любопытно, какое из представленных решений является самым быстрым, поэтому я собрал небольшой тест.
Полученные результаты
Код
Результаты на самом деле удивили меня. Я думал, что решение взрыва будет самым быстрым способом ...
источник
Я добавил substr в тест https://stackoverflow.com/a/25472778/2386943, и это самый быстрый способ тестирования (CentOS PHP 5.3.3, Ubuntu PHP 5.5.9) для i5.
Полученные результаты
Код
== UPDATE ==
Как уже упоминалось в комментариях @MrBandersnatch, есть еще более быстрый способ сделать это:
Вот обновленные результаты теста с «SubstringStrChr» (экономит примерно до 0,001 с):
источник
str_replace(__NAMESPACE__ . '\\', '', __CLASS__);
. Результаты на слабой виртуальной машине показали, что она почти в два раза быстрее всех этих.php -f bench.php Reflection: 0.44037771224976 s ClassA Basename: 0.48089025020599 s ClassA Explode: 0.54955270290375 s ClassA Substring: 0.38200764656067 s ClassA Frank's Custom Benchmark: 0.22782742977142 s ClassA
if ($pos = strrchr(static::class, '\\')) { .. } else { ... }
.$classNameShort = substr(strrchr('\\' . get_class($this), '\\'), 1);
Вот более простой способ сделать это, если вы используете Laravel PHP Framework:
источник
Я использую это:
источник
Чтобы получить короткое имя как однострочное (начиная с PHP 5.4 ):
Это чистый подход и разумно быстро .
источник
Я оказался в уникальной ситуации, когда ее
instanceof
нельзя было использовать (в частности, в чертах пространства имен), и мне нужно было короткое имя наиболее эффективным способом, поэтому я сделал небольшой собственный тест. Он включает в себя все различные методы и варианты ответов на этот вопрос.Список полного результата здесь, но вот основные моменты:
$obj->getShortName()
самый быстрый метод , однако , используя только отражение для получения короткого имени, это почти самый медленный метод.'strrpos'
может вернуть неправильное значение, если объект не находится в пространстве имен, поэтому пока'safe strrpos'
он немного медленнее, я бы сказал, что это победитель.'basename'
совместимости между Linux и Windows вам необходимо использоватьstr_replace()
этот метод, который делает этот метод самым медленным из всех.В упрощенной таблице результатов скорость измеряется по сравнению с самым медленным методом:
источник
Вы можете использовать
explode
для разделения пространства имен иend
для получения имени класса:источник
Yii путь
Yii использует этот метод в своем генераторе кода Gii
Методическая документация
Больше информации:
https://github.com/yiisoft/yii2/blob/master/framework/helpers/BaseStringHelper.php http://www.yiiframework.com/doc-2.0/yii-helpers-basestringhelper.html#basename()-detail
источник
Вот простое решение для PHP 5.4+
Что будет возвращаться?
Расширенное имя класса и пространство имен работают хорошо для:
Как насчет класса в глобальном пространстве имен?
источник
Если вам нужно знать имя класса, которое было вызвано из класса, и вам не нужно пространство имен, вы можете использовать это
Это замечательно, когда у вас есть метод внутри класса, который расширяется другими классами. Кроме того, это также работает, если пространства имен вообще не используются.
Пример:
источник
Основываясь на ответе @MaBi, я сделал это:
Что вы можете использовать так:
A::class
возвращаетсяFoo\Bar\Baz\A
, ноA::getClassShortName()
возвращаетсяA
.Работает на PHP> = 5.5.
источник
Я знаю, что это старый пост, но это то, что я использую - быстрее, чем все вышеперечисленное, просто вызовите этот метод из вашего класса, намного быстрее, чем с помощью Reflection
источник
Нашел на странице документации get_class , где он был размещен мной на nwhiting dot com .
Но идея пространств имен состоит в том, чтобы структурировать ваш код. Это также означает, что вы можете иметь классы с одним и тем же именем в нескольких пространствах имен. Таким образом, теоретически объект, который вы передаете, может иметь имя класса (обрезанное), но при этом он будет совершенно другим объектом, чем вы ожидаете.
Кроме того, вы можете проверить наличие определенного базового класса , и в этом случае
get_class
ничего не получится. Вы можете проверить оператораinstanceof
.источник
Вы можете получить неожиданный результат, когда у класса нет пространства имен. Т.е.
get_class
возвращаетсяFoo
, тогда$baseClass
быoo
.Это может быть легко исправлено путем добавления префикса
get_class
с обратной косой чертой:Теперь также классы без пространства имен будут возвращать правильное значение.
источник
Старый добрый regex кажется быстрее, чем большинство предыдущих показанных методов:
Так что это работает, даже если вы предоставляете краткое имя класса или полностью определенное (каноническое) имя класса.
Регулярное выражение использует все предыдущие символы до тех пор, пока не будет найден последний разделитель (который также используется). Таким образом, оставшаяся строка будет кратким именем класса.
Если вы хотите использовать другой разделитель (например, /), просто используйте вместо этого этот разделитель. Не забудьте избежать обратной косой черты (т. Е. \), А также шаблона char (т. Е. /) Во входном шаблоне.
источник
Поскольку «ReflectionClass» может зависеть от версии, просто используйте следующее:
или даже очистить
источник
Цитирую php.net:
Исходя из этой информации и расширения от ответа arzzzen, это должно работать как в системах Windows, так и в системах Nix *:
Примечание. Я провел тестирование
ReflectionClass
сbasename+str_replace+get_class
использованием отражения и примерно на 20% быстрее, чем при использовании подхода с базовым именем, но с YMMV.источник
Самое быстрое и простое решение, которое работает в любой среде:
источник
$Object->__class->getShortName()
меня бесит PHP. Ваш подход работает, но теперь вы добавляете конкретные методы в ваши классы, просто чтобы показать, что должно быть языковой конструкцией.источник
Если вы просто удаляете пространства имен и хотите что-нибудь после последнего \ в имени класса с пространством имен (или просто именем, если нет '\'), вы можете сделать что-то вроде этого:
По сути, это регулярное выражение для получения любой комбинации символов или обратной косой черты вверх и до последнего обратного слеша, чтобы возвращать только символы без обратной косой черты вверх и до конца строки. Добавление? после первой группировки означает, что совпадение с образцом не существует, оно просто возвращает полную строку.
источник
Самый быстрый, который я нашел здесь
PHP 7.2
наUbubntu 18.04
источник