0

Working on a small php MVC project and I got stuck trying to retrive the values from the url (think of id's and such). I am trying to get this values inside each controller method as method parameters but not sure if this is done easily or that I must get them directly inside each controller instead. As an example I have included the ProductController class.

example.com/post/349
example.com/user/4
example.com/product/4231

Files

// core controller class (not doing anything atm)
namespace Core;

class Controller 
{
    // nothing here for now
}



// product controller class
namespace App\Controllers;

use Core\{Controller, View};

class ProductController extends Controller 
{
    public function index(int $id = null)// I want to go this way 
    {
        // use id value here or not

        // render page
    }

    public function edit(int $id) 
    {
        // use id value here

        // render page
    }
}
user759235
  • 2,147
  • 3
  • 39
  • 77
  • 1
    What's your question about this? As you haven't shared how the controller is found, it's impossible to tell you how to get to that `$id` value – Nico Haase Aug 16 '21 at 09:44
  • You have to use something to query the actually requested path. Getting access to that depends on your runtime environment. For example, if you're running PHP with Apache `mod_php` the data is in `$_SERVER["PATH_INFO"]` or `$_SERVER["SCRIPT_URL"]` depending how you get the path from Apache to PHP. Most people use some framework that does this for you. For example, see https://stackoverflow.com/q/2261951/334451 – Mikko Rantalainen Aug 16 '21 at 12:31

2 Answers2

0

Use ReflectionFunctionAbstract $reflect$reflect->getParameters();

Get params List Array

And Build the $args array

call_user_func_array("method", $args);

In Thinkphp Framework, https://github.com/top-think/framework/tree/6.0/src/think /top-think/framework/blob/6.0/src/think/Container.php

    /**
     * 绑定参数
     * @access protected
     * @param ReflectionFunctionAbstract $reflect 反射类
     * @param array                      $vars    参数
     * @return array
     */
    protected function bindParams(ReflectionFunctionAbstract $reflect, array $vars = []): array
    {
        if ($reflect->getNumberOfParameters() == 0) {
            return [];
        }

        // 判断数组类型 数字数组时按顺序绑定参数
        reset($vars);
        $type   = key($vars) === 0 ? 1 : 0;
        $params = $reflect->getParameters();
        $args   = [];

        foreach ($params as $param) {
            $name           = $param->getName();
            $lowerName      = Str::snake($name);
            $reflectionType = $param->getType();

            if ($reflectionType && $reflectionType->isBuiltin() === false) {
                $args[] = $this->getObjectParam($reflectionType->getName(), $vars);
            } elseif (1 == $type && !empty($vars)) {
                $args[] = array_shift($vars);
            } elseif (0 == $type && array_key_exists($name, $vars)) {
                $args[] = $vars[$name];
            } elseif (0 == $type && array_key_exists($lowerName, $vars)) {
                $args[] = $vars[$lowerName];
            } elseif ($param->isDefaultValueAvailable()) {
                $args[] = $param->getDefaultValue();
            } else {
                throw new InvalidArgumentException('method param miss:' . $name);
            }
        }

        return $args;
    }
Siam
  • 33
  • 3
  • Of course, you need to define `Route` to parse `example.com/post/349` 。Like `/post/{$id}` – Siam Aug 16 '21 at 09:44
  • I have build a route class that works with an Request class in the same way but is there a nicer way to get these values as a sort of default setting in each controller rahter that calling the reflection class? – user759235 Aug 16 '21 at 10:09
  • I think it's the only way for get the value form url and setting for method. 1.Parse the method params 2.Build the args array form GET/POST/OTHER WAY (keep the sequence same with method setting) 3. call_user_func_array("method", $args); – Siam Aug 16 '21 at 14:33
0

You write a logic of routes and you wire the routes to the controllers
1 - You define a route and to this route you associate a controller
2 -You write a regular expression to extract the parameters ex: $ id from the route
3 - Then you write logic to transmit the extracted parameters to the controller
Ex :

 /**
 * Processing of the request
 * @return Response
 */
public function handle():Response{

    //Get controlleur matched with route 
    $controller = $this->request->parameters()->get('_controller');

    //Get route parameters like id etc.
    $arguments = $this->request->parameters()->get('_arguments');

   
   if (is_array($controller)) {
       //Get controller class
    $controller_class = $controller [0];

    $reflector = new ReflectionClass($controller_class);
    //Get controller instance (object)
    $controller [0] = $reflector->newInstanceArgs([$this]);

    // Call controller method with arguments
    $response = call_user_func_array($controller,$arguments);
   
   }elseif (is_callable($controller)) {//
       $response = $controller ($arguments);
   }
 
    return $response;
}