Php and calling method

Php and calling method

Callbacks can be denoted by the callable type declaration.

Some functions like call_user_func() or usort() accept user-defined callback functions as a parameter. Callback functions can not only be simple functions, but also object methods, including static class methods.

Passing

A PHP function is passed by its name as a string . Any built-in or user-defined function can be used, except language constructs such as: array() , echo , empty() , eval() , exit() , isset() , list() , print or unset() .

A method of an instantiated object is passed as an array containing an object at index 0 and the method name at index 1. Accessing protected and private methods from within a class is allowed.

Static class methods can also be passed without instantiating an object of that class by either, passing the class name instead of an object at index 0, or passing ‘ClassName::methodName’ .

Apart from common user-defined function, anonymous functions and arrow functions can also be passed to a callback parameter.

Note:

As of PHP 8.1.0, anonymous functions can also be created using the first class callable syntax.

Generally, any object implementing __invoke() can also be passed to a callback parameter.

Example #1 Callback function examples

// An example callback function
function my_callback_function () echo ‘hello world!’ ;
>

// An example callback method
class MyClass static function myCallbackMethod () echo ‘Hello World!’ ;
>
>

// Type 1: Simple callback
call_user_func ( ‘my_callback_function’ );

// Type 2: Static class method call
call_user_func (array( ‘MyClass’ , ‘myCallbackMethod’ ));

// Type 3: Object method call
$obj = new MyClass ();
call_user_func (array( $obj , ‘myCallbackMethod’ ));

// Type 4: Static class method call
call_user_func ( ‘MyClass::myCallbackMethod’ );

// Type 5: Relative static class method call
class A public static function who () echo «A\n» ;
>
>

class B extends A public static function who () echo «B\n» ;
>
>

call_user_func (array( ‘B’ , ‘parent::who’ )); // A, deprecated as of PHP 8.2.0

// Type 6: Objects implementing __invoke can be used as callables
class C public function __invoke ( $name ) echo ‘Hello ‘ , $name , «\n» ;
>
>

$c = new C ();
call_user_func ( $c , ‘PHP!’ );
?>

Example #2 Callback example using a Closure

// This is our range of numbers
$numbers = range ( 1 , 5 );

// Use the closure as a callback here to
// double the size of each element in our
// range
$new_numbers = array_map ( $double , $numbers );

print implode ( ‘ ‘ , $new_numbers );
?>

The above example will output:

Note:

Callbacks registered with functions such as call_user_func() and call_user_func_array() will not be called if there is an uncaught exception thrown in a previous callback.

User Contributed Notes 19 notes

You can also use the $this variable to specify a callback:

Читайте также:  Класс без конструктора kotlin

public $property = ‘Hello World!’ ;

public function MyMethod ()
<
call_user_func (array( $this , ‘myCallbackMethod’ ));
>

public function MyCallbackMethod ()
<
echo $this -> property ;
>

Performance note: The callable type hint, like is_callable(), will trigger an autoload of the class if the value looks like a static method callback.

When specifying a call back in array notation (ie. array($this, «myfunc») ) the method can be private if called from inside the class, but if you call it from outside you’ll get a warning:

class mc <
public function go (array $arr ) <
array_walk ( $arr , array( $this , «walkIt» ));
>

private function walkIt ( $val ) <
echo $val . «
» ;
>

public function export () <
return array( $this , ‘walkIt’ );
>
>

$m = new mc ;
$m -> go ( $data ); // valid

array_walk ( $data , $m -> export ()); // will generate warning

?>

Output:
1
2
3
4

Warning: array_walk() expects parameter 2 to be a valid callback, cannot access private method mc::walkIt() in /in/tfh7f on line 22

A note on differences when calling callbacks as «variable functions» without the use of call_user_func() (e.g. » «):

— Using the name of a function as string has worked since at least 4.3.0
— Calling anonymous functions and invokable objects has worked since 5.3.0
— Using the array structure [$object, ‘method’] has worked since 5.4.0

Note, however, that the following are not supported when calling callbacks as variable functions, even though they are supported by call_user_func():

— Calling static class methods via strings such as ‘foo::doStuff’
— Calling parent method using the [$object, ‘parent::method’] array structure

All of these cases are correctly recognized as callbacks by the ‘callable’ type hint, however. Thus, the following code will produce an error «Fatal error: Call to undefined function foo::doStuff() in /tmp/code.php on line 4»:

class foo static function callIt (callable $callback ) $callback ();
>

static function doStuff () echo «Hello World!» ;
>
>

foo :: callIt ( ‘foo::doStuff’ );
?>

The code would work fine, if we replaced the ‘$callback()’ with ‘call_user_func($callback)’ or if we used the array [‘foo’, ‘doStuff’] as the callback instead.

You can use ‘self::methodName’ as a callable, but this is dangerous. Consider this example:

class Foo public static function doAwesomeThings () FunctionCaller :: callIt ( ‘self::someAwesomeMethod’ );
>

public static function someAwesomeMethod () // fantastic code goes here.
>
>

class FunctionCaller public static function callIt (callable $func ) call_user_func ( $func );
>
>

Foo :: doAwesomeThings ();
?>

Читайте также:  Фон для TR

This results in an error:
Warning: class ‘FunctionCaller’ does not have a method ‘someAwesomeMethod’.

For this reason you should always use the full class name:
FunctionCaller :: callIt ( ‘Foo::someAwesomeMethod’ );
?>

I believe this is because there is no way for FunctionCaller to know that the string ‘self’ at one point referred to to `Foo`.

