【问题标题】:How can I implement Method Chaining in PHP 5.x?如何在 PHP 5.x 中实现方法链?
【发布时间】:2023-03-11 13:55:01
【问题描述】:

我为 PHP 5.4.x 编写了以下类。这应该像我预期的那样工作吗?

class SqlBuilder {
    private $dbTable;
    private $action;
    private $data;
    private $clause;

    public function toString() {
        // $sql = generate sql string
        // [...]
        return $sql;
    }

    [...]

    public function setClause($clause) {
        $this->clause = $clause;
    }

    public function setDbTable($dbTable) {
        $this->dbTable = $dbTable;
    }   

    public function setAction($action) {
        $this->action = $action;
    }
}   
$sql = (new \dbal\SqlBuilder())
            ->setAction($this->action)
            ->setClause($this->clause)
            ->setDbTable($this->dbTable)
            ->toString();

我希望能够访问我所有的 setter 方法。相反,我看到以下错误:

致命错误:在非对象上调用成员函数 toString()

这似乎有效:

$builder= new \dbal\SqlBuilder();
$builder->setAction($this->action)
$builder->setClause($this->clause)
$builder->setDbTable($this->dbTable)
$sql = $builder->toString();

但我知道这也有效:

class Foo
{
    public $a = "I'm a!";
    public $b = "I'm b!";
    public $c;

    public function getB() {
        return $this->b;
    }

    public function setC($c) {
        $this->c = $c;
        return $this;
    }

    public function getC() {
        return $this->c;
    }
}

print (new Foo)
       ->setC($_GET["c"])
       ->getC(); // I'm c!

我以前在 Javascript 中使用过这种语法风格。有没有办法让它在 PHP 中工作?

【问题讨论】:

  • 我不确定我是否理解这个问题。
  • SqlBuilder 类是什么?我不认识。
  • 我真的很失望,因为这不是一个真正的问题而被关闭。是的,提出问题的人很难表达他的问题,但这是一个真实的问题。如果你花时间仔细阅读它,我想你会明白他的要求。
  • 我已经修改了问题以反映我认为 nakwa 的问题。

标签: php method-chaining


【解决方案1】:

您所问的是所谓的方法链。为了让它按照您想要的方式工作,每个方法调用都需要返回对您正在调用的对象的引用。所以,

->setAction($this->action)
// needs to return $this; so that
        ->setClause($this->clause)
// knows what to operate upon and in turn needs to return $this; so that
        ->setDbTable($this->dbTable)
// can do the same

试试:

public function setClause($clause) {
    $this->clause = $clause;
    return $this;
}

public function setDbTable($dbTable) {
    $this->dbTable = $dbTable;
    return $this;
}   

public function setAction($action) {
    $this->action = $action;
    return $this;
}

【讨论】:

  • 只是一个旁注......当你创建一个类的实例时,构造函数返回一个类的实例。当你将它分配给一个变量时,你就会拥有对存储在变量中的类的引用,所以当你在对象中调用某些东西时,你是通过它的引用来这样做的。在一个类中,$this 变量包含相同的引用,因此通过返回 $this,如上例所示,您将返回相同的引用,从而使链接成为可能。
  • 是的。这也使其保持高效。由于您要返回对实例的引用,因此每次调用都不会占用更多内存:)
  • 不确定 - 是不是因为您仍在对象的范围内,所以您不需要退出然后返回调用成员函数?
  • 因为它指向的是同一个内存空间中的对象的实例。这就是参考。
猜你喜欢
  • 2020-07-15
  • 2014-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多