web-dev-qa-db-fra.com

PHP - est-il possible de déclarer une méthode statique et non statique

Puis-je déclarer une méthode dans un objet en tant que méthode statique et non statique avec le même nom que celui qui appelle la méthode statique?

Je veux créer une classe qui a une méthode statique "send" et une méthode non statique qui appelle la fonction statique. Par exemple:

class test {
    private $text;
    public static function instance() {
        return new test();
    }

    public function setText($text) {
        $this->text = $text;
        return $this;
    }

    public function send() {
        self::send($this->text);
    }

    public static function send($text) {
        // send something
    }
}

Je veux pouvoir appeler la fonction sur ces deux était

test::send("Hello World!");

et

test::instance()->setText("Hello World")->send();

c'est possible?

54
alphanyx

Vous pouvez le faire, mais c'est un peu compliqué. Vous devez le faire en surchargeant: les méthodes __call et __callStatic magic.

class test {
    private $text;
    public static function instance() {
        return new test();
    }

    public function setText($text) {
        $this->text = $text;
        return $this;
    }

    public function sendObject() {
        self::send($this->text);
    }

    public static function sendText($text) {
        // send something
    }

    public function __call($name, $arguments) {
        if ($name === 'send') {
            call_user_func(array($this, 'sendObject'));
        }
    }

    public function __callStatic($name, $arguments) {
        if ($name === 'send') {
            call_user_func(array('test', 'sendText'), $arguments[0]);
        }
    }
}

Ce n'est pas une solution idéale, cela rend votre code plus difficile à suivre, mais cela fonctionnera si vous avez PHP> = 5.3.

64
lonesomeday

Il y a un moyen beaucoup plus simple.

class MyClass {

    private $r = "I'm regular!";
    private static $s = "I'm static!";

    public function method() {
        if (isset($this) && $this instanceof self) {
            // Regular call
            echo $this->r;
        } else {
            // Static call
            echo static::$s;
        }
    }

}

Maintenant, vous pouvez facilement faire:

(new MyClass())->method();
// I'm regular!

ou

MyClass::method();
// I'm static!

Vous pouvez utiliser ce cadre pour réaliser tout ce que vous décrivez dans la question.

Note: Seul inconvénient, cela ne fonctionnera qu'avec PHP> = 5.4

7
mae

Non, vous ne pouvez pas avoir deux méthodes avec le même nom. Vous pouvez fondamentalement faire la même chose en renommant l’une des méthodes. Renommer test::send("Hello World!"); en test::sendMessage("Hello World!"); fonctionnerait. Je créerais simplement la méthode d'envoi unique avec un argument texte facultatif qui modifie le fonctionnement de la méthode.

public function send($text = false) {
    if (!$text) {
        $text = $this -> text;
    }

    // Send something
}

Je suis curieux de savoir pourquoi vous avez besoin de la fonction statique.

2
Jordan Shute

Je créerais une classe cachée en tant que constructeur et renverrais cette classe cachée à l'intérieur de la classe parent qui a des méthodes statiques égales à celles de la classe cachée:

// Parent class

class Hook {

    protected static $hooks = [];

    public function __construct() {
        return new __Hook();
    }

    public static function on($event, $fn) {
        self::$hooks[$event][] = $fn;
    }

}


// Hidden class

class __Hook {

    protected $hooks = [];

    public function on($event, $fn) {
        $this->hooks[$event][] = $fn;
    }

}

Pour l'appeler statiquement:

Hook::on("click", function() {});

Pour l'appeler dynamiquement:

$hook = new Hook;
$hook->on("click", function() {});
1
Taufik Nurrohman