5

array_walk在类中使用 with 闭包时遇到了一个奇怪的问题。在我使用 php 版本5.4.7的开发环境中不会出现问题,但在我的部署环境5.3.3中会出现问题。

以下代码在我的生产机器上运行良好,但在我的部署环境中崩溃:

<?php
    error_reporting(-1);

    Class TestArrayWalk
    {
        /** @var null|array */
        protected $userInput = null;

        /**
         * This expects to be passed an array of the users input from
         * the input fields.
         *
         * @param  array $input
         * @return void
         */
        public function setUserInput( array $input )
        {
            $this->userInput = $input;

            // Lets explode the users input and format it in a way that this class
            // will use for marking
            array_walk( $this->userInput, function( &$rawValue )
                {
                    $rawValue = array(
                        'raw' => $rawValue,
                        'words' => $this->splitIntoKeywordArray( $rawValue ),
                        'marked' => false,
                        'matched' => array()
                    );
                }
            );
        }

        public function getUserInput()
        {
            return $this->userInput;
        }

        protected function splitIntoKeywordArray( $input )
        {
            if ( ! is_string( $input )){ return array(); }
            return preg_split('/(\s|[\.,\/:;!?])/', $input, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
        }

    }


    $testArrayWalk = new TestArrayWalk();
    $testArrayWalk->setUserInput(
            array(
                'This is a test input',
                'This is another test input'
                )
        );

    var_dump( $testArrayWalk->getUserInput() );

我得到的错误是:这是该测试类Using $this when not in object context on line 26中的唯一用法。$this我假设在我使用的版本之间发生了一些变化,这使得上述代码在我的开发环境中成为可能。

我还假设由于我无法更改部署环境(它的客户端并且他们不会更改它),因此我将不得不使用 aforeach而不是array_walk.

我的问题是:鉴于上述情况,这是否可能在 5.3.3 中使用array_walk如果不是我如何foreach以与使用 array_walk 相同的方式使用(更具体地说是&$rawValue位)?

我的环境是:

  • 我的开发环境是PHP 5.4.7版本
  • 我的服务器(部署)环境是PHP 5.3.3版本

谢谢。

编辑 2

感谢所有帮助过的人。在您的帮助下,我完成了这项工作,并将我的工作代码发布到https://gist.github.com/carbontwelve/6727555以供将来参考。

4

3 回答 3

10

这在 PHP 手册中有描述:

版本说明
5.4.0 $this 可用于匿名函数。

匿名函数

可能的解决方法是将其重新分配给另一个变量并通过use

$_this = $this;
function() use($_this) { ... }

但请记住,您将无法访问私人和受保护的成员,因此您必须splitIntoKeywordArray公开

于 2013-09-26T17:30:35.990 回答
1

如果您正在使用,您也可以使用PHP < 5.4

public function setUserInput( array $input )
{
    $this->userInput = $input;
    $userInput_array = &$this->userInput;
    array_walk( &$userInput_array, function( &$rawValue ) use (&$userInput_array) {
        // use $userInput_array instaed of $this->userInput_array
    });
}
于 2013-09-26T17:17:51.533 回答
1

我在类中的私有函数中定义的 lambda 函数遇到了类似的问题:

MyClass{
    private $str="doesn't work :-(";
    private function foo(){
        $bar=function(){
            echo $this->str; // triggers an "Using $this when not in object context" error
        };
        $bar();
    }
}

PHP 5.3.0 的解决方案use:在您的父范围(即私有函数)中声明一个变量 $obj=&$this 并使用语言构造将其传递给匿名函数。还要确保您访问的函数/变量具有public可见性(受保护的|私有可能不起作用)。

MyClass{
    public $str="it just works :-)";
    private function foo(){
        $obj=&$this;
        $bar=function() use(&$obj){
            echo $this->str; // it works!
        };
        $bar();
    }
}
于 2015-12-06T17:16:19.020 回答