skip to Main Content

Considering the following PHP code:

class Vacation 
{
  protected $onSuccess;
  protected $friend;

  public function onSuccess(callable $callback): self
  {
    $this->onSuccess = $callback;
    return $this;
  }

  public function go()
  {
    echo 'gone' . PHP_EOL;

    $this->friend = 'John';

    call_user_func($this->onSuccess, $this->friend);
  }
}

(new Vacation())
  ->onSuccess(function(){
    echo 'to the beach' . PHP_EOL;
    echo 'with ' . $friend . PHP_EOL; // this doesn't work, $this or self either
  })
  ->go();

Is it possible to access the $friend variable in any way from the closure above?
It seems like it shouldn’t be possible because of the scope of the closure.

2

Answers


  1. No, it is not possible to access the $friend variable in the closure above because it is defined as a protected property of the Vacation class and is not accessible outside the class.

    Additionally, the closure does not have access to the $this or $self variables that point to the current object instance, so it cannot access the $friend property via $this->friend or self::$friend.

    If you want to access the $friend property from within the closure, you could modify the onSuccess method to accept an additional argument that sets the value of $friend and pass it when calling the closure:

    class Vacation 
    {
      protected $onSuccess;
      protected $friend;
    
      public function onSuccess(callable $callback): self
      {
        $this->onSuccess = $callback;
        return $this;
      }
    
      public function go()
      {
        echo 'gone' . PHP_EOL;
    
        $this->friend = 'John';
    
        call_user_func($this->onSuccess, $this->friend, $this);
      }
    }
    
    (new Vacation())
      ->onSuccess(function($friend, $vacation){
        echo 'to the beach' . PHP_EOL;
        echo 'with ' . $friend . PHP_EOL; // this now works
        echo 'on a ' . get_class($vacation) . PHP_EOL; // also possible to access the object instance
      })
      ->go();
    

    Here, we have added a second argument to the closure that allows the value of $friend to be passed in from the go method. We also pass the current object instance as a second argument, which allows access to the protected $friend property via $vacation->friend.

    Login or Signup to reply.
  2. The Manider solution is fine but you can use this kind of snippet

    <?php
    class Vacation {
    protected $onSuccess;
    protected $friend;
    
    public function onSuccess( callable $callback ): self {
        $this->onSuccess = $callback;
        return $this;
    }
    
    public function getFriend( ) {
        return $this->friend;
    }
    
    public function go( ) {
        echo 'gone' . PHP_EOL;
        $this->friend = 'John';
        call_user_func( $this->onSuccess, $this );
    }
    }
    
    (new Vacation())->onSuccess( function ( $vacation ) {
      echo 'to the beach' . PHP_EOL;
      echo 'with ' . $vacation->getFriend() . PHP_EOL; // this works
      echo 'on a ' . get_class( $vacation ) . PHP_EOL; // also possible to access the object instance
    } )->go();
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search