【问题标题】:Best DRY Method for PHP methods 2 levels deep in a Class?PHP 方法的最佳 DRY 方法 2 级深度一个类?
【发布时间】:2012-10-15 16:53:48
【问题描述】:

我在一个大型类中工作,该类是应用程序的骨干之一,我们称之为myClass。我需要为这个类创建一个新的公共方法,并让它接受一个变量数组,该数组调用我正在编写的函数的各个方法:my_new_iterative_function()... 从某种意义上说,我需要一个“类在一个类中”(javascript 很适合这个;)......我怎样才能实现以下目标,我迭代 $fallback_order 参数数组以更改调用这些方法的顺序,然后有一个默认顺序,执行如果$fallback_order 是默认参数中定义的假?

class myClass {
    public function existing_app_method_1() {
        // other code
    }
    public function existing_app_method_2() {
        // other code
    }
    // large app-centric class with many more methods

    public function my_new_iterative_function( array $fallback_order = false ) {
        method_foo() {
            // do stuff
        }
        method_bar() {
            // do stuff
        }
        method_more_methods() {
            // there are at least 5 of them in total
        }

        if ( $fallbackorder == false ):
            method_foo();
            method_bar();
        else:
            foreach ( $fallback_order as $index => $this_fallback ) {
                $name = $this_fallback;
                if ( $this_fallback == $name ):
                    $this->$name();
                endif;
            }
        endif;
    }
}

视图模板中的目标如下:

<div><?php $myClass->my_new_iterative_function( array( 'method_more_methods', 'method_bar', 'method_foo', ) ); ?></div>

编辑:修正了一些明显错误的逻辑

【问题讨论】:

  • 它必须在哪个版本的 php 上工作?从 5.3 开始,您可以拥有 anonymous functions 和闭包。
  • 我们假设 PHP 是最新版本

标签: php class methods syntax


【解决方案1】:

您可以将方法作为匿名函数放在方法内的数组中,并使用输入索引这些数组,如下所示:

class Foo {
    private $stuff = 'tickle me elmo';        

    public function my_new_iterative_function(array $fallback_order = array('method_foo', 'method_bar')) {

        $self = $this; // this acts as a keyword, you can't use in the `use ()` part

        $order_functions = array(
            'method_foo' => function() use ($self) {
                print "im in foo: {$self->stuff}<br>";
            },
            'method_bar' => function(){
                print "im in bar<br>";
            },
        );

        foreach ( $fallback_order as $index => $this_fallback ) {
            $order_functions[$this_fallback]();
        }
    }
}
(new Foo)->my_new_iterative_function(); // look, one-line `new` and method call, since php 5.4
(new Foo)->my_new_iterative_function([ 'method_bar', 'method_foo', ]); // and even [] for array literals too!

我还在默认参数中嵌入了默认顺序。 (当您将其作为数组输入时将其设置为 false 是一个致命错误)

【讨论】:

  • 小问题 - 我需要使用$this,这里的代码为using $this when not in object context 抛出错误。 :/ ...是否有解决方法,以便仍然可以使用此代码?我在呼唤其他方法,真正的代码是非常复杂的。
  • 您可以使用范围语法将 $this 推入,更新示例。
【解决方案2】:

我意识到你已经接受了一个很好的答案,我应该警告这一点,说我真的不太了解 PHP,但我想我可能会插话,因为我已经给出了一点有点想法。

我想知道将您迭代的方法中的逻辑抽象到单独的 commands 中是否会更整洁(具有明显的优势,您可以在不触及迭代代码的情况下添加更多方法,并且您可以最大限度地减少额外的添加到大类的代码)。然后,您可以将默认订单数组设置为myClass 的属性,但如果需要,在my_new_iterative_function 方法的参数中覆盖它(或者,可能更好,通过myClass 上的设置器)。

对不起,代码是这样的:

class myClass 
{

    // override default order via class setter if required
    protected $fallback_order = array(new FooCommand(), new BarCommand(), new ANOtherCommand());

    public function my_new_iterative_function(  ) {

            foreach ( $this -> fallback_order as $value ) {
                $value -> execute();
            }
    }
}

或者可能是这样的:

class MyClass 
{

    // override default order in method invokation if required
    protected $default_fallback_order = array(new FooCommand(), new BarCommand(), new ANOtherCommand());

    public function my_new_iterative_function( $fallback_order = null ) {

            // Use default fallback order if an override has not been 
            // specified in method parameter
            if (is_null($fallback_order))
                $fallback_order = $this -> default_fallback_order;

            foreach ( $fallback_order as $value ) {
                $value -> execute();
            }
    }
}

$myClass = new MyClass();
$myClass -> my_new_iterative_function(); // use default fallback order
$myClass -> my_new_iterative_function(array(new ANOtherCommand(), new BarCommand(), new FooCommand()));

【讨论】:

  • 这很好——因为上面的答案(你可能已经猜到了)现在让我有些头疼。如果在my_new_iterative_function() 中声明了$fallback_order,这仍然有效吗?因为出于业务逻辑的原因,my_new_iterative_function() 需要成为接收有序函数数组的点。 myClass 包含大量公共和私有方法。它是一个大型控制器。
  • 我敢肯定,我只是不是 100% 了解语法,当然也不是您的业务需求。您能否对函数中接收的参数值设置一个条件,以决定是使用该参数值还是使用类属性中的默认值?
猜你喜欢
  • 2014-09-16
  • 1970-01-01
  • 2023-04-02
  • 1970-01-01
  • 2012-07-22
  • 1970-01-01
  • 2017-11-22
  • 2011-06-16
  • 1970-01-01
相关资源
最近更新 更多