3

可能重复:
PHP 方法链接?

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

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

这是什么结构?

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

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

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

4

6 回答 6

6

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

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

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

->运算符也是左关联的。因此,表达式 like$a->b->c的解释方式与前面的示例类似:首先解释器$a->b通过查找调用bin的成员进行求值a,然后查找调用cin that 的成员!这假设$a->b实际评估为一个对象;如果没有,那么 PHP 解释器会给你一个错误:“试图获取非对象的属性”。

这种范式可以无限扩展:$a->b->c->d->e->f->g->....等等。

在 Fluent Interface 设计模式中,这是通过让所有实例方法返回实例来实现的。所以$a->b()返回$a。因此,与先调用再调用$a->b()->c()是完全一样的。$a->b()$a->c()

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

于 2012-09-22T04:12:52.520 回答
4

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

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

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

所以:

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

真的只是简写:

$result = $pdo->queryOneRow(...);
$result->getValue(<some column>)
于 2012-09-22T03:55:48.473 回答
1
$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 必须返回某个类的对象。

希望有帮助...

于 2012-09-22T04:01:00.600 回答
0

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

$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),并且由于再次返回同一辆自行车,您可以将其放慢速度同一行。

免责声明:这个例子确实是通用的,但它应该有助于说明问题的答案。

于 2012-09-22T03:57:43.257 回答
0

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

例如。

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();  
于 2012-09-22T04:02:40.513 回答
0

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

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

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

于 2012-09-22T04:54:43.343 回答