Aristona
Aristona

Reputation: 9351

How can I make a call to desired function using Closure object?

I created a basic class to play with Closure object a bit. I don't understand the behaviour of this application/closures so I wanted to ask a few things. My mind is pretty cloudy at the moment so I don't know why something runs or why not.

<?php

class Route
{
     public static $bindings = array();
     public static $dispatch = array();

     public static function bind($bind)
     {
         self::$bindings[] = $bind;
     }

     public static function getAllBindings()
     {
         return (array) self::$bindings;
     }

     public static function get($binding, Closure $dispatch)
     {

         if(in_array($binding, self::$bindings))
         {
             if(is_callable($dispatch))
             {
                 return call_user_func($dispatch);
             }
             else
             {
                 die("Dispatch method is not callable.");
             }
         }
         else
         {
             die("Binding is not found in bindings array.");
         }
     }

     public static function test()
     {
         echo "Test ran!";
     }
 }

Basically, we bind bindings (such as /admin, /account, /profile etc.) Then, we try to call a method using closure.

// Let's bind account and admin as available bindings
    Route::bind('account');
    Route::bind('admin');

// Let's try doing a get call with parameter "account"
    Route::get('account', function() { 
         // This is where I'm stuck. See below examples:
         // Route::test();
         // return "test";
         // return "testa";
         // return self::test();
    });

If you checked above, here are my questions:

  1. If I provide a non-existent method, is_callable check does not run and I get a php fatal error. Isn't is_callable a valid check for checking inexistent methods? Why does it happen?
  2. If I provide return "Test"; in the closure, is my $closure parameter in get method going to contain "Test" string?
  3. Can I pass a methods from different classes inside the closure? Like:

    Route::get('account', function () {
        if(User::isLoggedIn() !== true)
             return Error::login_error('Unauthorized.');
    });
    
  4. If so, in which scope this call is being made? PHP's scope in closure, or does call_user_func call it inside Route class' scope since it is passed to it via closure? (To clear it a bit more, PHP's scope may do $route->get but Closure scope may use $this->get)
  5. Is there any way to dump Closure object like var_dump/print_r to see it's contents?

A short guidance will get me going. I know PHP but using closures is pretty new to me.

Thanks alot and I appreciate your replies.

Upvotes: 0

Views: 241

Answers (1)

hek2mgl
hek2mgl

Reputation: 158100

You won't need that is_callable() check as the Closure type hint in the method declaration already ensures this. Also you don't need call_user_func(). This will give you the following get() method:

 public static function get($binding, Closure $dispatch)
 {

     if(!in_array($binding, self::$bindings))
     {
         die("Binding is not found in bindings array.");
     }

     return $dispatch();
 }

Note : Currently the $binding param will just being used in a check, but not as a param to $dispatch(), what would I have expected. I can't see a reason for that. You should rethink this part


I found another hidden question in your post:

// Let's try doing a get call with parameter "account"
Route::get('account', function() { 
    // This is where I'm stuck. See below examples:
    // Route::test();
    // return "test";
    // return "testa";
    // return self::test();
});

It should look like:

// Let's try doing a get call with parameter "account"
Route::get('account', function() { 
    // Both should work well:
    // Route::test();
    // .. or 
    // return self::test();
});

Upvotes: 1

Related Questions