【问题标题】:A little help understanding object oriented PHP [duplicate]一点帮助理解面向对象的 PHP [重复]
【发布时间】:2012-09-14 11:11:05
【问题描述】:

可能重复:
PHP method chaining?

我对 PHP 和 OOP 比较陌生,我无法理解在我的数据库代码中弹出的重复结构。

我了解如何创建类、实例化它以及访问属性和方法,但$myobject->function() 对我来说已经很复杂了。

这是什么结构?

$myobject->function()->something。我越来越多地反复看到这一点,尤其是当我开始关注 mysql PDO 查询时。例如:

$query->function1($arg)
  ->function2($arg)
  ->function3($arg);

这里发生了什么?它是简单地链接一个类中多个方法的调用,还是function1() 的那些子函数?类定义是什么样的?

【问题讨论】:

  • '方法链' - 这就是它的名称。这为我打开了一个全新的搜索结果世界,谢谢。到目前为止,我正在阅读的其中一个非常有用的是talkphp.com/advanced-php-programming/…。因此,通过返回 '$this' 对象,我可以简单地继续调用 '$this' 对象的方法和属性。感谢大家到目前为止的答案,他们真的很有帮助。 @mehaase 特别感谢您提供的非常丰富的回复。从运营商的角度来看,很有启发性。

标签: php oop


【解决方案1】:

这是一个有趣的简单演示:

<?php

class ChainMe {

    public function hello() {
        echo 'Hello ';

        return $this;
    }

    public function good($is = false) {
        if ($is === true) {
            echo 'beautiful ';
        }

        return $this;
    }

    public function day() {
        echo "world!\n\n";

        return $this;
    }

}

$happy = new ChainMe();
$happy
    ->hello()
    ->good(true)
    ->day();

$meh = new ChainMe();
$meh->hello()->good()->day();

?>

http://codepad.org/zlQEMPqK

如果你对 jQuery 非常熟悉并且曾经见过类似的东西:

jQuery('#my .awesome[selector]')
    .fadeToggle('fast')
    .addClass('rocks')
    .fadeToggle();

然后你就体验到了链接。例如,查看源代码中jQuery 变量的定义:

// Define a local copy of jQuery
jQuery = function( selector, context ) {
    // The jQuery object is actually just the init constructor 'enhanced'
    return new jQuery.fn.init( selector, context, rootjQuery );
},

还有jQuery.extendjQuery.fn/jQuery.fn.init$ and window._$。您会看到它的许多成员方法返回this(或返回另一个方法,该方法又返回this)。反过来有。当 jQuery 首次亮相时,那是许多“Javascript”开发人员第一次看到这种模式。需要一些时间来适应。 :)

在 jQuery 中,在许多情况下,它应该为方法链提供良好的性能提升(例如,在时间很重要的动画队列中)。我不知道PHP中是否是这种情况,但这完全有可能。我更多地使用浏览器而不是服务器,所以我在 PHP 中没有看到那么多。但关键是,这是一个需要掌握的权力概念。

