首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >迁移到PHP8.0:使用$this时取消绑定$this

迁移到PHP8.0:使用$this时取消绑定$this
EN

Stack Overflow用户
提问于 2021-02-03 16:19:55
回答 2查看 2K关注 0票数 4

一步一步地将我的项目从PHP7.1迁移到PHP8.0

在正式的PHP手册中,在“从PHP7.3.x迁移到PHP7.4.x”一章的“弃用特性”一章中,我试图理解以下贬义描述

当使用$this $this 时,取消绑定的 对于使用$this的非静态闭包,取消绑定$this是不可取的.

不过,没有成功。

这就是为什么我会感激,如果有人能详细解释我,这意味着什么。也许一个代码片段也会有帮助。

非常感谢您的时间!

也许这也有助于解释

在我的项目中,我只有一种情况,在我看来,这个不推荐的通知是可以应用的:下面所示的RouteCollection类的方法RouteCollection。我更喜欢粘贴类的更多代码,以帮助您理解我使用executeGroupHandler方法的上下文。

RouteCollection类:

代码语言:javascript
复制
<?php

namespace Packages\Router;

//...
use Packages\Router\RouteCollectionInterface;


/**
 * Route collection.
 */
class RouteCollection implements RouteCollectionInterface {

    //...

    /**
     * Group patterns list. Indexed array.
     *
     * Each time a group handler is executed its pattern is saved in this list.
     * All addRoute operations taken place inside the scope of a group handler
     * prefix the pattern of the corresponding route with the saved group pattern.
     *
     * @var array
     */
    private $groupPatterns = [];

    //...

    /**
     * Add a group (helper method).
     *
     * @param string $pattern Group pattern.
     * @param \Closure $handler Group handler.
     * @return $this
     */
    public function group(string $pattern, \Closure $handler) {
        $this->addGroup($pattern, $handler);
        return $this;
    }

    /**
     * Add a group.
     *
     * @param string $pattern Group pattern.
     * @param \Closure $handler Group handler.
     * @return $this
     */
    private function addGroup(string $pattern, \Closure $handler) {
        $this->saveGroupPattern($pattern);

        $this->executeGroupHandler($handler);

        /*
         * Remove the last group pattern from the group patterns list. This step
         * is performed only after all calls for adding groups/routes inside the
         * scope of the current group handler have finished their processing.
         */
        $this->popLastGroupPattern();

        return $this;
    }

    /**
     * Save a group pattern.
     *
     * @param string $pattern Group pattern.
     * @return $this
     */
    private function saveGroupPattern(string $pattern) {
        $this->groupPatterns[] = $pattern;
        return $this;
    }

    /**
     * Execute a group handler.
     *
     * Temporarily bind the group handler to the route collection 
     * object - defined by the argument in Closure::call - and 
     * execute it. Inside the scope of the group handler, the route 
     * collection will be accessed using the keyword "$this".
     * 
     * @link https://www.php.net/manual/en/closure.call.php Closure::call
     *
     * @param \Closure $handler Group handler.
     * @return mixed The return value of calling the handler.
     */
    private function executeGroupHandler(\Closure $handler) {
        return $handler->call($this);
    }

    /**
     * Pop the group pattern off the end of group patterns list.
     *
     * @return string The popped group pattern.
     */
    private function popLastGroupPattern() {
        return array_pop($this->groupPatterns);
    }

}

使用RouteCollection类:

定义了RouteCollection类后,我使用它类似于以下内容:

代码语言:javascript
复制
<?php

use Packages\Router\RouteCollection;
use SampleMvc\App\View\Template\Users\AddUser as AddUserView;
use SampleMvc\App\Controller\Users\AddUser as AddUserController;

$routeCollection = new RouteCollection();

// Add a group of routes to the route collection.
$routeCollection->group('/users/add', function() {
    $this->get('', [AddUserView::class, 'index']);

    $this->post('', [
        'controller' => AddUserController::class,
        'view' => [AddUserView::class, 'addUser'],
    ]);
});

//...
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-02-03 17:41:46

反对的是在本RFC中提议(并接受),它给出了关于什么是不推荐的以及为什么不推荐的更多细节。

最后一句解释了哪些闭包受到影响:

特别是,这适用于在非静态方法中声明的非静态闭包。首先,可以通过将闭包标记为静态来避免$this绑定。

后来进一步缩小了在这个承诺中的范围,因此它只适用于闭包中实际上提到了$this的闭包。

与此同时,第一句给出了一个更清楚的例子,说明了所反对的是什么:

目前,可以通过使用$this从原来有一个闭包的闭包中解除$closure->bindTo(null)变量的绑定。

关键字是取消绑定的而不是重新绑定的,以及示例中的null

尼基塔在本评论中有更多的背景

我们之所以对这种弃用感兴趣,完全是为了支持PHP8中与$this访问相关的一些性能改进,这是通过删除对非静态方法的静态调用来实现的。$this访问可以分为两类:已知$this为非空的访问和不为空的访问。方法调用(will)属于前一类。这样,闭包也将归入前一类。

换句话说,在PHP8中,引擎会盲目地假设闭包中对$this的任何引用实际上都是一个对象,而不是null。

因此,不推荐的特定场景是有一个闭包提到了$this,然后您解除了它的绑定,这样$this就不会被设置为任何东西。只要您为$this提供了一个新的值,您就应该不受影响,因为$this永远不是null

票数 3
EN

Stack Overflow用户

发布于 2021-02-03 17:24:20

好的问题,我也不明白PHP中“闭包的非绑定变量”意味着什么。

我编写了一个简单的测试来检查绑定另一个$this是否可以被认为是“取消绑定的$this":

代码语言:javascript
复制
class ClosureTest extends TestCase
{

    private $x = 1;

    public function testClosure(): void
    {
        var_dump(\PHP_VERSION);
        $callable = function (): int {
            return $this->x;
        };
        self::assertSame(1, \call_user_func($callable));

        $closure = \Closure::fromCallable($callable);

        $obj = new class {
            private $x = 2;
        };
        self::assertSame(2, $closure->call($obj));
    }
}

我在7.3和8.0下运行了它,没有收到任何通知,所以您的代码也可能在8.0下运行是安全的。但我会进一步调查这个问题。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66031512

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档