迁移到 PHP 8.0:使用 $this 时解除绑定 $this

dak*_*kis 7 php php-7 php-7.4 php-8

我正在逐步将我的项目从PHP 7.1迁移到PHP 8.0

在PHP官方手册中,在“从PHP 7.3.x迁移到PHP 7.4.x”一章的“弃用功能”子章节中,我尝试理解以下弃用描述

解除绑定$this$this使用

解除绑定$this使用的非静态闭包$this解除绑定。

虽然,没有成功。

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

非常感谢您的宝贵时间!


也许这也有助于解释

在我的项目中,我认为只有一种情况可以应用此弃用通知:下面介绍的类executeGroupHandler的方法RouteCollection。我更愿意粘贴更多的类代码,以帮助您理解我使用该方法的上下文executeGroupHandler

路由集合类:

<?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);
    }

}
Run Code Online (Sandbox Code Playgroud)

RouteCollection类的使用:

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

<?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'],
    ]);
});

//...
Run Code Online (Sandbox Code Playgroud)

IMS*_*SoP 3

此 RFC 中提出(并接受)了弃用,其中提供了有关弃用内容及其原因的更多详细信息。

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

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

后来在此提交中进一步缩小了范围,以便它仅适用于$this闭包中实际提到的闭包。

与此同时,第一句话给出了一个更清晰的例子来说明什么是被弃用的:

目前,可以通过使用 来解除 $this 变量与最初具有该变量的闭包的绑定$closure->bindTo(null)

关键字是unbind而不是rebindnull ,以及示例中的the 。

尼基塔在此评论中提供了更多背景信息:

我们对此弃用感兴趣的原因完全是为了在 PHP 8 中实现与 $this 访问相关的一些性能改进,这是通过删除对非静态方法的静态调用来实现的。$this 访问可以分为两类:我们知道 $this 为非空的访问和我们不知道的访问。方法调用(will)属于前一类。随着这种弃用,关闭也将属于前一类。

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

因此,不推荐使用的特定场景是,您有一个提到 的闭包$this,然后您将其解除绑定,因此$this根本不会设置为任何内容。只要您为 提供新值$this,您就应该不受影响,因为$this永远不会受到影响null