在 PHP 中链接静态方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/125268/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Chaining Static Methods in PHP?
提问by Wilco
Is it possible to chain static methods together using a static class? Say I wanted to do something like this:
是否可以使用静态类将静态方法链接在一起?说我想做这样的事情:
$value = TestClass::toValue(5)::add(3)::subtract(2)::add(8)::result();
. . . and obviously I would want $value to be assigned the number 14. Is this possible?
. . . 显然我希望 $value 被分配数字 14。这可能吗?
Update: It doesn't work (you can't return "self" - it's not an instance!), but this is where my thoughts have taken me:
更新:它不起作用(你不能返回“自我”——这不是一个实例!),但这就是我的想法:
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;
}
}
After working that out, I think it would just make more sense to simply work with a class instance rather than trying to chain static function calls (which doesn't look possible, unless the above example could be tweaked somehow).
在解决了这个问题之后,我认为简单地使用类实例而不是尝试链接静态函数调用会更有意义(这看起来不可能,除非上面的例子可以以某种方式进行调整)。
采纳答案by Mathew Byrne
I like the solution provided by Camilo above, essentially since all you're doing is altering the value of a static member, and since you do want chaining (even though it's only syntatic sugar), then instantiating TestClass is probably the best way to go.
我喜欢上面 Camilo 提供的解决方案,基本上因为你所做的只是改变静态成员的值,而且你确实想要链接(即使它只是语法糖),那么实例化 TestClass 可能是最好的方法.
I'd suggest a Singleton pattern if you want to restrict instantiation of the class:
如果您想限制类的实例化,我建议使用单例模式:
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();
回答by Ariful Islam
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();
回答by sectus
Little crazy code on php5.3... just for fun.
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();
回答by sectus
With php7 you will be able to use desired syntax because of new Uniform Variable Syntax
使用 php7,您将能够使用所需的语法,因为新的统一变量语法
<?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;
回答by Camilo Díaz Repka
If toValue(x) returns an object, you could do like this:
如果 toValue(x) 返回一个对象,你可以这样做:
$value = TestClass::toValue(5)->add(3)->substract(2)->add(8);
Providing that toValue returns a new instance of the object, and each next method mutates it, returning an instance of $this.
提供 toValue 返回对象的一个新实例,每个 next 方法都会改变它,返回 $this 的一个实例。
回答by Phobis
You could always use the First method as a static and the remaining as instance methods:
您始终可以将 First 方法用作静态方法,将其余方法用作实例方法:
$value = Math::toValue(5)->add(3)->subtract(2)->add(8)->result();
Or better yet:
或者更好:
$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);
}
}
Just an FYI.. I wrote this off the top of my head (right here on the site). So, it may not run, but that is the idea. I could have also did a recursive method call to eval, but I thought this may be simpler. Please let me know if you would like me to elaborate or provide any other help.
仅供参考......我把这个写在我的头上(就在网站上)。因此,它可能无法运行,但这就是想法。我也可以对 eval 进行递归方法调用,但我认为这可能更简单。如果您希望我详细说明或提供任何其他帮助,请告诉我。
回答by George Garchagudashvili
This is more accurate, easier, and read-friendly (allows 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;
}
}
Example:
例子:
echo Calculator::add(5)
->subtract(2)
->multiple(2.1)
->devide(10)
->result();
result: 0.63
结果:0.63
回答by kdion4891
People are overcomplicating this like crazy.
人们疯狂地过度复杂化。
Check this out:
看一下这个:
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;
}
}
Usage:
用法:
OopClass::make('Hello')->second('To')->third('World');
回答by sanmai
Technically you can call a static method on an instance like $object::method()in PHP 7+, so returning a new instance should work as a replacement for return self. And indeed it works.
从技术上讲,您可以像$object::method()在 PHP 7+ 中那样在实例上调用静态方法,因此返回一个新实例应该可以替代return self. 确实有效。
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);
Outputs int(14).
输出int(14)。
This about same as returning __CLASS__as used in other answer. I rather hope no-one ever decides to actually use these forms of API, but you asked for it.
这与其他答案中__CLASS__使用的返回大致相同。我宁愿希望没有人决定实际使用这些形式的 API,但您要求这样做。
回答by dirtside
In a nutshell... no. :) The resolution operator (::) would work for the TetsClass::toValue(5) part, but everything after that will just give a syntax error.
简而言之……不。:) 解析运算符 (::) 将适用于 TetsClass::toValue(5) 部分,但之后的所有内容只会出现语法错误。
Once namespaces are implemented in 5.3, you can have "chained" :: operators, but all that'll do is drill down through the namespace tree; it won't be possible to have methods in the middle of things like this.
一旦命名空间在 5.3 中实现,您就可以“链接” :: 操作符,但所有要做的就是向下钻取命名空间树;在这样的事情中间不可能有方法。

