Php посмотреть все объекты

PHP — получить все имена классов в определенном пространстве имен

Я пробовал get_declared_classes() внутри getAllClasses() , но MyClass1 и MyClass2 не были в списке. Как я могу это сделать?

12 ответов

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

PHP предлагает некоторые встроенные функции для получения этих классов (get_declared_classes и т.д.), Но они не смогут найти классы, которые не были загружены (include/require), поэтому он не будет работать, как ожидается, с автозагрузчиками (например, Composer для пример). Это серьезная проблема, поскольку использование автозагрузчиков очень распространено.

Таким образом, ваше последнее средство — найти все файлы PHP самостоятельно и проанализировать их, чтобы извлечь их пространство имен и класс:

$path = __DIR__; $fqcns = array(); $allFiles = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)); $phpFiles = new RegexIterator($allFiles, '/\.php$/'); foreach ($phpFiles as $phpFile) < $content = file_get_contents($phpFile->getRealPath()); $tokens = token_get_all($content); $namespace = ''; for ($index = 0; isset($tokens[$index]); $index++) < if (!isset($tokens[$index][0])) < continue; >if (T_NAMESPACE === $tokens[$index][0]) < $index += 2; // Skip namespace keyword and whitespace while (isset($tokens[$index]) && is_array($tokens[$index])) < $namespace .= $tokens[$index++][1]; >> if (T_CLASS === $tokens[$index][0] && T_WHITESPACE === $tokens[$index + 1][0] && T_STRING === $tokens[$index + 2][0]) < $index += 2; // Skip class keyword and whitespace $fqcns[] = $namespace.'\\'.$tokens[$index][1]; # break if you have one class per file (psr-4 compliant) # otherwise you'll need to handle class constants (Foo::class) break; >> > 

Если вы следуете стандартам PSR 0 или PSR 4 (ваше дерево каталогов отражает ваше пространство имен), вам не нужно ничего фильтровать: просто укажите путь, который соответствует требуемому пространству имен.

Читайте также:  Create uml from java

Если вы не любите копировать/вставлять приведенные выше фрагменты кода, вы можете просто установить эту библиотеку: https://github.com/gnugat/nomo-spaco. Если вы используете PHP> = 5.5, вы также можете использовать следующую библиотеку: https://github.com/hanneskod/classtools.

Обновление: так как этот ответ стал несколько популярным, я создал упаковочный пакет, чтобы упростить вещи. Он содержит в основном то, что я описал здесь, без необходимости добавлять класс самостоятельно или настраивать $appRoot вручную. Это может в конечном итоге поддерживать больше, чем просто PSR-4.

$ composer require haydenpierce/class-finder 

Смотрите больше информации в файле README.

Я не был доволен ни одним из решений здесь, поэтому я решил построить свой класс, чтобы справиться с этим. Это решение требует, чтобы вы были:

Короче говоря, этот класс пытается выяснить, где классы фактически живут в вашей файловой системе, на основе пространств имен, которые вы определили в composer.json . Например, классы, определенные в пространстве имен Backup\Test находятся в /home/hpierce/BackupApplicationRoot/src/Test . Этому можно доверять, потому что сопоставление структуры каталога с пространством имен требуется PSR-4:

Смежные имена подпространств имен после «префикса пространства имен» соответствуют подкаталогу в «базовом каталоге», в котором разделители пространства имен представляют разделители каталога. Имя подкаталога ДОЛЖНО совпадать с регистром имен под-пространства имен.

Возможно, вам придется настроить appRoot чтобы он указывал на каталог, содержащий composer.json .

, $files); return array_filter($classes, function($possibleClass)< return class_exists($possibleClass); >); > private static function getDefinedNamespaces() < $composerJsonPath = self::appRoot . 'composer.json'; $composerConfig = json_decode(file_get_contents($composerJsonPath)); //Apparently PHP doesn't like hyphens, so we use variable variables instead. $psr4 = "psr-4"; return (array) $composerConfig->autoload->$psr4; > private static function getNamespaceDirectory($namespace) < $composerNamespaces = self::getDefinedNamespaces(); $namespaceFragments = explode('\\', $namespace); $undefinedNamespaceFragments = []; while($namespaceFragments) < $possibleNamespace = implode('\\', $namespaceFragments) . '\\'; if(array_key_exists($possibleNamespace, $composerNamespaces))< return realpath(self::appRoot . $composerNamespaces[$possibleNamespace] . implode('/', $undefinedNamespaceFragments)); >array_unshift($undefinedNamespaceFragments, array_pop($namespaceFragments)); > return false; > > 

Источник

Функции для работы с классами и объектами

В PHP предусмотрен широкий набор функций для тестирования классов и объектов. Для чего это нужно? Вы, наверняка, сами написали большинство классов, которые используются в сценарии. На самом деле во время выполнения программы не всегда известно, какие классы используются. Например, вы могли разработать систему для «прозрачной» работы со сложными классами, разработанными сторонними производителями. В подобном случае экземпляр объекта обычно создается только на основании имени класса. В PHP разрешается использовать строки, чтобы ссылаться на классы динамически, как показано ниже:

// Файл Task.php namespace tasks; class Task < function doSpeak() < echo "Привет!"; >> // Файл TaskRunner.php $classname = "Task"; require_once ".php"; $classname = "tasks\\$classname"; $myObj = new $classname(); $myObj->doSpeak();

Строку, которую мы назначили переменной $classname, можно получить из файла конфигурации или путем сравнения данных веб-запроса с содержимым каталога. Затем можно использовать эту строку для загрузки файла класса и создания экземпляра объекта. Обратите внимание на то, что в приведенном выше фрагменте кода я указал перед именем класса пространство имен.

