不在array_walk中的对象上下文错误时使用$ this

时间:2013-09-26 16:03:18

标签: php

在类中使用array_walk和闭包时,我遇到了一个奇怪的问题。使用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的唯一用法。我假设在我使用的版本之间发生了一些变化,这使我的开发环境中的代码成为可能。

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

我的问题是这样的:鉴于上述情况,如果不是{i}如何使用array_walk,我是否可以使用foreach使用array_walk(更具体地说是&$rawValue位)?

我的环境是:

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

感谢。

修改2

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

3 个答案:

答案 0 :(得分:10)

这在PHP手册中有描述:

Version Description
5.4.0   $this can be used in anonymous functions.

Anonymous functions

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

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

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

答案 1 :(得分: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
    });
}

答案 2 :(得分: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的解决方案:在父作用域(即私有函数)中声明变量$ obj =&amp; $ this,并使用{{}将其传递给anonymouse函数1}}语言构造。还要确保您访问的函数/变量具有use可见性(protected | private可能不起作用)。

public