【讨论】:

    【解决方案2】:

    这是一种称为Fluent Interface 的设计模式。它通过一些使用它的著名框架(例如 jQuery)变得流行起来。这是编写紧凑、可读的代码(在某些情况下)的绝妙技巧,但与许多设计模式一样,它并不适合所有情况。

    -&gt; 符号实际上只是一个运算符。类似于+- 可用于对数字进行操作的方式,-&gt; 运算符可以对对象和成员进行操作。 PHP 解释器可以将5 + 4 之类的表达式简化为9,它也可以简化$a-&gt;b 之类的表达式。通过在 $a 内部查找名为 b 的成员来评估表达式 $a-&gt;b

    就像+ 运算符可以在表达式中多次使用一样,例如5 + 2 + 7-&gt; 运算符也可以多次使用。 PHP 解释器与+ 运算符保持关联,这意味着它评估5 + 2 + 7 就好像它写成(5 + 2) + 7,它评估为7 + 7,而后者又评估为14

    -&gt; 运算符也是左关联的。所以像$a-&gt;b-&gt;c 这样的表达式的解释方式与前面的示例类似:首先解释器通过在a 中查找名为b 的成员来评估$a-&gt;b,然后在那!这假设 $a-&gt;b 实际上计算为一个对象;如果没有,那么 PHP 解释器会给你一个错误:“尝试获取非对象的属性”。

    这种范式可以无限扩展:$a-&gt;b-&gt;c-&gt;d-&gt;e-&gt;f-&gt;g-&gt;....

    在 Fluent Interface 设计模式中,这是通过让所有实例方法返回实例来实现的。所以$a-&gt;b() 返回$a。因此,$a-&gt;b()-&gt;c() 与调用$a-&gt;b() 然后调用$a-&gt;c() 完全相同。

    有些人认为前者比后者更具可读性。在某些情况下这是真的,但在其他情况下则不是。像大多数设计模式一样,在决定是否使用此模式时,您需要做出良好的判断。请记住,这种模式只有在纯粹为了副作用而调用实例方法时才有效。除了实例本身之外,您不能从实例方法返回任何其他值,否则您将破坏流畅的接口。

    【讨论】:

      【解决方案3】:

      使用面向对象的编程,对象可以有多个实例。这些实例中的属性可以有不同的值。

      例如。

      class Person {
          public var $name;
          public var $age:
      
          public function simpleGetter() {
             echo "name : ". $this->name;
             echo "age : ". $this->age;
             return $this;
          }
      
          public function addAgeByOne($instance = null) {
              return ++$instance->age;
          }
      }
      
      $student = new Person();
      $student->name = "Student\'s name";
      $student->age = 23;
      
      $teacher = new Person();
      $teacher->name = "Teacher\'s name";
      $teacher->age = 45;
      
      $student->simpleGetter(); // will display the property value from student instance
      $teacher->simpleGetter(); // will display the property value from teacher instance
      
      
      // yes this is chaining, it will first retrieve the results from simpleGetter() and then
      // pass on to addAgeByOne
      $student->simpleGetter()->addAgeByOne();  
      

      【讨论】:

        【解决方案4】:
        $query->function1($arg) ->function2($arg) ->function3($arg);
        

        意思是:

        $some_object1 = $query->function1($arg); 
        $some_object2 = $some_object2->function2($arg); 
        $final_result = $some_object2->function3($arg);
        

        所以你的函数 1 和函数 2 必须返回某个类的对象。

        希望对您有所帮助...

        【讨论】:

          【解决方案5】:

          -> 语法是用于访问类的方法和成员的运算符。当你做这样的事情时:

          $someObject -> function1(arg) -> function2(arg) ...您只是进一步访问返回的对象。

          假设你有一个类 Bike。这辆自行车有一个名为 SpeedUp(arg) 的方法,它以浮点数作为参数。 SpeedUp 方法返回调用该方法的对象($this 指针)。为了稍微改变一下,我们将添加一个 SlowDown(arg) 方法。

          class myBike
          {
              private function SpeedUp($arg)
              {
                  //Do something with $arg, then return "this"...
                  return $this;
              }
          
              private function SlowDown($arg)
              {
                  //Do somethign with $arg, then return "this".
                  return $this;
              }
          }
          
          Bike myBike;
          MyBike -> SpeedUp(50.3) -> SpeedUp(40.3) -> SlowDown(30.4);
          

          那么这里发生了什么?首先,参数的存在是无关紧要的。不管你有没有,你的方法仍然可以返回这个对象。

          您可以使用这么多 -> 运算符,因为这辆自行车会将自己返回给调用者。因此,当您调用 MyBike -> SpeedUp() 时,这将返回 MyBike,因此在第二个 SpeedUp 调用中,它本质上将是 myBike -> SpeedUp(40.3),并且由于再次返回同一辆自行车,您可以将其放慢速度同一行。

          免责声明:这个例子很笼统,但它应该有助于说明问题的答案。

          【讨论】:

            【解决方案6】:

            $myobject-&gt;function() 正在返回一个对象,-&gt;something 将访问该对象上的一个字段。

            基本上,这种编程方法的主要概念是对象包含数据和与包含的数据交互的方法(或“函数”)。这些容器可以方便地传递。 PHP 为您提供了一些速记,因此您不必将所有内容都分配给变量。

            返回对象是一种分层功能的方式,因此具有查询方法的 PDO 对象可能会返回一个行对象。行对象有自己的一组方法(例如,用于获取列值),因此您可以调用这些方法。

            所以:

            $pdo->queryOneRow(...)->getValue(<some column>)
            

            实际上只是以下的简写:

            $result = $pdo->queryOneRow(...);
            $result->getValue(<some column>)
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2011-03-13
              • 2013-11-10
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2018-08-31
              • 2016-04-09
              相关资源
              最近更新 更多