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:
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.
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
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
});
}
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 apublic
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();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With