> As of PHP 5.2.3, it is also possible to pass ‘ClassName::methodName’

You can also use ‘self::methodName’. This works in PHP 5.2.12 for me.

I needed a function that would determine the type of callable being passed, and, eventually,
normalized it to some extent. Here’s what I came up with:

/**
* The callable types and normalizations are given in the table below:
*
* Callable | Normalization | Type
* ———————————+———————————+—————
* function (. ) use (. ) <. >| function (. ) use (. ) <. >| ‘closure’
* $object | $object | ‘invocable’
* «function» | «function» | ‘function’
* «class::method» | [«class», «method»] | ‘static’
* [«class», «parent::method»] | [«parent of class», «method»] | ‘static’
* [«class», «self::method»] | [«class», «method»] | ‘static’
* [«class», «method»] | [«class», «method»] | ‘static’
* [$object, «parent::method»] | [$object, «parent::method»] | ‘object’
* [$object, «self::method»] | [$object, «method»] | ‘object’
* [$object, «method»] | [$object, «method»] | ‘object’
* ———————————+———————————+—————
* other callable | idem | ‘unknown’
* ———————————+———————————+—————
* not a callable | null | false
*
* If the «strict» parameter is set to true, additional checks are
* performed, in particular:
* — when a callable string of the form «class::method» or a callable array
* of the form [«class», «method»] is given, the method must be a static one,
* — when a callable array of the form [$object, «method»] is given, the
* method must be a non-static one.
*
*/
function callableType ( $callable , $strict = true , callable& $norm = null ) if (! is_callable ( $callable )) switch ( true ) case is_object ( $callable ):
$norm = $callable ;
return ‘Closure’ === get_class ( $callable ) ? ‘closure’ : ‘invocable’ ;
case is_string ( $callable ):
$m = null ;
if ( preg_match ( ‘~^(?[a-z_][a-z0-9_]*)::(?[a-z_][a-z0-9_]*)$~i’ , $callable , $m )) list( $left , $right ) = [ $m [ ‘class’ ], $m [ ‘method’ ]];
if (! $strict || (new \ ReflectionMethod ( $left , $right ))-> isStatic ()) $norm = [ $left , $right ];
return ‘static’ ;
>
> else $norm = $callable ;
return ‘function’ ;
>
break;
case is_array ( $callable ):
$m = null ;
if ( preg_match ( ‘~^(:?(?self|parent)::)?(?[a-z_][a-z0-9_]*)$~i’ , $callable [ 1 ], $m )) if ( is_string ( $callable [ 0 ])) if ( ‘parent’ === strtolower ( $m [ ‘reference’ ])) list( $left , $right ) = [ get_parent_class ( $callable [ 0 ]), $m [ ‘method’ ]];
> else list( $left , $right ) = [ $callable [ 0 ], $m [ ‘method’ ]];
>
if (! $strict || (new \ ReflectionMethod ( $left , $right ))-> isStatic ()) $norm = [ $left , $right ];
return ‘static’ ;
>
> else if ( ‘self’ === strtolower ( $m [ ‘reference’ ])) list( $left , $right ) = [ $callable [ 0 ], $m [ ‘method’ ]];
> else list( $left , $right ) = $callable ;
>
if (! $strict || !(new \ ReflectionMethod ( $left , $right ))-> isStatic ()) $norm = [ $left , $right ];
return ‘object’ ;
>
>
>
break;
>
$norm = $callable ;
return ‘unknown’ ;
>
$norm = null ;
return false ;
>

Читайте также:  Java declare class in file

?>

Hope someone else finds it useful.

Источник

PHP: Calling another class’ method

I’m still learning OOP so this might not even be possible (although I would be surprised if so), I need some help calling another classes method. For example in ClassA I have this method:

now from ClassB (different file, but in the same directory), I want to call ClassA ‘s getName() , how do I do that? I tried to just do an include() but that does not work. Thanks!

Does class B have any relation to class A (such as hierarchical)? If so, Class B can extend class A and you will have access to class A’s functions. If not, can you describe your two objects a little more (what they represent).

The thing is, Class A is already extending another class (simple_html_dom that I downloaded from the net) so I dont want to (dont even know if I can) extend Class A which is already extending some other class

@evert, I dont have any code. I was hoping someone could give me some code to do what I wrote above as I am stuck.

4 Answers 4

//file1.php name; > > ?> //file2.php function callA() < $classA = new ClassA(); $name = $classA->getName(); echo $name; //Prints John > > $classb = new ClassB(); $classb->callA(); ?> 

Note that you cannot easily unit test your B class now, because you have tightly coupled to A class to it.

right — that include should probably be in a controlling file that calls both A and B instead of B including A. In this example you would always be instantiating A when you load B. But it should be easy for you to separate.

That’s another lesson for the OP to learn another day. all the OP needs now is basics. Thanks for pointing that out anyway

If they are separate classes you can do something like the following:

class A < private $name; public function __construct() < $this->name = 'Some Name'; > public function getName() < return $this->name; > > class B < private $a; public function __construct(A $a) < $this->a = $a; > function getNameOfA() < return $this->a->getName(); > > $a = new A(); $b = new B($a); $b->getNameOfA(); 

What I have done in this example is first create a new instance of the A class. And after that I have created a new instance of the B class to which I pass the instance of A into the constructor. Now B can access all the public members of the A class using $this->a .

Also note that I don’t instantiate the A class inside the B class because that would mean I tighly couple the two classes. This makes it hard to:

Источник

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