How to Auto Call Function in PHP for Every Other Function Call

How to auto call function in php for every other function call

Your best bet is the magic method __call, see below for example:

<?php

class test {
function __construct(){}

private function test1(){
echo "In test1", PHP_EOL;
}
private function test2(){
echo "test2", PHP_EOL;
}
protected function test3(){
return "test3" . PHP_EOL;
}
public function __call($method,$arguments) {
if(method_exists($this, $method)) {
$this->test1();
return call_user_func_array(array($this,$method),$arguments);
}
}
}

$a = new test;
$a->test2();
echo $a->test3();
/*
* Output:
* In test1
* test2
* In test1
* test3
*/

Please notice that test2 and test3 are not visible in the context where they are called due to protected and private. If the methods are public the above example will fail.

test1 does not have to be declared private.

ideone.com example can be found here

Updated: Add link to ideone, add example with return value.

Call function before each function

There are different approaches to solve your problem. Some of them are mentioned in the comments already. Let us take the simplest approaches for solving your issue.

The magic method __call()

As lovelace said in the comments, there is already a simple solution for your problem stated in another stack overflow article. It uses PHPs own magic method __call(). Let 's have a look at a simple example.

class Foo
{
protected function before() : void
{
echo "before";
}

public function after() : void
{
echo "after";
}

public function __call($method, $arguments) : void
{
if (method_exists($this, $method)) {
$this->before();
return call_user_func_array(array($this, $method), $arguments);
}
}
}

// Testing
$class = new Foo();
$class->after(); // echoes "before->after"

As you can see the magic method __call provides proper handling for your purpose. First it checks, if the called method exists and after that it executes the before method before the called method is executed. The before method is called automatically, when you call a class method, that exists.

The callback approach

As also mentioned in the comments a callback function could be a possible solution without handling class instances. Let 's have a look at the callback example.

$callback = function()
{
echo "before->";
}

function foo(callable $callback, $bla)
{
$callback();
echo $bla;
}

// example code
foo($callback, 'go and make some coffee');
// output: "before->go and make some coffee"

This approach is even simpler as using the __call method, because you need just a callable function as parameter for your functions. Easy, hm?

The observer pattern

The observer pattern came with the standard php library in php5 and is more complex. I guess way too complex for your use case. To keep it complete, here 's a short example, how the observer pattern could be a usable solution to your issue.

class Group implements SplSubject
{
/**
* persons in this group
* @var \SplObjectStorage
*/
protected $persons;

/**
* observer active in this group
* @var \SplObjectStorage
*/
protected $observers;

/**
* the person, which actually speaks
* @var Person
*/
protected $speaker;

/**
* Initializes our class members and sets an observer for this group
*/
public function __construct()
{
$this->persons = new \SplObjectStorage();
$this->observers = new \SplObjectStorage();

$onSpeakObserver = new OnSpeakObserver($who, $what);
$this->attach($onSpeakObserver);
}

public function add(Person $person) {
$this->persons->attach($person);
}

public function speak(Person $who, $what) {
echo $who . " says: " . $what . "<br>";

$this->speaker = $who;
$this->notify();
}

public function getSpeaker() {
return $this->speaker;
}

public function getGroup() {
return $this->persons;
}

public function attach(\SplObserver $observer) {
$this->observers->attach($observer);
}

public function detach(\SplObserver $observer) {
$this->observers->attach($observer);
}

public function notify() {
foreach ($this->observers as $observer) {
$observer->update($this);
}
}
}

This is our basic class called group, which should be observed. A class, which should be observed, is always called the "subject". A subject takes one ore more observers, which are called by the notify method of the subject. A group consists of several people and a speaker. There is always one speaker and the other persons are listeners, which can react, when the speaker says something. For the reaction of the listeners we need an observer. This observer listens, if the speaker says something. The observer is added directly in the constructor of the group.

This class implements the \SplSubject interface, which brings us the methods attach, detach and notify for handling the observer, we attach to the group. Next we need the classes for a person and the observer itself.

class Person 
{
protected $name = '';

public function __construct(string $name) : void
{
$this->name = $name;
}

public function __toString() : string
{
return $this->name;
}
}

A simple person with a name.

class OnSpeakObserver implements \SplObserver 
{
public function update(\SplSubject $subject)
{
foreach ($subject->getGroup() as $person) {
if ($person !== $subject->getSpeaker()) {
echo $person . " says: me!<br>";
}
}
}
}

This is our observer, which implements the native \SplObserver interface, which forces us to use the update method. This method is called every time, when a person in the group speaks.

