Frage

Ist es möglich, Ketten statischer Methoden zusammen, um eine statische Klasse mit? Sagen, dass ich so etwas wie dies tun wollte:

$value = TestClass::toValue(5)::add(3)::subtract(2)::add(8)::result();

. . . und natürlich würde ich $ value will zugewiesen wird die Zahl 14. Ist das möglich?

Aktualisieren : Es funktioniert nicht (Sie nicht „selbst“ zurückkehren können - es ist nicht eine Instanz!), Aber das ist, wo meine Gedanken mich genommen haben:

class TestClass {
    public static $currentValue;

    public static function toValue($value) {
        self::$currentValue = $value;
    }

    public static function add($value) {
        self::$currentValue = self::$currentValue + $value;
        return self;
    }

    public static function subtract($value) {
        self::$currentValue = self::$currentValue - $value;
        return self;
    }

    public static function result() {
        return self::$value;
    }
}

Danach ausarbeitet, ich glaube, es wäre einfach mehr Sinn machen, einfach mit einer Klasseninstanz zu arbeiten anstatt zu versuchen, Kette statischer Funktion Anrufen (was nicht möglich sieht, es sei denn, das obige Beispiel irgendwie wird gezwickt könnte).

War es hilfreich?

Lösung

Ich mag die von Camilo bereitgestellte Lösung oben, im Wesentlichen da alles, was Sie tun, um den Wert eines statischen Elements zu verändern, und da Sie verketten wollen (auch wenn es nur syntaktischer Zucker), dann Instanziieren Testclass ist wahrscheinlich die beste Weg zu gehen.

Ich hätte gerne ein Singleton Muster vorschlagen, wenn Sie die Klasse instantiieren einschränken möchten:

class TestClass
{   
    public static $currentValue;

    private static $_instance = null;

    private function __construct () { }

    public static function getInstance ()
    {
        if (self::$_instance === null) {
            self::$_instance = new self;
        }

        return self::$_instance;
    }

    public function toValue($value) {
        self::$currentValue = $value;
        return $this;
    }

    public function add($value) {
        self::$currentValue = self::$currentValue + $value;
        return $this;
    }

    public function subtract($value) {
        self::$currentValue = self::$currentValue - $value;
        return $this;
    }

    public function result() {
        return self::$currentValue;
    }
}

// Example Usage:
$result = TestClass::getInstance ()
    ->toValue(5)
    ->add(3)
    ->subtract(2)
    ->add(8)
    ->result();

Andere Tipps

class oop{
    public static $val;

    public static function add($var){
        static::$val+=$var;
        return new static;
    }

    public static function sub($var){
        static::$val-=$var;
        return new static;
    }

    public static function out(){
        return static::$val;
    }

    public static function init($var){
        static::$val=$var;
        return new static;      
    }
}

echo oop::init(5)->add(2)->out();

Little verrückt Code auf PHP5.3 ... nur so zum Spaß.

namespace chaining;
class chain
    {
    static public function one()
        {return get_called_class();}

    static public function two()
        {return get_called_class();}
    }

${${${${chain::one()} = chain::two()}::one()}::two()}::one();

Mit php7 können Sie gewünschte Syntax verwenden, da der neuen

<?php

abstract class TestClass {

    public static $currentValue;

    public static function toValue($value) {
        self::$currentValue = $value;
        return __CLASS__;
    }

    public static function add($value) {
        self::$currentValue = self::$currentValue + $value;
        return __CLASS__;
    }

    public static function subtract($value) {
        self::$currentValue = self::$currentValue - $value;
        return __CLASS__;
    }

    public static function result() {
        return self::$currentValue;
    }

}

$value = TestClass::toValue(5)::add(3)::subtract(2)::add(8)::result();
echo $value;

Demo

Wenn toValue (x) ein Objekt zurückgibt, können Sie wie folgt tun:

$value = TestClass::toValue(5)->add(3)->substract(2)->add(8);

Vorausgesetzt, dass toValue eine neue Instanz des Objekts zurückgibt, und jede nächste Methode mutiert es, eine Instanz von $ Rückkehr diesen.

Sie können immer die erste Methode als statische verwenden und die restlichen als Instanzmethoden:

$value = Math::toValue(5)->add(3)->subtract(2)->add(8)->result();

Oder noch besser:

 $value = Math::eval(Math::value(5)->add(3)->subtract(2)->add(8));

class Math {
     public $operation;
     public $operationValue;
     public $args;
     public $allOperations = array();

     public function __construct($aOperation, $aValue, $theArgs)
     {
       $this->operation = $aOperation;
       $this->operationValue = $aValue;
       $this->args = $theArgs;
     }

     public static function eval($math) {
       if(strcasecmp(get_class($math), "Math") == 0){
            $newValue = $math->operationValue;
            foreach ($math->allOperations as $operationKey=>$currentOperation) {
                switch($currentOperation->operation){
                    case "add":
                         $newvalue = $currentOperation->operationValue + $currentOperation->args;
                         break;
                    case "subtract":
                         $newvalue = $currentOperation->operationValue - $currentOperation->args;
                         break;
                }
            }
            return $newValue;
       }
       return null;
     }

