php проверка существования функции в классе

Проверка существования метода в PHP

Классы могут содержать динамические методы, наличие которых неочевидно внешнему разработчику. Кроме того, в процессе эксплуатации могут создаваться разнородные массивы объектов, которые могут содержать различные методы. Для подобных ситуаций необходимы инструменты проверки существования метода в классе. В качестве такого инструмента в PHP выступает функция «method_exists()».

Функция в качестве первого параметра принимает имя класса или объект, а в качестве второго имя метода и возвращает «true», если объект или класс имеет данный метод, и «false» в противном случае.

Продемонстрируем работу функции «method_exists()» и создадим класс «myExists», который будет содержать два метода, открытый и закрытый.

В примере при помощи функции «method_exists()» в объекте класса «myExists» проверяется наличие существующих методов «method_public()», «method_private()» и не существующего метода «method_protected()». Результат:

Как видно из результата проверки, функция возвращает «true» для каждого из методов, независимо от его спецификатора доступа, «false» возвращается только в том случае, если объект не обладает ни закрытым, ни открытым методом с таким именем.

В качестве первого аргумента функции «method_exists()» используется объект класса «$_Class_myExists», однако для проверки метода вовсе не обязательно создавать объект, достаточно передать имя класса. Пример:

При работе с функцией «method_exists()» следует учитывать, что она не может определить наличие динамических методов, созданных при помощи специального метода «__call()», «__callStatic()».

Помимо функции «method_exists()» можно воспользоваться альтернативной функцией «is_callable()», которая в отличие от «method_exists()», кроме проверки метода класса позволяет проверить существование функции, не входящей в состав класса.

Работая со сторонним классом, разработчик зачастую не знает досконально всех методов данного класса. Для того чтобы получить их полный список, можно воспользоваться функцией «get_class_methods()». В качестве первого параметра функция принимает имя класса, а возвращает массив его открытых методов. Следует подчеркнуть, что закрытые методы этой функцией не возвращаются. Пример:

Как можно видеть, закрытый метод «method_private()» не включён в результирующий массив. Динамические методы, которые эмулируются при помощи специального метода «__call()», «__callStatic()», также не попадают в список, получаемый при помощи функции «get_class_methods()».

Источник

class_exists

(PHP 4, PHP 5, PHP 7, PHP 8)

class_exists — Проверяет, был ли объявлен класс

Описание

Эта функция проверяет, был ли объявлен указанный класс или нет.

Список параметров

Имя класса. Воспринимается без учёта регистра.

Вызывать ли по умолчанию __autoload.

Возвращаемые значения

Примеры

Пример #1 Пример использования class_exists()

// Проверяем существование класса перед его использованием
if ( class_exists ( ‘MyClass’ )) <
$myclass = new MyClass ();
>

Пример #2 Пример использования c параметром autoload

if ( class_exists ( MyClass ::class)) <
$myclass = new MyClass ();
>

Смотрите также

User Contributed Notes 9 notes

use a\namespaced\classname as coolclass;

class_exists( ‘coolclass’ ) => false

If you recursively load several classes inside an autoload function (or mix manual loading and autoloading), be aware that class_exists() (as well as get_declared_classes()) does not know about classes previously loaded during the *current* autoload invocation.

Apparently, the internal list of declared classes is only updated after the autoload function is completed.

Beware: class_exists is case-INsensitive, as is class instantiation.

(tested with PHP 5.5.10 on Linux)

This can cause some headaches in correlating class names to file names, especially on a case-sensitive file system.

If you are checking if a class exists that is in a specific namespace then you have to pass in the full path to the class:

I’m running PHP 5.3.4 on Windows 7 and had some difficulty autoloading classes using class_exists(). In my case, when I checked for the class and it didn’t exist, class_exists automatically threw a system Exception. I was also throwing my own exception resulting in an uncaught exception.

If you have a directory of classes you want to create. (Modules in my instance). you can do it like that

If spl_autoload_register() had been called, then function will try autoload class if it does not exists.

Источник

method_exists

(PHP 4, PHP 5, PHP 7, PHP 8)

method_exists — Проверяет, существует ли метод в данном классе

Описание

Список параметров

Экземпляр объекта или имя класса

Возвращаемые значения

Примеры

Пример #1 Пример использования method_exists()

Результат выполнения данного примера:

Пример #2 Пример статического использования method_exists()

Результат выполнения данного примера:

Примечания

Вызов этой функции будет использовать все зарегистрированные функции автозагрузки, если класс ещё не известен.

Смотрите также

User Contributed Notes 20 notes

As noted [elsewhere] method_exists() does not care about the existence of __call(), whereas is_callable() does:

Undocumented change since 7.4.0 is released:

class Foo
<
private function privateMethodTest ()
<

