是否可以使用静态类将静态方法链接在一起?说我想做这样的事情:
$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;
}
}
在完成这项工作之后,我认为简单地使用类实例而不是尝试链接静态函数调用(这看起来不可能,除非以上示例可以某种方式进行调整)更有意义。 / p>
答案 0 :(得分:46)
我喜欢Camilo上面提供的解决方案,主要是因为您所做的只是改变静态成员的值,并且因为您确实需要链接(即使它只是合成糖),那么实例化TestClass可能是最好的要走的路。
如果你想限制类的实例化,我建议使用Singleton模式:
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();
答案 1 :(得分:40)
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();
答案 2 :(得分:31)
关于php5.3的小疯狂代码......只是为了好玩。
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();
答案 3 :(得分:10)
使用php7,您可以使用所需的语法,因为新的Uniform Variable Syntax
<?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;
答案 4 :(得分:9)
如果toValue(x)返回一个对象,你可以这样做:
$value = TestClass::toValue(5)->add(3)->substract(2)->add(8);
假设toValue返回一个对象的新实例,并且每个next方法都会改变它,返回$ this的实例。
答案 5 :(得分:3)
您始终可以将First方法用作静态方法,将剩余的方法用作实例方法:
$value = Math::toValue(5)->add(3)->subtract(2)->add(8)->result();
或者更好:
$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);
}
}
只是一个FYI ..我把它写在了我的头顶(就在网站上)。所以,它可能无法运行,但这就是主意。我本可以对eval做一个递归方法调用,但我认为这可能更简单。如果您希望我详细说明或提供任何其他帮助,请与我们联系。
答案 6 :(得分:2)
从技术上讲,您可以在PHP 7+中的类似$object::method()
的实例上调用静态方法,因此返回一个新实例可以代替return self
。 And indeed it works.
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);
输出int(14)
。
这与返回in other answer的__CLASS__
相同。我希望没有人决定使用这些形式的API,但是您要求这样做。
答案 7 :(得分:1)
简而言之......不。 :)解析运算符(::)适用于TetsClass :: toValue(5)部分,但之后的所有内容都只会产生语法错误。
一旦命名空间在5.3中实现,你可以拥有“链式”::运算符,但所有这些都是向下钻取命名空间树;在这样的事情中,不可能有方法。
答案 8 :(得分:1)
可以做的最好的事情
class S
{
public static function __callStatic($name,$args)
{
echo 'called S::'.$name . '( )<p>';
return '_t';
}
}
$_t='S';
${${S::X()}::F()}::C();
答案 9 :(得分:1)
这更准确,更容易,并且对读取更友好(允许代码完成)
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;
}
}
示例:强>
echo Calculator::add(5)
->subtract(2)
->multiple(2.1)
->devide(10)
->result();
结果:0.63
答案 10 :(得分:0)
不,这不起作用。 ::
运算符需要回溯到一个类,因此在TestClass::toValue(5)
求值之后,::add(3)
方法只能评估最后一个的答案。
因此,如果toValue(5)
返回整数5,您基本上会调用int(5)::add(3)
,这显然是一个错误。
答案 11 :(得分:0)
我从类新的Instance或Static方法找到方法链的最简单方法如下所示。我在这里使用了Late Static Binding,我非常喜欢这个解决方案。
我创建了一个实用程序,可以在Laravel中使用tostr在下一页上发送多个用户通知。
<?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");
答案 12 :(得分:0)
具有静态属性的方法链接的完整功能示例:
Order Attribute
使用示例:
<?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);
}
}
答案 13 :(得分:0)
人们像疯了似的把事情复杂化了。
检查一下:
class OopClass
{
public $first;
public $second;
public $third;
public static function make($first)
{
return new OopClass($first);
}
public function __construct($first)
{
$this->first = $first;
}
public function second($second)
{
$this->second = $second;
return $this;
}
public function third($third)
{
$this->third = $third;
return $this;
}
}
用法:
OopClass::make('Hello')->second('To')->third('World');
答案 14 :(得分:0)
这是无需通过getInstance
方法(已在PHP 7.x上测试)的另一种方法:
class TestClass
{
private $result = 0;
public function __call($method, $args)
{
return $this->call($method, $args);
}
public static function __callStatic($method, $args)
{
return (new static())->call($method, $args);
}
private function call($method, $args)
{
if (! method_exists($this , '_' . $method)) {
throw new Exception('Call undefined method ' . $method);
}
return $this->{'_' . $method}(...$args);
}
private function _add($num)
{
$this->result += $num;
return $this;
}
private function _subtract($num)
{
$this->result -= $num;
return $this;
}
public function result()
{
return $this->result;
}
}
该类可以如下使用:
$res1 = TestClass::add(5)
->add(3)
->subtract(2)
->add(8)
->result();
echo $res1 . PHP_EOL; // 14
$res2 = TestClass::subtract(1)->add(10)->result();
echo $res2 . PHP_EOL; // 9
答案 15 :(得分:-1)
使用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)
已完成合同。
规则一:最进化和可维护的总是更好。