     public function add($number){
         $math = new Math("add", null, $number);
         $this->allOperations[count($this->allOperations)] &= $math;
         return $this;
     }

     public function subtract($number){
         $math = new Math("subtract", null, $number);
         $this->allOperations[count($this->allOperations)] &= $math;
         return $this;
     }

     public static function value($number){
         return new Math("value", $number, null);
     }
 }

Nur ein FYI .. Ich schrieb dies die Oberseite meines Kopfes (direkt hier auf der Website) ab. So kann es nicht laufen, aber das ist die Idee. Ich könnte auch ein rekursive Methodenaufruf hat eval, aber ich dachte, dies einfacher sein kann. Bitte lassen Sie mich wissen, wenn Sie mich möchte andere Hilfe erarbeiten oder zu liefern.

Technisch können Sie eine statische Methode auf einer Instanz wie $object::method() in PHP 7+ nennen, so eine neue Instanz der Rückkehr sollte return self als Ersatz arbeiten. Und in der Tat funktioniert es.

final class TestClass {
    public static $currentValue;

    public static function toValue($value) {
        self::$currentValue = $value;
        return new static();
    }

    public static function add($value) {
        self::$currentValue = self::$currentValue + $value;
        return new static();
    }

    public static function subtract($value) {
        self::$currentValue = self::$currentValue - $value;
        return new static();
    }

    public static function result() {
        return self::$currentValue;
    }
}

$value = TestClass::toValue(5)::add(3)::subtract(2)::add(8)::result();

var_dump($value);

Ausgänge int(14).

Hier geht es um gleiche wie __CLASS__ wie verwendet in anderer Antwort zurück. Ich hoffe vielmehr immer niemand diese Formen der API, um tatsächlich zu nutzen entscheidet, aber Sie haben es so gewollt.

Auf den Punkt gebracht ... nein. :) Der Auflösungsoperator (:. :) funktionieren würde für die TetsClass :: toValue (5) Teil, aber alles danach wird nur einen Syntaxfehler geben

Sobald Namespaces in 5.3 implementiert sind, können Sie haben „angekettet“ :: Betreiber, aber alles, was werde tun, ist der Namespace-Baum Drilldown durch; es wird nicht möglich sein, Methoden der Dinge in der Mitte wie diese zu haben.

Das Beste, was getan werden kann,

class S
{
    public static function  __callStatic($name,$args)
    {
        echo 'called S::'.$name . '( )<p>';
        return '_t';
    }
}

$_t='S';
${${S::X()}::F()}::C();

Dies ist genauer, einfacher und schreibfreundlich (erlaubt Code-Completion)

class Calculator
{   
    public static $value = 0;

    protected static $onlyInstance;

    protected function __construct () 
    {
        // disable creation of public instances 
    }

    protected static function getself()
    {
        if (static::$onlyInstance === null) 
        {
            static::$onlyInstance = new Calculator;
        }

        return static::$onlyInstance;
    }

    /**
     * add to value
     * @param numeric $num 
     * @return \Calculator
     */
    public static function add($num) 
    {
        static::$value += $num;
        return static::getself();
    }

    /**
     * substruct
     * @param string $num
     * @return \Calculator
     */
    public static function subtract($num) 
    {
        static::$value -= $num;
        return static::getself();
    }

    /**
     * multiple by
     * @param string $num
     * @return \Calculator
     */
    public static function multiple($num) 
    {
        static::$value *= $num;
        return static::getself();
    }

    /**
     * devide by
     * @param string $num
     * @return \Calculator
     */
    public static function devide($num) 
    {
        static::$value /= $num;
        return static::getself();
    }

    public static function result()
    {
        return static::$value;
    }
}

Beispiel:

echo Calculator::add(5)
        ->subtract(2)
        ->multiple(2.1)
        ->devide(10)
    ->result();

Ergebnis: 0,63

Nein, das wird nicht funktionieren. Der :: Betreiber muss eine Klasse bewerten zurück, so dass nach der TestClass::toValue(5) auswertet, würde die ::add(3) Methode nur in der Lage sein, sich auf die Antwort des letzten zu bewerten.

Also, wenn toValue(5) die ganze Zahl 5 zurückgegeben, würden Sie im Grunde int(5)::add(3) anrufen, die offensichtlich ein Fehler ist.

Die einfachste Methode, die ich je für die Methode Verkettung von neuer Instanz oder statische Methode der Klasse gefunden habe, ist als unten. Ich habe Späte statische Bindung hier verwendet, und ich liebte wirklich diese Lösung.

Ich habe ein Dienstprogramm erstellt mehrere Benutzerbenachrichtigung auf der nächsten Seite mit tostr in Laravel.

senden
<?php

namespace App\Utils;

use Session;

use Illuminate\Support\HtmlString;

