Using Reflection in Calling Method from URL parameters in MVC

Currently I am working on a simple MVC framework of mine. So my Core library loads the controller and method based on the URL with the given parameters. The parameters are an array after exploding the URL. This is done by using call_user_func_array([$controller, $method], $params). To prevent user from passing incorrect parameters in URL I came up with the following solution using Reflection to check whether correct number and types of parameters are passed.

Core

class Core {

    public function __construct(){
      $url = $this->getUrl();
      // After loading correct Model and Controller (and called method)...

      // Get params - Any values left over in url are params 
      $this->params = $url ? array_values($url) : [];
      $this->params = $this->correctURLTypes($this->params);
      
      $r = new ReflectionMethod($this->currentController, $this->currentMethod);
      $requiredArgs = $this->numberOfRequiredArgs(); // Only Required params not optional
      $totalArgs = $r->getNumberOfParameters(); // Total no. of params in method (required + optional)
      $givenArgs = count($this->params);
      if($givenArgs >= $requiredArgs && $givenArgs <= $totalArgs) {
        // get params at index 1, 2, 3 ... $givenArgs
        for ($i = 0; $i < $givenArgs; $i++) { 
          $param = new ReflectionParameter(array($this->currentController, $this->currentMethod), $i);
          $paramType = $param->getType();

          if($paramType == 'string') $this->params[$i] = (string) $this->params[$i]; 
          // cast int/bool/float if expecting string

          $givenType = Utils::typeOf($this->params[$i]); // static function to return type of variable
          
          if(!is_null($paramType) && $paramType != $givenType) { // if type specified and dont match
            die("Types dont match");
          }
        }
        call_user_func_array([$this->currentController, $this->currentMethod], $this->params);
      }  else {
        die("Arg count incorrect");
      }
    }

    public function getUrl(){
        if(isset($_GET['url'])){
          $url = rtrim($_GET['url'], '/');
          $url = filter_var($url, FILTER_SANITIZE_URL);
          $url = explode('/', $url);
          return $url;
        }
    }

    public function correctURLTypes($arr) {
      foreach ($arr as $key => $value) {
        // string, int, float, bool ONLY
        if(is_numeric($value)) {
          if(ctype_digit($value)) {
            $arr[$key] = (int) $value;
          } else {
            $val = $value+0;
            if(is_float($val)) {
              $arr[$key] = (float) $value;
            }
          }
        } else {
          if(in_array($value, ['true', 'false'])) {
            if($value == 'true') 
              $arr[$key] = true;
            else 
              $arr[$key] = false;
          } else {
            $arr[$key] = (string) $value;
          }
        }
      }
      return $arr;
    }

    public function numberOfRequiredArgs() {
      $r = new ReflectionMethod($this->currentController, $this->currentMethod);
      $required = 0;

      foreach ($r->getParameters() as $key => $val) {
        if(!$val->isDefaultValueAvailable()) $required++;
      }

      return $required;
    }
}

So a method can be called which has required type specified and may have optional parameters like:
public function show(int $id, bool $edit = true) {


I was unsure if this is a good way of doing it and if its a hack. I wanted feedback and suggestions for loading the methods and parameters in such a way.

I use the Active Record Design Pattern, but that seems like a little bit of overkill to me? Though someone who does MVC will know better than me.

I just control what my classes parameters can access by making it protected:

static protected array $params = [];

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.