Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using $this when not in object context error within array_walk

Tags:

php

I am experiencing an odd problem with using array_walk with closures within a class. The problem does not arise within my development environment using php version 5.4.7 but it does on my deployment environment 5.3.3.

The following code runs fine on my production box, but crashes on my deployment environment:

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

The error I am getting is: Using $this when not in object context on line 26 which is the only usage of $this within that test class. I am assuming something changed between the versions I am using that has made the above code possible in my development environment.

I also assume that as I cant change the deployment environment (its the clients and they wont change it) that I am going to have to use a foreach rather than array_walk.

My question is this: Given the above, is this possible in 5.3.3 using array_walk if not how do I use foreach in the same way that I am using array_walk ( more specifically the &$rawValue bit)?

My environments are:

  • My development environment is PHP version 5.4.7
  • My server (deployment) environment is PHP version 5.3.3

Thanks.

Edit 2

Thanks to everyone who helped. With your help I got this working and have posted my working code to https://gist.github.com/carbontwelve/6727555 for future reference.

like image 702
carbontwelve Avatar asked Sep 26 '13 16:09

carbontwelve


3 Answers

This is described in PHP manual:

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

Anonymous functions

Possible workaround would be to re-assign this to another variable and pass it via use:

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

but keep in mind you will not be able to access private and protected members so you will have to make splitIntoKeywordArray public

like image 148
Adam Zielinski Avatar answered Nov 18 '22 18:11

Adam Zielinski


You may also use if you are using 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
    });
}
like image 26
The Alpha Avatar answered Nov 18 '22 18:11

The Alpha


I had a similar problem with a lambda function defined in a private function within a class:

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

Solution for PHP 5.3.0: declare a variable $obj=&$this in your parent scope (ie. the private function) and pass it to the anonymouse function by using the use language construct. Also make sure the function/variable that you access has a public visibility (protected|private might not work).

MyClass{
    public $str="it just works :-)";
    private function foo(){
        $obj=&$this;
        $bar=function() use(&$obj){
            echo $this->str; // it works!
        };
        $bar();
    }
}
like image 1
Eugen Mihailescu Avatar answered Nov 18 '22 16:11

Eugen Mihailescu