0

I want to create a daemon constructor in PHP.

class DAEMON {
    var host;
    var port;
    function __construct($host, $port) {
        $this -> host = $host;
        $this -> port = $port;
    }
    function start() {
        while (true) {
            $this->loop();
        }
    }
    function loop() {

    }
}

In addition to passing the $host and $port parameters like

$server = new DAEMON("127.0.0.1", 9000);
$server -> start();

I want somehow to pass the loop() function as a 3rd parameter, so it overwrites the loop() function or inject code inside it.

I have tried

$server = new DAEMON("127.0.0.1", 9000, function() {
    // function() can't take any parameters
    // I cant use $server variable here
});
$server -> start();

and

$server = new DAEMON("127.0.0.1", 9000);
$server::loop = function() {
    //not working, it's not javascript
};
$server->start();

Neither work. How can I do it? I have struggled many hours trying to find a solution..

3 Answers 3

2

You can just pass a anonymous function to the constructor

http://php.net/manual/en/functions.anonymous.php

<?php

class DAEMON {
    private $host;
    private $port;
    private $callback;

    public function __construct($host, $port, $callback) {
        $this->host = $host;
        $this->port = $port;
        if ( ! is_callable($callback)) {
            throw new InvalidArgumentException('callback needs to be a function');
        }

        $this->callback = $callback;
    }

    public function start() {
        $callback = $this->callback;
        while (true) {
            $callback($this);
        }
    }
}

$server = new DAEMON("127.0.0.1", 9000, function($server) {
    echo "hello_world";
});

$server->start();
Sign up to request clarification or add additional context in comments.

3 Comments

This is essentially what I was writing/testing. One thing I would add though is that you won't be able to access the $host and other private properties on $server inside your callback. You would have to make them public, add a getter method or pass them in as separate arguments.
Nah you could simple pass the host and port simply to the callback function as well if you need to
That was one of the options I suggested, "pass them in as separate arguments".
1

You can call the use language construct to pass arguments to the anonymous functions. In your case, if you wanted to use the $server variable, then you could do ..

$server = new DAEMON("127.0.0.1", 9000, function() use ($server){
    // function() can't take any parameters
    // I cant use $server variable here
});
$server -> start();

... but for this to work, your DAEMON{} class should have a third parameter in the constructor that accepts callable type..

2 Comments

$server = new DEMON("127.0.0.1", 1337, function() use ($server){ echo $server->host; }); throws error
Trying to get property of non-object
0

I am unsure on your actual reasons on allowing a function to run arbitrary code but you can do something really dirty by executing a string as php code .

class DAEMON {
    private $host;
    private $port;
    private $injection;

    public function __construct($host, $port, $injection) {
        $this->host = $host;
        $this->port = $port;
        $this->injection = $injection;
    }
    public function start() {
        while (true) {
            $this->loop();
        }
    }
    private function loop() {
        eval($this->injection);
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.