PHP 5.4 - '关闭 $this 支持'

Posted

技术标签:

【中文标题】PHP 5.4 - \'关闭 $this 支持\'【英文标题】:PHP 5.4 - 'closure $this support'PHP 5.4 - '关闭 $this 支持' 【发布时间】:2011-08-09 16:37:44 【问题描述】:

我看到 php 5.4 的新计划功能是:特征、数组解引用、JsonSerializable 接口和称为“closure $this support”的东西

http://en.wikipedia.org/wiki/Php#Release_history

虽然其他人要么立即清楚(JsonSeraliable,数组解引用),要么我查看了细节(特征),但我不确定“闭包 $this 支持”是什么。我在谷歌上搜索它或在 php.net 上找到任何关于它的东西都没有成功

有谁知道这应该是什么?

如果我不得不猜测,它的意思是这样的:

$a = 10; $b = 'strrrring';
//'old' way, PHP 5.3.x
$myClosure = function($x) use($a,$b)
             
                 if (strlen($x) <= $a) return $x;
                 else return $b;
             ;

//'new' way with closure $this for PHP 5.4
$myNewClosure = function($x) use($a as $lengthCap,$b as $alternative)
                 
                     if(strlen($x) <=  $this->lengthCap)) return $x;
                     else 
                     
                         $this->lengthCap++;  //lengthcap is incremented for next time around
                         return $this->alternative;
                     
                 ;

意义(即使这个例子是微不足道的)是在过去,一旦构造了闭包,绑定的“使用”变量就固定了。有了“closure $this support”,他们更像是你可以搞砸的成员。

这听起来正确和/或接近和/或合理吗?有谁知道这个“关闭 $this 支持”是什么意思?

【问题讨论】:

FWIW,5.4 还不是 PHP 主干的官方名称——它在内部仍然被称为“5.3.99”,关于它是否真的会存在一些争议5.4 与否(与 6.0 相比,这将与大型 Unicode 重写“6.0”分支无关)。 啊,很高兴知道。感谢您修复标签 【参考方案1】:

这已经为 PHP 5.3 计划好了,但是

对于 PHP 5.3 $this 对闭包的支持已被删除,因为无法就如何以理智的方式实现它达成共识。该 RFC 描述了在下一个 PHP 版本中实现它的可能途径。

这确实意味着你可以引用对象实例(live demo)

<?php
class A 
  private $value = 1;
  public function getClosure() 
  
    return function()  return $this->value; ;
  


$a = new A;
$fn = $a->getClosure();
echo $fn(); // 1

有关讨论,请参阅 PHP Wiki

Closures: Object extension

为了历史利益:

closures (rfc) removal-of-this (rfc:closures)

【讨论】:

哦,我走错了方向。你的意思是'$this' 是Foo 的实例,对吗?我认为 '$this' 是闭包本身。 use 还有必要吗? @jon 不,使用use 甚至是不可能的。迄今为止,您不能在任何 PHP 版本中使用 $this 作为词法变量。我更新了 Wiki 中的示例和一个显示当前 PHP 主干结果的键盘链接。 谢谢,太好了。顺便说一句 - public $closure 没有做任何事情,只是分散了你的注意力,你在其他方面表现得很好 @Gordon - 我认为 jon 在一般情况下是指 use - 不是特定于 $this。 AFAIK,use 仍然需要访问局部变量。我期待着放弃use ($self) 把戏。 :) @Bracketworks 我不能 100% 确定,但更多参与该决定的人告诉我,他们认为是 A。【参考方案2】:

Gordon 错过的一件事是重新绑定 $this。虽然他描述的是默认行为,但可以重新绑定它。

示例

class A 
    public $foo = 'foo';
    private $bar = 'bar';

    public function getClosure() 
        return function ($prop) 
            return $this->$prop;
        ;
    


class B 
    public $foo = 'baz';
    private $bar = 'bazinga';


$a = new A();
$f = $a->getClosure();
var_dump($f('foo')); // prints foo
var_dump($f('bar')); // works! prints bar

$b = new B();
$f2 = $f->bindTo($b);
var_dump($f2('foo')); // prints baz
var_dump($f2('bar')); // error

$f3 = $f->bindTo($b, $b);
var_dump($f3('bar')); // works! prints bazinga

闭包bindTo 实例方法(或者使用静态Closure::bind)将返回一个新闭包,$this 重新绑定到给定的值。范围通过传递第二个参数来设置,这将确定从闭包内访问时私有成员和受保护成员的可见性。

PHP: Closure Blog post: Closure Object Binding in PHP 5.4

【讨论】:

+1 用于描述bindTo() 功能,这是一个非常重要的功能。【参考方案3】:

基于@Gordon 的回答,可以在 PHP 5.3 中模仿闭包的一些 hacky 方面-$this。

<?php
class A

    public $value = 12;
    public function getClosure()
    
        $self = $this;
        return function() use($self)
        
            return $self->value;
        ;
    


$a = new A;
$fn = $a->getClosure();
echo $fn(); // 12

【讨论】:

是的,但一个显着的区别是您不能从闭包内访问$self 上的任何私有或受保护的属性或方法。 +1 哈哈,一年后找到了这个答案,它解决了我的问题。 ;) @jgivoni 你的意思是,在 PHP 5.3 中不能访问私有或受保护的变量? @Shiro,是的。 5.3 的此解决方法仅适用于公共属性。 @Pacerier,我不知道在 PHP 5.3 的闭包中访问非公共属性的任何解决方法。最好的建议是升级到 5.4 或更高版本。【参考方案4】:

只是建立在其他答案的基础上,我认为这个例子将展示 PHP 5.4+ 的可能性:

<?php

class Mailer 
    public    $publicVar    = 'Goodbye ';
    protected $protectedVar = 'Josie ';
    private   $privateVar   = 'I love CORNFLAKES';

    public function mail($t, $closure) 
        var_dump($t, $closure());
    


class SendsMail 
    public    $publicVar    = 'Hello ';
    protected $protectedVar = 'Martin ';
    private   $privateVar   = 'I love EGGS';

    public function aMailingMethod() 
        $mailer = new Mailer();
        $mailer->mail(
            $this->publicVar . $this->protectedVar . $this->privateVar,
            function() 
                 return $this->publicVar . $this->protectedVar . $this->privateVar;
            
        );
    


$sendsMail = new SendsMail();
$sendsMail->aMailingMethod();

// prints:
// string(24) "Hello Martin I love EGGS"
// string(24) "Hello Martin I love EGGS"

见:https://eval.in/private/3183e0949dd2db

【讨论】:

以上是关于PHP 5.4 - '关闭 $this 支持'的主要内容,如果未能解决你的问题,请参考以下文章

需要带有 PHP 5.4 版本的 XAMPP - windows [关闭]

Heroku 是不是支持 PHP? [关闭]

PHP5.3PHP5.4下安装ZendOptimizer或Zend Guard Loader的方法

meedu知识付费解决方案 v4.5.4源码

如何使用 PHP 构建支持票证系统? [关闭]

PhpStorm Laravel 5.4 自动外观支持