PHP 5 Reflection API performance

前端 未结 10 1010
不知归路
不知归路 2020-12-02 20:11

I\'m currently considering the use of Reflection classes (ReflectionClass and ReflectionMethod mainly) in my own MVC web framework, because I need to automatically instancia

10条回答
  •  南笙
    南笙 (楼主)
    2020-12-02 20:12

    The overhead is small so there is no big performance penalty other stuff like db, template processing etc are performance problems, test your framework with a simple action to see how fast it is.

    For example the code bellow (frontcontroller) which uses reflection does it jobs in a few miliseconds

    getParameters() as $parameter) {
                        $parameters[$parameter->getName()] = null;
                    }
                    return $parameters;
                }
            }
        }
    
        /**
         * Redirect or direct to a action or default module action and parameters
         * it has the ability to http redirect to the specified action
         * internally used to direct to action
         *
         * @param string $moduleName
         * @param string $actionName
         * @param array $parameters
         * @param bool $http_redirect
    
         * @return bool
         */
        function redirect($moduleName, $actionName, $parameters = null, $http_redirect = false) {
            self :: $moduleName = $moduleName;
            self :: $actionName = $actionName;
            // We assume all will be ok
            $ok = true;
    
            @include_once ( PATH . '/modules/' . $moduleName . '.php' );
    
            // We check if the module's class really exists
            if (!class_exists('mod_' . $moduleName, false)) { // if the module does not exist route to module main
                @include_once ( PATH . '/modules/main.php' );
                $modClassName = 'mod_main';
                $module = new $modClassName();
                if (method_exists($module, $moduleName)) {
                    self :: $moduleName = 'main';
                    self :: $actionName = $moduleName;
                    //$_PARAMS = explode( '/' , $_SERVER['REQUEST_URI'] );
                    //unset($parameters[0]);
                    //$parameters = array_slice($_PARAMS, 1, -1);
                    $parameters = array_merge(array($actionName), $parameters); //add first parameter
                } else {
                    $parameters = array($moduleName, $actionName) + $parameters;
                    $actionName = 'index';
                    $moduleName = 'main';
                    self :: $moduleName = $moduleName;
                    self :: $actionName = $actionName;
                }
            } else { //if the action does not exist route to action index
                @include_once ( PATH . '/modules/' . $moduleName . '.php' );
                $modClassName = 'mod_' . $moduleName;
                $module = new $modClassName();
                if (!method_exists($module, $actionName)) {
                    $parameters = array_merge(array($actionName), $parameters); //add first parameter
                    $actionName = 'index';
                }
                self :: $moduleName = $moduleName;
                self :: $actionName = $actionName;
            }
            if (empty($module)) {
                $modClassName = 'mod_' . self :: $moduleName;
                $module = new $modClassName();
            }
    
            $method = new ReflectionMethod('mod_' . self :: $moduleName, self :: $actionName);
    
            //sanitize and set method variables
            if (is_array($parameters)) {
                foreach ($method->getParameters() as $parameter) {
                    $param = current($parameters);
                    next($parameters);
                    if ($parameter->isDefaultValueAvailable()) {
                        if ($param !== false) {
                            self :: $params[$parameter->getName()] = sanitizeOne(urldecode(trim($param)), $parameter->getDefaultValue());
                        } else {
                            self :: $params[$parameter->getName()] = null;
                        }
                    } else {
                        if ($param !== false) {//check if variable is set, avoid notice
                            self :: $params[$parameter->getName()] = sanitizeOne(urldecode(trim($param)), 'str');
                        } else {
                            self :: $params[$parameter->getName()] = null;
                        }
                    }
                }
            } else {
                foreach ($method->getParameters() as $parameter) {
                    self :: $params[$parameter->getName()] = null;
                }
            }
    
            if ($http_redirect === false) {//no redirecting just call the action
                if (is_array(self :: $params)) {
                    $method->invokeArgs($module, self :: $params);
                } else {
                    $method->invoke($module);
                }
            } else {
                //generate the link to action
                if (is_array($parameters)) { // pass parameters
                    $link = '/' . $moduleName . '/' . $actionName . '/' . implode('/', self :: $params);
                } else {
                    $link = '/' . $moduleName . '/' . $actionName;
                }
                //redirect browser
                header('Location:' . $link);
    
                //if the browser does not support redirecting then provide a link to the action
                die('Your browser does not support redirect please click here ' . $link . '');
            }
            return $ok;
        }
    
        /**
         * Redirects to action contained within current module
         */
        function redirectAction($actionName, $parameters) {
            self :: $actionName = $actionName;
            call_user_func_array(array(&$this, $actionName), $parameters);
        }
    
        public function module($moduleName) {
            self :: redirect($moduleName, $actionName, $parameters, $http_redirect = false);
        }
    
        /**
         * Processes the client's REQUEST_URI and handles module loading/unloading and action calling
         *
         * @return bool
         */
        public function dispatch() {
            if ($_SERVER['REQUEST_URI'][strlen($_SERVER['REQUEST_URI']) - 1] !== '/') {
                $_SERVER['REQUEST_URI'] .= '/'; //add end slash for safety (if missing)
            }
    
            //$_SERVER['REQUEST_URI'] = @str_replace( BASE ,'', $_SERVER['REQUEST_URI']);
            // We divide the request into 'module' and 'action' and save paramaters into $_PARAMS
            if ($_SERVER['REQUEST_URI'] != '/') {
                $_PARAMS = explode('/', $_SERVER['REQUEST_URI']);
    
                $moduleName = $_PARAMS[1]; //get module name
                $actionName = $_PARAMS[2]; //get action
                unset($_PARAMS[count($_PARAMS) - 1]); //delete last
                unset($_PARAMS[0]);
                unset($_PARAMS[1]);
                unset($_PARAMS[2]);
            } else {
                $_PARAMS = null;
            }
    
            if (empty($actionName)) {
                $actionName = 'index'; //use default index action
            }
    
            if (empty($moduleName)) {
                $moduleName = 'main'; //use default main module
            }
            /* if (isset($_PARAMS))
    
              {
    
              $_PARAMS = array_slice($_PARAMS, 3, -1);//delete action and module from array and pass only parameters
    
              } */
            return self :: redirect($moduleName, $actionName, $_PARAMS);
        }
    }
    

提交回复
热议问题