【问题标题】:Method chaining in phpphp中的方法链
【发布时间】:2019-12-22 10:10:18
【问题描述】:

我有以下课程

class FormValidator{

    public function __construct() {}

    public function __destruct(){}

    private $value;

    public function Value($value){
        $this->value = trim($value);
        return $this;
    }

    public function Required(){
        if(empty($this->value)){
           return false;
        }
        else{
            return $this;
        }
    }

    public function MinLength($length){
        $len = strlen($this->value);
        if($len < $length){
           return false;
        }
        else{
            return $this;
        }
    }
}

在我的 php 代码中,我正在调用 -

 $validator = new FormValidator();
 $result = $validator->Value("")->Required()->MinLength(5)->SomeOtherMethod();

上面一行给出了错误Call to a member function MinLength() on a non-object ...

更新:如果 Required() 返回 false,我需要停止调用 MinLength()。

我怎样才能使我的陈述发挥作用?

【问题讨论】:

  • Required 返回布尔值或 $this。也许您可以先检查Required 和MinLength if($validator-&gt;Required() &amp;&amp; $validator-&gt;MinLength(5)) { $validator-&gt;Value("")-&gt;SomeOtherMethod(); }
  • 如果您仍在使用 PHP 5,我强烈建议您尽快升级。不再支持此版本。 Let Rasmus Lerdorf explain it to you

标签: php


【解决方案1】:

您应该改用exceptions,它会处理错误,而方法本身将始终返回当前实例。

这就变成了:

<?php
class FormValidationException extends \Exception 
{
}

class FormValidator
{
  private $value;

  public function Value($value): self
  {
    $this->value = trim($value);
    return $this;
  }

  /**
   * @return $this
   * @throws FormValidationException
   */
  public function Required(): self
  {
    if (empty($this->value)) {
      throw new \FormValidationException('Value is required.');
    }
    return $this;
  }

  /**
   * @param int $length
   * @return $this
   * @throws FormValidationException
   */
  public function MinLength(int $length): self
  {
    $len = strlen($this->value);
    if ($len < $length) {
      throw new \FormValidationException("Value should be at least {$length} characters long.");
    }
    return $this;
  }
}

用法:

$validator = new FormValidator();
try {
  $result = $validator->Value("lodddl")->Required()->MinLength(5);
} catch (\FormValidationException $e) {
  echo 'Error: ', $e->getMessage();
}

演示:https://3v4l.org/OFcPV

编辑:由于 OP 使用的是 PHP 5.2(很遗憾),这里有一个版本,在根命名空间之前删除 \s,返回类型声明和参数类型。

PHP 5.2 演示:https://3v4l.org/cagWS

【讨论】:

  • 哦,你快一点。这就是它的完成方式。方法就像一个接口,并且总是返回相同的类型。
  • 看起来不错。 php v5.2 支持这个吗?该参考文献未提及任何版本。
  • @DanielW.with 这个逻辑,从任何方法返回的相同类型都是实例。这意味着您在其他任何事情上都依赖例外。这突出了为什么流畅的界面令人困惑和痛苦。
  • @s.k.paul 这是一个PHP 5.2 compatible version,但只要有机会,你一定要升级。
  • 我的客户坚持使用 v5.2。
【解决方案2】:

除了使用异常(@Jeto 的解决方案),您还可以使用包含所有错误的数组。 此解决方案的一个好处是您将在一次运行中遇到多个错误,而不是在第一个错误时中断。

<?php
class FormValidator
{
  private $value;

  private $_errors = array();

  public function Value($value)
  {
    $this->value = trim($value);
    return $this;
  }

  /**
   * @return $this
   */
  public function Required()
  {
    if (empty($this->value)) {
      $this->_errors[] = 'Value is required';
    }
    return $this;
  }

  /**
   * @param int $length
   * @return $this
   */
  public function MinLength($length)
  {
    $len = strlen($this->value);
    if ($len < $length) {
      $this->_errors[] = "Value should be at least {$length} characters long.";
    }
    return $this;
  }

  public function hasErrors(){
    return (count($this->_errors) > 0);
  }

  public function getErrors(){
      return $this->_errors;
  }
}

$validator = new FormValidator();
$validator->Value("1234")->Required()->MinLength(5);
if($validator->hasErrors()){
    echo implode('<br>',$validator->getErrors());
}

Example here

【讨论】:

  • @Progrock 谢谢,这是写快速回复时复制过去的怪物:)
【解决方案3】:

导致方法Required()返回false而不是Class object

    if(empty($this->value)){
        return false;
    }

您必须将代码更改为。

$result = $validator->Value("");
if($result->Required()){ // if is not false do 
   $result->MinLength(5)->SomeOtherMethod();
}else{
    // do anything if value is empty.
}

【讨论】:

  • 现在方法返回不一致。什么是可链接的,什么不是?类的接口不再明显。
  • @Progrock 当然,我理解我的回答不完整,感谢您的回答:)
【解决方案4】:

在以下方法中,您调用的是布尔值上的方法。

Required();

MinLength();

为了在MinLength方法中解决这个问题:

if($len < $length){

    // As a flag
    $this->failed = true;

    return $this;
}

还有 SomeOtherMethod():

public function SomeOtherMethod() {
    if (! $this->failed) {
        // do something...
    } else {
        // do nothing...
    }
}

Requied() 方法执行相同操作

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多