class Toaster
{
    private static $options = [

        "closeButton" => false,

        "debug" => false,

        "newestOnTop" => false,

        "progressBar" => false,

        "positionClass" => "toast-top-right",

        "preventDuplicates" => false,

        "onclick" => null,

        "showDuration" => "3000",

        "hideDuration" => "1000",

        "timeOut" => "5000",

        "extendedTimeOut" => "1000",

        "showEasing" => "swing",

        "hideEasing" => "linear",

        "showMethod" => "fadeIn",

        "hideMethod" => "fadeOut"
    ];

    private static $toastType = "success";

    private static $instance;

    private static $title;

    private static $message;

    private static $toastTypes = ["success", "info", "warning", "error"];

    public function __construct($options = [])
    {
        self::$options = array_merge(self::$options, $options);
    }

    public static function setOptions(array $options = [])
    {
        self::$options = array_merge(self::$options, $options);

        return self::getInstance();
    }

    public static function setOption($option, $value)
    {
        self::$options[$option] = $value;

        return self::getInstance();
    }

    private static function getInstance()
    {
        if(empty(self::$instance) || self::$instance === null)
        {
            self::setInstance();
        }

        return self::$instance;
    }

    private static function setInstance()
    {
        self::$instance = new static();
    }

    public static function __callStatic($method, $args)
    {
        if(in_array($method, self::$toastTypes))
        {
            self::$toastType = $method;

            return self::getInstance()->initToast($method, $args);
        }

        throw new \Exception("Ohh my god. That toast doesn't exists.");
    }

    public function __call($method, $args)
    {
        return self::__callStatic($method, $args);
    }

    private function initToast($method, $params=[])
    {
        if(count($params)==2)
        {
            self::$title = $params[0];

            self::$message = $params[1];
        }
        elseif(count($params)==1)
        {
            self::$title = ucfirst($method);

            self::$message = $params[0];
        }

        $toasters = [];

        if(Session::has('toasters'))
        {
            $toasters = Session::get('toasters');
        }

        $toast = [

            "options" => self::$options,

            "type" => self::$toastType,

            "title" => self::$title,

            "message" => self::$message
        ];

        $toasters[] = $toast;

        Session::forget('toasters');

        Session::put('toasters', $toasters);

        return $this;
    }

    public static function renderToasters()
    {
        $toasters = Session::get('toasters');

        $string = '';

        if(!empty($toasters))
        {
            $string .= '<script type="application/javascript">';

            $string .= "$(function() {\n";

            foreach ($toasters as $toast)
            {
                $string .= "\n toastr.options = " . json_encode($toast['options'], JSON_PRETTY_PRINT) . ";";

                $string .= "\n toastr['{$toast['type']}']('{$toast['message']}', '{$toast['title']}');";
            }

            $string .= "\n});";

            $string .= '</script>';
        }

        Session::forget('toasters');

        return new HtmlString($string);
    }
}

Dies wird, wie unten arbeiten.

Toaster::success("Success Message", "Success Title")

    ->setOption('showDuration', 5000)

    ->warning("Warning Message", "Warning Title")

    ->error("Error Message");

Voll funktionsfähiges Beispiel für Verfahren Chaining mit statischen Eigenschaften:

<?php


class Response
{
    static protected $headers = [];
    static protected $http_code = 200;
    static protected $http_code_msg = '';
    static protected $instance = NULL;


    protected function __construct() { }

    static function getInstance(){
        if(static::$instance == NULL){
            static::$instance = new static();
        }
        return static::$instance;
    }

    public function addHeaders(array $headers)
    {
        static::$headers = $headers;
        return static::getInstance();
    }

    public function addHeader(string $header)
    {
        static::$headers[] = $header;
        return static::getInstance();
    }

    public function code(int $http_code, string $msg = NULL)
    {
        static::$http_code_msg = $msg;
        static::$http_code = $http_code;
        return static::getInstance();
    }

    public function send($data, int $http_code = NULL){
        $http_code = $http_code != NULL ? $http_code : static::$http_code;

        if ($http_code != NULL)
            header(trim("HTTP/1.0 ".$http_code.' '.static::$http_code_msg));

        if (is_array($data) || is_object($data))
            $data = json_encode($data);

        echo $data; 
        exit();     
    }

    function sendError(string $msg_error, int $http_code = null){
        $this->send(['error' => $msg_error], $http_code);
    }
}

Anwendungsbeispiel:

Response::getInstance()->code(400)->sendError("Lacks id in request");

Verwenden Sie PHP 7! Wenn Ihr Web-Anbieter kann nicht -> Änderung Anbieter! Sperren Sie nicht in Vergangenheit an.

final class TestClass {
    public static $currentValue;

    public static function toValue($value) {
        self::$currentValue = $value;
        return __CLASS__;
    }

    public static function add($value) {
        self::$currentValue = self::$currentValue + $value;
        return __CLASS__;
    }

    public static function subtract($value) {
        self::$currentValue = self::$currentValue - $value;
        return __CLASS__;
    }

    public static function result() {
        return self::$currentValue;
    }
}

Und sehr einfache Bedienung:

$value = TestClass::toValue(5)::add(3)::subtract(2)::add(8)::result();

var_dump($value);

Return (oder werfen Fehler):

int(14)

abgeschlossen Vertrag.

Regel: am weitesten entwickelte und wartbar ist immer besser.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top