mr_reboot's avatar

External method for callback?

I am trying to call another method in my class as the callback for collection->map() (or any of the other callable functions laravel uses everywhere).

So instead of having something like this:

$collection->map(function ($item, $key) { 
// ...in line code here 
})

I'd rather do something like this:

$collection->map($this->some_callback_method($item, $key))

Obviously I get an error that $item and $key are not defined. Is there a way I can do this in a class? The PHP docs only show functions outside of classes for callbacks. The laravel docs do it all inline. I'd prefer to have the code seperate in some cases to keep things clean.

Thanks!

0 likes
7 replies
LaryAI's avatar
Level 58

Certainly! You can achieve this by using a method reference in PHP. Instead of directly calling the method, you can pass an array containing the object and the method name to the map function. Here's how you can do it:

  1. Define the callback method in your class.
  2. Use an array to reference the method when passing it to map.

Here's an example:

class MyClass {
    public function processCollection($collection) {
        // Use [$this, 'someCallbackMethod'] to reference the method
        $collection->map([$this, 'someCallbackMethod']);
    }

    public function someCallbackMethod($item, $key) {
        // Your callback logic here
        // For example, let's just return the item for now
        return $item;
    }
}

// Example usage
$collection = collect([1, 2, 3, 4, 5]);
$instance = new MyClass();
$instance->processCollection($collection);

In this example:

  • processCollection is a method in MyClass that takes a collection and maps it using the someCallbackMethod.
  • someCallbackMethod is the method that will be used as the callback for the map function.

By passing [$this, 'someCallbackMethod'] to map, you are effectively telling PHP to use the someCallbackMethod of the current instance ($this) as the callback function.

This keeps your code clean and allows you to separate the callback logic into its own method.

mr_reboot's avatar
$this->worksheet->items->map([$this, 'key_month_set']);

Gives me this error:

Illuminate\Database\Eloquent\Collection::map(): Argument #1 ($callback) must be of type callable, array given,

My method is defined like this in same class:

    private function key_month_set($item, $key): void
    {
					//...some code here
	}
puklipo's avatar

[$this, 'key_month_set'] only works for public methods.

public function key_month_set()
MohamedTammam's avatar

You should pass the method itself, not calling it.

$collection->map($this->some_callback_method)
mr_reboot's avatar

@MohamedTammam I tried this but I get a property not found error.

Undefined property: ***\WorksheetRepository::$key_month_set
maxxd's avatar

Call the method from within the callback.

    /**
     * Execute the console command.
     */
    public function handle()
    {
        $whatever = \collect([
			'test one',
			'test two',
			'test three',
			'test four',
		]);
		$whatever->map(function($value, $key){
			$this->testOne($value, $key);
		});
		return self::SUCCESS;
    }

	private function testOne(string $foo, int $bar)
	{
		$this->line("{$bar}::{$foo}");
	}

Please or to participate in this conversation.