Цепные статические методы в PHP? - PullRequest
48 голосов
/ 24 сентября 2008

Возможно ли связать статические методы вместе, используя статический класс? Скажем, я хотел сделать что-то вроде этого:

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

. , , и, очевидно, я бы хотел, чтобы $ value было присвоено число 14. Возможно ли это?

Обновление : это не работает (вы не можете вернуть «я» - это не экземпляр!), Но это то, куда меня взяли мысли:

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;
    }
}

После этого я думаю, что было бы более разумно просто работать с экземпляром класса, а не пытаться связывать статические вызовы функций (что не представляется возможным, если приведенный выше пример не может быть каким-то образом изменен).

Ответы [ 14 ]

0 голосов
/ 11 января 2019

Полнофункциональный пример объединения методов со статическими атрибутами:

<?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);
    }
}

Пример использования:

Response::getInstance()->code(400)->sendError("Lacks id in request");
0 голосов
/ 05 марта 2018

Используйте PHP 7! Если ваш веб-провайдер не может -> сменить провайдера! Не блокируйся в прошлом.

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;
    }
}

И очень простое использование:

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

var_dump($value);

Возврат (или ошибка выброса):

int(14)

завершен контракт.

Правило первое: наиболее развитое и обслуживаемое всегда лучше.

0 голосов
/ 13 июня 2017

Самый простой способ, который я когда-либо нашел для цепочки методов из нового экземпляра или статического метода класса, как ниже Я использовал Late Static Binding здесь, и мне очень понравилось это решение.

Я создал утилиту для отправки нескольких уведомлений пользователей на следующей странице, используя tostr в Laravel.

<?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);
    }
}

Это будет работать, как показано ниже.

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

    ->setOption('showDuration', 5000)

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

    ->error("Error Message");
0 голосов
/ 24 сентября 2008

Нет, это не сработает. Оператор :: должен выполнить оценку обратно в класс, поэтому после оценки TestClass::toValue(5) метод ::add(3) сможет оценить только ответ последнего.

Так что если бы toValue(5) вернуло целое число 5, вы бы в основном позвонили int(5)::add(3), что, очевидно, является ошибкой.

...