Обычно подобные операции выполняют, когда нужно, чтобы система могла выполнять созданные пользователем подключаемые дополнительные модули (plug-ins). Но прежде чем делать такие рискованные вещи в реальном проекте, вы должны проверить, что указанный класс существует, у него есть нужные вам методы и т.д.

В PHP 5 часть функций для работы с классами была заменена более мощным Reflection API, который мы будем изучать в следующей статье. Однако простота и удобство использования в некоторых случаях делают эти функции более предпочтительными. По этой причине мы сейчас и приступим к их рассмотрению.

Курс PHP для начинающих

Поиск классов

Функции class_exists() передается строка, содержащая имя класса. Она возвращает значение true, если класс существует, и false — в противном случае. С помощью этой функции можно сделать предыдущий фрагмент кода более безопасным:

// Файл TaskRunner.php $classname = "Task"; $path = ".php"; if ( !file_exists( $path )) < throw new Exception( "Файл не найден" ); > require_once( $path ); $qclassname = "tasks\\$classname"; if ( !class_exists( $qclassname ) ) < throw new Exception( "Класс $qclassname не найден" ); >$myObj = new $qclassname(); $myObj->doSpeak();

Конечно, мы не можем быть уверенными, что для конструктора рассматриваемого класса не потребуются аргументы. Для достижения такого уровня безопасности программирования необходимо обратиться к Reflection API, который мы будем изучать в следующей статье. Тем не менее перед его использованием с помощью функции class_exists() мы должны убедиться в том, что нужные нам классы существуют.

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

Чтобы получить массив всех классов, определенных в сценарии, можно воспользоваться функцией get_declared_classes():

print_r(get_declared_classes());

В результате будет выведен список встроенных и определенных пользователем классов. Помните, что данная функция возвращает только те классы, которые были объявлены к моменту ее вызова.

Курс PHP для начинающих

Получение информации об объекте или классе

Как вы знаете, с помощью уточнений типов классов можно ограничить тип аргументов метода некоторого объекта. Но даже используя эту возможность, не всегда можно быть уверенным в отношении типа объекта. Существует ряд основных средств для проверки типа объекта. Прежде всего, мы можем узнать класс объекта с помощью функции get_class(). В качестве аргумента ей передается объект любого типа, а она возвращает в виде строки его имя класса (для проработки последующих примеров вам понадобится структура класса ShopProduct, которую мы определили к данному моменту и вспомогательные классы — исходный код):

function getProduct() < return new CDProduct('Первый снег', 'Группа', 'Моральный кодекс', 2.99, 55.01); >$product = getProduct(); if (get_class($product) == 'CDProduct') echo '$product - объект класса CDProduct';

Функция getProduct() просто создает экземпляр объекта CDProduct и возвращает его. Мы воспользуемся данной функцией в этом разделе. Функция get_class() выдает очень специфическую информацию. Обычно же нужна более общая информация о принадлежности к семейству классов. Предположим, нам нужно знать, что объект принадлежит семейству ShopProduct, но при этом не имеет значения, к какому классу конкретно: BookProduct или CDProduct. Для этой цели в PHP предусмотрен оператор instanceof.

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

$product = getProduct(); if ($product instanceof ShopProduct) echo '$product - объект класса CDProduct';

Курс PHP для начинающих

Получение информации о методах

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

foreach (get_class_methods('CDProduct') as $key=>$value) < echo "$key => ()
"; >

В этом примере мы передаем имя класса функции get_class_methods() и выводим возвращенный ею массив с помощью цикла foreach. Мы могли бы также передать функции get_class_methods() объект и получили бы такой же результат. Если вы используете не самую старую версию PHP, то в возвращенный список будут включены только имена общедоступных методов.

Курс PHP для начинающих

Получение информации о свойствах

Точно так же, как можно запросить список методов класса, можно запросить и список его полей. Функции get_class_vars() передается имя класса, а она возвращает ассоциативный массив. Имена полей сохраняются в виде ключей этого массива, а значения полей — в виде значений.

Курс PHP для начинающих

Получение информации о наследовании

С помощью функций для работы с классами можно также выявлять отношения наследования. Например, с помощью функции get_parent_class() можно узнать имя родительского класса для указанного класса. Этой функции передается ссылка на объект или имя класса, а она возвращает имя суперкласса, если таковой существует. Если же такого класса нет, т.е. если у проверяемого класса нет родительского класса, то функция вернет значение false. В результате вызова

echo get_parent_class('CDProduct');

мы получим имя родительского класса ShopProduct, как и можно было ожидать.

С помощью функции is_subclass_of() можно также проверить, является ли класс дочерним для другого класса. Этой функции передается ссылка на дочерний объект и имя родительского класса. Функция возвращает значение true, если второй класс является суперклассом первого аргумента:

function getProduct() < return new CDProduct('Первый снег', 'Группа', 'Моральный кодекс', 2.99, 55.01); >$product = getProduct(); // Получим объект if (is_subclass_of($product, 'ShopProduct')) echo 'CDProduct является подклассом класса ShopProduct';

Функция is_subclass_of() сообщит информацию только об отношениях наследования в классе. Но она не поможет вам узнать, реализует ли класс интерфейс. Для этой цели следует использовать оператор instanceof. Кроме того, можно воспользоваться функцией class_implements(), которая является частью SPL (Standard PHP Library — стандартная библиотека PHP). Этой функции передается имя класса или ссылка на объект, а она возвращает массив имен интерфейсов:

$product = getProduct(); if (in_array('IChargeable', class_implements($product))) echo 'CDProduct реализует интерфейс IChargeable';

Прежде чем отобразить результат, в этом коде мы проверяем, есть ли имя интерфейса в массиве, возвращенном функцией class_implements().

Источник

Оцените статью