With this the classes, we have a simple observer pattern. In this simple example the observer forces a reaction every time a person in a group says something.

// open a group (the subject, which is observed)
$friends = new Group();

// add some persons to our group
$sarah = new Person('Sarah');
$friends->add($sarah);

$nicole = new Person('Nicole');
$friends->add($nicole);

$marcel = new Person('Marcel');
$friends->add($marcel);

$steffen = new Person('Steffen');
$friends->add($steffen);

// Marcel says ...
$friends->speak($marcel, 'Who likes the observer pattern?');

// result:
// Marcel says: Who likes the observer pattern?
// Sarah says: me!
// Nicole says: me!
// Steffen says: me!

You could transfer this little example to solve your problem. An observer could listen on the execution of your functions and every time one of your functions is called, the observer could execute another function before. As shown in this example, the observer does nothing more than executing, after a person in a group has said something. Same goes for your issue. It all depends on when the notify method of the subject is called.

If you have any questions feel free to ask.

Call a function from another function in PHP

If you are using a class, then you can use $this for calling the function:

class Test {

public function say($a) {
return $a ;

}

public function tell() {
$c = "Hello World" ;
$a = $this->say($c) ;
return $a ;
}
}

$b= new Test() ;
echo $b->tell() ;

If you are using a normal function, then use closure:

function tell(){
$a = "Hello" ;
return function($b) use ($a){
return $a." ".$b ;
} ;
}

$s = tell() ;
echo $s("World") ;

Auto call a php function every 10 seconds

You just need to put it in a function and call it again when it's finish.

function ajaxCall() {
$.ajax({
...
}.always(function() {
setTimeout(ajaxCall, 10000); // 10 seconds
});
}

ajaxCall();

EDIT

Updated due to roasted comment.

Is it possible to run a function when another function starts and another function when a function ends?

Measuring execution time is the domain of profilers. In PHP, you could use Xdebug to do so. See Simplest way to profile a PHP script for other suggestions. In any case, a profiler is what you want to use. It's a professional tool for the purpose.

As an alternative, you could invest into an observability tool, like Instana or Tideways. There are others. While observability is somewhat different from profiling, both tools come with code profiling capabilities to complement their observability features. Full disclosure: I work for Instana and am friends with the owner of Tideways.

I am not aware of a good userland no-code approach to adding interceptors to function calls. There are libraries like Componere, runkit or uopz but I don't think you'll get very far with them and you will need to install an extension. If given the choice between installing Xdebug or one of these, I'd go with Xdebug.

A low code approach might be to use attributes as pointed out in the comments to your question. That will still require you to heavily touch up your code because every line of code you want measured needs to have the attribute.

Apart from that, you could hack something together in a namespace:

<?php

namespace My;

foreach (get_defined_functions()['internal'] as $function) {
if ($function === 'assert') continue;
$declaration = sprintf(
'namespace My; function %s() {
$start = \microtime(true);
$retval = \call_user_func_array("%s", \func_get_args());
echo \microtime(true) - $start, PHP_EOL;
return $retval;
}',
$function,
$function,
$function,
$function
);
eval($declaration);
};

echo strtotime('today');

This will output something like

6.9141387939453E-5
1624485600

Demo: https://3v4l.org/r9Rpd

This will create a function for every internal PHP function in the namespace My, wrapping that internal function. You can insert any code you want to run before and after the function in the function declaration.

PHP will first check the current namespace for a defined function before falling back to looking into the global namespace. Thus, when calling strtotime, it will invoke My\strtotime.

There are probably plenty of caveats I didn't think through with this approach. I am not recommending to use that. As I said in the beginning: use a profiler.

Calling function at the beginning of every action

You have two options here.

The first option, override the constructor:

    public function __construct()
{
parent::__construct(); // Call parent constructor
$this->someFunction(); // Call your function
}

Don't forget to call the parent constructor (Constructor of the CController class) and after that, call your action.

The second option you have is to override the 'beforeAction' function

protected function beforeAction($action)
{
return true; // True: the action should be executed, false if not.
}

Hope it helps you :).

Making a method in PHP automatically run some code after being called. Possible?

A far simpler way to do this would to simply have a third method which calls run() and then calls common_code(). Subclasses can then override run() all they want.

abstract class Parent_Class {
public abstract function run();

protected function common_code() {
// Common code here
}

protected function start() {
$this->run();
$this->common_code();
}

}

class Child_Class {
public function run() {
// Code here
}
}


Related Topics



Leave a reply



Submit