class Bar extends Foo
<

var_dump ( method_exists ( Bar ::class, ‘privateMethodTest’ ));
// PHP 7.4: bool(false)
// PHP 7.3: bool(true)

var_dump ( is_callable ( Bar ::class, ‘privateMethodTest’ ));
// PHP 7.3: bool(true)
// PHP 7.4: bool(true)

A couple of the older comments (specifically «jp at function dot fi» and «spam at majiclab dot com») state that is_callable() does not respect a methods visibility when checked outside of that class. ie. That private/protected methods are seen as callable when tested publicly. However, this was a bug (#29210) in early versions of PHP 5 and was fixed (according to the changelog) in PHP 5.0.5 (and/or PHP 5.1.0).

Just to mention it: both method_exists() and is_callable() return true for inherited methods:

class ChildClass extends ParentClass

$p = new ParentClass ();
$c = new ChildClass ();

This function is case-insensitive (as is PHP) and here is the proof:
class A <
public function FUNC () < echo '*****' ; >
>

if you want to check for a method «inside» of a class use:

small example for those who didn’t understood what i mean ( maybe caused by bad english 🙂 ):

?>

the output will be: a::test() exists!

maybe this will help someone

Note that prepending the namespace (if any) is required even if the calling class is in the same namespace:

If you want to check in a class itself if a method is known you may do so with magic variable __CLASS__

private function foo ()<

$test = new A ( ‘foo’ );
//should return true

It wasn’t spelled out but could be inferred: method_exists() also works on interfaces.

a little difference :

to find a method of an object (instance of a class)

Here is a useful function that you can use to check classes methods access e.g whether it is public, private or static or both..

// Example class
class myClass <

public function publ () <

private function priv () <

private static function privstatic () <

public static function publstatic () <

static function mytest () <

As mentioned before, is_callable and method_exists report all methods callable even if they are private/protected and thus actually not callable. So instead of those functions you may use following work-around which reports methods as supposed to.

class Foo1 <
public function bar () <
echo «I’m private Foo1::bar()» ;
>
>

class Foo2 <
private function bar () <
echo «I’m public Foo2::bar()» ;
>
>

$f1 =new Foo1 ;
$f2 =new Foo2 ;

?>

output
Foo1::bar() is callable (correct)
Foo2::bar() is callable (incorrect)
Foo1::bar() is callable (correct)
Foo2::bar() isn’t callable (correct)

Using method_exists inside an object’s __call() method can be very usefull if you want to avoid to get a fatal error because of a limit in function nesting or if you are calling methods that dont exist but need to continue in your application:

call_user_method uses the same mechanism as a normal method call. So you can get the returned values as well in this way.

I was wondering if caching the the methods in an array would have a faster lookup. So I ran a very simple benchmark using xdebug_time_index() with 10000 iterations on each statement.

using PHP 5.3.13 btw

Please note that the test was done on multiple methods, not just one, the code presented above is to show the results, not the actual test code that ran. Also, this was tested just out of curiosity and I didn’t set up a specific environment or used any profiling tools, and it was not meant to be an official benchmark in anyway.

Just a note that the behaviour of this function changed between version 5.0.x and 5.1.x when using static member functions

Im not sure of a workaround for PHP 5.0.x yet.

Источник

function_exists

(PHP 4, PHP 5, PHP 7, PHP 8)

Описание

Список параметров

Имя функции в виде строки.

Возвращаемые значения

Примеры

Пример #1 Пример использования function_exists()

Примечания

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

Смотрите также

User Contributed Notes 23 notes

You can use this function to conditionally define functions, see: http://php.net/manual/en/functions.user-defined.php

For instance WordPress uses it to make functions «pluggable.» If a plugin has already defined a pluggable function, then the WP code knows not to try to redefine it.

But function_exists() will always return true unless you wrap any later function definition in a conditional clause, like if()<. >. This is a subtle matter in PHP parsing. Some examples:

if ( function_exists ( ‘foo’ )) <
print «foo defined\\n» ;
> else <
print «foo not defined\\n» ;
>
function foo () <>

if ( function_exists ( ‘bar’ )) <
print «bar defined\\n» ;
> else <
print «defining bar\\n» ;
function bar () <>
>
print «calling bar\\n» ;
bar (); // ok to call function conditionally defined earlier

print «calling baz\\n» ;
baz (); // ok to call function unconditionally defined later
function baz () <>

qux (); // NOT ok to call function conditionally defined later
if (! function_exists ( ‘qux’ )) <
function qux () <>
>
?>
Prints:
foo defined
defining bar
calling bar
calling baz
PHP Fatal error: Call to undefined function qux()

Any oddities are probably due to the order in which you include/require files.

It should be noted that the function_exists check is not relative to the root namespace. This means that the namespace should be appended to the check:

PHP supports nested function based on certain criteria.

Please look over the code.

function Audio()
<
echo «Plugged Audo 5.1:
«;
function Volume()
<
echo «Volume controls:
«;
function Equalizer()
<
echo «Equalize Bands:
«;
>
>
>
//Call to nested functions
Audio();
Volume();
Equalizer();

if(function_exists(‘Volume’)):
echo «TRUE»;
else:
echo «FALSE»;
endif;

Case 1: //Result :Works Well
———
Audio();
Volume();
Equalizer();

Case 2: //Results Notice Error. Root function Audio must be called first.
———
Volume();

Case 3: //Results Error. Root function Volume must be called.
———
Audio();
Equalizer();

Note :
The nested function should be called based on their order used.
In our example when Audio is not called and instantly when we try to call Volume puts under error.

Even though there is an possibility to use nested functions in PHP. It looks overhead to do so. Better to avoid in logical ground of script.

Tested on PHP 5.5.32

This is not going to go down as you might expect it should (even if you play smart and require/include_once):

if( function_exists ( ‘my_function’ ))
<
throw new Exception ( «‘my_function’ is already defined!» );
>

function my_function ()
<
// Do the work here
>
?>

This, however does work:

Thought this might save someone a few minutes of debugging time.

function_exists will return false for functions disabled with the disable_functions ini directive. However those functions are still declared so trying to define them yourself will fail.

Functions within a function are better off as anonymous returns from create_function(), unless you want to be able to call it elsewhere.

However, I have used this in skinning: I use alert_box() to display certain errors, like a faulty SQL query. This simply calls display_alert(), which is defined in my skin scripts. However, alert_box() is sometimes called before I know which skin to load, so it has its own functionality which it uses if function_exists(‘display_alert’) returns false.

If you use suhosin.executor.func.blacklist instead of disabled_functions in your php.ini, function_exists will return true for a disabled function. I used this to have the same beahviour with suhosin.executor.func.blacklist and disabled_functions:

To prevent direct calls to included files i use the following technique.

In the main file create an empty function with a random name. Like so:

function hjudejdjiwe () < return true ; >
?>

Then check for the existence of this function within your include:

if (! function_exists ( ‘hjudejdjiwe’ )) < die( '!' ); >
?>

Simple but effective.

i was wondering whether is_callable or function exists is faster when checking class methods.

my results when doing each operation 10000 times with a simple test class were the following:

is_callable: 0.28671383857727 seconds
function_exists: 0.14569997787476 seconds

(following tests have proved this to be true).

thus you can see, function_exists is twice as fast as is_callable.

The confusion expressed in some of the submissions here arise because functions declared outside conditional blocks are defined as the code is loaded and are thus callable and exist wherever in the code they are declared, whereas those declared inside a condition block are not defined until that block is executed. Thus:

echo foo();
function foo()

however because those inside a conditional are defined as they are encountered during code execution

yields: Fatal error: Uncaught Error: Call to undefined function foo()

I would like to comment on the following post:

A note of caution: function_exists() appears to be case-insensitive (at least as of PHP 4.3.8). e.g.:

function MyCasedFunction () <
return true ;
>

// Will return true, even though casing is «wrong»
if ( function_exists ( «mYcAsEdFuNcTiOn» ))
echo «I see it!» ;
?>

I believe that function calls itself are case insensitve, so this function is returning a valid truth. PHP doesn’t care about cases.

function B () <
function C () <
function D ()<>
>
>

IsFunctionExist ( ‘A’ );
IsFunctionExist ( ‘B’ );
IsFunctionExist ( ‘C’ );
IsFunctionExist ( ‘D’ );

I, too, was wondering whether is_callable or function exists is faster when checking class methods. So, I setup the following test:

class test
<
function test ()
<
return true ;
>
>

is_callable = TRUE, function_exists = FALSE

Did 10000 is_callables in 0.0640790462494 seconds
Did 10000 function_exists in 0.0304429531097 seconds

So the fact that function_exists is twice as fast is slightly over shadowed by the fact that it doesn’t work on class methods, at least not as far as I can tell.

This can be used to conditionally define a user function. In this sense, it can act as a sort of inline include_once().

For example, suppose you have a function A that calls function B. B is only used inside function A and is never called from anywhere else in the script. It’s logical (and perfectly legal in PHP) to define B inside of A’s definition, like so:

I stumbled over the same problem as «eddiec» (users not able or not willing to use «_once»-suffixes).

A possible alternative explanation for the behavior:

If a file is included, it is possibly parsed every include-time.(?)
While parsing, every function in global scope is tried to register. THIS gets wrong, when multiple times included, and it produces an error.

If functions are defined within block scopes, their registration seems to be delayed until execution of such a block. Thus, not the function «function_exists» functions wrong, but simply the philosophy of the interpreter produces such results.

Thus, the same effect can be achieved by simply putting block braces around the contents of an include_once file:

if (function_exists(‘function_in_question’)) return;
<
function function_in_question(. )
<
.
>
. other stuff
>

. which is equivalent to.

if (!function_exists(‘function_in_question’))
<
function function_in_question(. )
<
.
>
. other stuff
>

// If you want to chack if the function is enabled or disable in php.ini you can use this function:

function_exists returns false on NULL and empty string:

if ( function_exists ( » )) <
echo «empty string function exists\n» ;
>

if ( function_exists ( NULL )) <
echo «NULL function exists\n» ;
>
?>

Neither of the echo statements happen when I run this.

Note that function_exists will return TRUE in the following situation, presumably because the function «testfunc» was defined when the script was PARSED/ITERPRETED, before the function_exists call was made at RUNTIME:

if ( function_exists ( ‘testfunc’ )) return;
function testfunc () < >
?>

So, this construction is not useful for preventing testfunc from being multiply defined if the script is muliply included or required.

However, the following construction DOES work to prevent multiple defines of testfunc:

if (! function_exists ( ‘testfunc’ )) <
function testfunc () < >
>
?>

CONTRAST this with similar uses of defined() which is completely runtime evaluated. These both work:

function_exists() does not cache its query internally.

by executing the following code

There is a 0.16878 seconds improvement, when you use static array to cache methods existence.

to bob at thethirdshift dot net
regarding is_callable vs function_exists.

using your code
is_callable = TRUE, function_exists = FALSE

Did 10000 is_callables in 0.0443360805511 seconds
Did 10000 function_exists in 0.0111110210419 seconds

then we replace
is_callable(array(‘test’,’test’));
with
$callarray = array(‘test’,’test’); // place this outside for-loop
is_callable($callarray);

is_callable = TRUE, function_exists = FALSE

Did 10000 is_callables in 0.0314660072327 seconds
Did 10000 function_exists in 0.0120670795441 seconds

then we replace
is_callable(array(‘test’,’test’));
with
is_callable(‘test’,’test’);

is_callable = TRUE, function_exists = FALSE

Did 10000 is_callables in 0.00991606712341 seconds
Did 10000 function_exists in 0.0113790035248 seconds

I hope you can see that loop-testing functions is not so simple. 🙂

Источник

property_exists

(PHP 5 >= 5.1.0, PHP 7, PHP 8)

property_exists — Проверяет, содержит ли объект или класс указанный атрибут

Описание

Функция проверяет, существует ли атрибут property в указанном классе.

Список параметров

Имя класса или объект класса для проверки

Возвращаемые значения

Примеры

Пример #1 Пример использования property_exists()

Примечания

Вызов этой функции будет использовать все зарегистрированные функции автозагрузки, если класс ещё не известен.

Смотрите также

User Contributed Notes 10 notes

The function behaves differently depending on whether the property has been present in the class declaration, or has been added dynamically, if the variable has been unset()

$testObject = new TestClass ;

If you want to test if declared *public* property was unset, you can use the following code:

As of PHP 5.3.0, calling property_exists from a parent class sees private properties in sub-classes.

declared properties cannot be unset
any set property does exist, even being set to null, regardless how it was set

[before-constructed] dump:
[my_public]: bool(true)
[my_protected]: bool(true)
[my_private]: bool(true)
[my_constructed_int]: bool(false)
[my_constructed_null]: bool(false)
[my_assigned_int]: bool(false)
[my_assigned_null]: bool(false)

[after-constructed] dump:
[my_public]: bool(true)
[my_protected]: bool(true)
[my_private]: bool(true)
[my_constructed_int]: bool(true)
[my_constructed_null]: bool(true)
[my_assigned_int]: bool(false)
[my_assigned_null]: bool(false)

[before-assigned] dump:
[my_public]: bool(true)
[my_protected]: bool(true)
[my_private]: bool(true)
[my_constructed_int]: bool(true)
[my_constructed_null]: bool(true)
[my_assigned_int]: bool(false)
[my_assigned_null]: bool(false)

[after-assigned] dump:
[my_public]: bool(true)
[my_protected]: bool(true)
[my_private]: bool(true)
[my_constructed_int]: bool(true)
[my_constructed_null]: bool(true)
[my_assigned_int]: bool(true)
[my_assigned_null]: bool(true)

[after-unset] dump:
[my_public]: bool(true)
[my_protected]: bool(true)
[my_private]: bool(true)
[my_constructed_int]: bool(false)
[my_constructed_null]: bool(false)
[my_assigned_int]: bool(false)
[my_assigned_null]: bool(false)

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *