Solicitud de controlador basado únicamente en Reflexiones Ver. 2 -- php campo con reflection camp codereview Relacionados El problema

Request handler based solely on reflections ver. 2


3
vote

problema

Español

Esta pregunta está conectada a la anterior: Solicitar controlador basado únicamente en Reflexiones

He editado el código, tomando Respuesta de Tim con respecto a la edición de la cohesión de la clase del kernel. < / p>

  <?php  namespace Qobox;  class Kernel {     private $request;     private $module;      /**      * Kernel constructor.      */     public function __construct()     {         $this->request = $this->getRequest();         $requestedModuleName = $this->getModule();         $moduleInstance = $this->getModuleInstance($requestedModuleName);         $this->setModuleProperties($moduleInstance);         $moduleMethod = $this->getModuleMethod();         $argumentArray = $this->setMethodArguments($moduleMethod);         $moduleMethod->invokeArgs($moduleInstance, $argumentArray);     }      /**      * Grab the Fully Qualified Module Name, including namespace      *      * @return string $FullyQualifiedModuleName      */     private function getModule()     {         $moduleList = require_once "Config/Modules.php";         /*$moduleList = array(             "Main" => array(),             "Nord" => array("Main"),         );*/         $namespaceArray = $this->getModuleNamespace($moduleList, array("\Output"));         return implode("\", $namespaceArray);     }      /**      * Get the requested module instance      *      * @param $requestedModuleName      * @return object      */     private function getModuleInstance($requestedModuleName)     {         try {             $this->module = new ReflectionClass($requestedModuleName);         } catch (ReflectionException $e) {             print_r($e);             exit;         }          if ($this->module->isInstantiable() === TRUE) {             return $this->module->newInstance();         } else         {             // todo: proper user-friendly error handler             echo 'Module is not instantiable';             exit;         }     }      /**      * Get the requested method of the requested module      *      * @return mixed      */     private function getModuleMethod()     {         $moduleMethods = $this->module->getMethods(ReflectionMethod::IS_PUBLIC);          foreach ($moduleMethods as $methodKey => $method) {             if ($method->name == "__construct") {                 unset($moduleMethods[$methodKey]);             }         }         $moduleMethods = array_values($moduleMethods);          if (!empty($this->request) && $this->module->hasMethod(array_keys($this->request)[0])) {             // the method exists, load it             $moduleMethod = $this->module->getMethod(array_shift($this->request));         } else {             $moduleMethod = $moduleMethods[0];         }          return $moduleMethod;     }      /**      * Combines the full qualified namespace for requested module      * Recursive function      *      * @param array $moduleList      * @param array $namespaceArray      * @return array      */     private function getModuleNamespace(Array $moduleList, Array $namespaceArray = array()) {   //print_r(is_array($moduleList[array_keys($moduleList)[0]]));exit;     if (!empty($this->request) && (array_key_exists(array_keys($this->request)[0], $moduleList) || in_array(array_keys($this->request)[0], $moduleList))) {         $loader = array_shift($this->request);     } else if (is_array($moduleList[array_keys($moduleList)[0]])) {         $loader = array_keys($moduleList)[0];     } else {         $loader = array_values($moduleList)[0];     }      $namespaceArray[] = $loader;      if (array_key_exists($loader, $moduleList) && is_array($moduleList[$loader]) && !empty($moduleList[$loader])) {         return $this->getModuleNamespace($moduleList[$loader], $namespaceArray);     } else {         return $namespaceArray;     } }      /**      * Get the module properties' instances      * Recursive function      *      * @param array $propertyValue      * @param String $moduleName      * @return stdClass      */     private function getModulePropertyInstance(Array $propertyValue, String $moduleName)     {         $propertyClass = new stdClass();         foreach ($propertyValue as $moduleCaller => $moduleSubname) {             if (is_array($moduleSubname) === TRUE) {                 $propertyClass->$moduleCaller = $this->getModulePropertyInstance($moduleSubname, $moduleName . "\" . $moduleCaller);             } else {                 $propertyClass->$moduleSubname = $this->getSubmodule($moduleName . "\" . $moduleSubname);             }         }          return $propertyClass;     }      /**      * Get the parsed _$REQUEST array      *      * @return array      */     private function getRequest()     {         $request = array();         foreach ($_REQUEST as $key => $value) {             $key = htmlspecialchars($key, ENT_QUOTES | ENT_DISALLOWED | ENT_HTML5, "UTF-8");             $value = htmlspecialchars($value, ENT_QUOTES | ENT_DISALLOWED | ENT_HTML5, "UTF-8");              if (empty($value)) {                 $request[$key] = $key;             } else {                 $request[$key] = $value;             }         }          return $request;     }      /**      * Get submodule instance      *      * @param String $submoduleName      * @return object      */     private function getSubmodule(String $submoduleName)     {         $namespacePrefixList = array("\Qobox\", "\Modules\", "\Output\");         foreach ($namespacePrefixList as $namespacePrefix) {             $submoduleNamespace = $namespacePrefix . $submoduleName;              try {                 $submodule = new ReflectionClass($submoduleNamespace);                 break;             } catch (ReflectionException $e) {             }         }          $submoduleInstance = $submodule->newInstance();         $submoduleProperties = $submodule->getProperties(ReflectionProperty::IS_PROTECTED);          foreach ($submoduleProperties as $submoduleProperty) {             $submoduleProperty->setAccessible(true);             if (empty($submoduleProperty->getValue($submoduleInstance))) {                 $submoduleName = $submoduleProperty->name;                 $submoduleProperty->setValue($submoduleInstance, $this->getSubmodule($submoduleName));             }             $submoduleProperty->setAccessible(false);         }         return $submoduleInstance;     }      /**      * Set requested module arguments      *      * @param $moduleMethod      * @return array      */     private function setMethodArguments($moduleMethod)     {         $argumentArray = array();         $moduleMethodArguments = $moduleMethod->getParameters();         foreach ($moduleMethodArguments as $Parameter) {             if (isset($request[$Parameter->name]) && !empty($request[$Parameter->name]) && $request[$Parameter->name] != $Parameter->name) {                 $argumentArray[$Parameter->name] = $request[$Parameter->name];             } else {                 if ($Parameter->isDefaultValueAvailable() === TRUE) {                     $argumentArray[$Parameter->name] = $Parameter->getDefaultValue();                 } else {                     $argumentArray[$Parameter->name] = "";                 }             }         }          return $argumentArray;     }      /**      * Set requested module properties      *      * @param $moduleInstance      */     private function setModuleProperties($moduleInstance)     {         $moduleProperties = $this->module->getProperties();         foreach ($moduleProperties as $property)         {             $moduleName = $property->name;             $property->setAccessible(true);             $propertyValue = $property->getValue($moduleInstance);              if (is_array($propertyValue) === TRUE)             {                 $propertyClass = $this->getModulePropertyInstance($propertyValue, $moduleName);                 $property->setValue($moduleInstance, $propertyClass);             } else             {                 $property->setValue($moduleInstance, $this->getSubmodule($moduleName . "\" . $moduleName));             }         }     } }   

Tengo la intención de dejar el saneamiento de entrada tal como está, coloque las variables y posteriores a las variables indistincesiblemente en una variable, solo desinfectando cada uno con htmlspecialchars($key, ENT_QUOTES | ENT_DISALLOWED | ENT_HTML5, "UTF-8") . Los archivos y las variables del servidor se dejan como está y se tratan en otra clase (módulo de kernel).

La lista blanca de enrutamiento se pone como datos simulados en el comentario en el código. Entonces,

  • la peiding para index.php?Main cargará la clase /Output/Main/Main.php
  • la peiding para index.php?Bananaz cargará la clase /Output/Main/Main.php (porque 9988777665544336 está cargado de forma predeterminada)

Claro, podría decir que todos los métodos públicos son, bueno, público.

Bueno, sí, solo las funciones públicas están disponibles, la lógica requerida está en private y 9988776655544338 Funciones. No creo que los usuarios puedan meterse algo aquí.

un ejemplo extendido

salida / ejemplo / example.php

  <?php  namespace OutputMain;  class Main {     private $Test;     private $Database;      public function runExample($hello)     {         echo $hello. ', ';         echo $this->Test->printWorld();         echo '<br><pre>';         print_r($this);     } }   

módulos / prueba / test.php

  htmlspecialchars($key, ENT_QUOTES | ENT_DISALLOWED | ENT_HTML5, "UTF-8")0  

qobox / base de datos / base de datos.php

  htmlspecialchars($key, ENT_QUOTES | ENT_DISALLOWED | ENT_HTML5, "UTF-8")1  

La salida de llamadas htmlspecialchars($key, ENT_QUOTES | ENT_DISALLOWED | ENT_HTML5, "UTF-8")2 sería similar a esta:

  htmlspecialchars($key, ENT_QUOTES | ENT_DISALLOWED | ENT_HTML5, "UTF-8")3  

Original en ingles

This question is connected to the previous one: Request handler based solely on reflections

I have edited the code, taking tim's answer in regard, editing the Kernel class cohesion.

<?php  namespace Qobox;  class Kernel {     private $request;     private $module;      /**      * Kernel constructor.      */     public function __construct()     {         $this->request = $this->getRequest();         $requestedModuleName = $this->getModule();         $moduleInstance = $this->getModuleInstance($requestedModuleName);         $this->setModuleProperties($moduleInstance);         $moduleMethod = $this->getModuleMethod();         $argumentArray = $this->setMethodArguments($moduleMethod);         $moduleMethod->invokeArgs($moduleInstance, $argumentArray);     }      /**      * Grab the Fully Qualified Module Name, including namespace      *      * @return string $FullyQualifiedModuleName      */     private function getModule()     {         $moduleList = require_once "Config/Modules.php";         /*$moduleList = array(             "Main" => array(),             "Nord" => array("Main"),         );*/         $namespaceArray = $this->getModuleNamespace($moduleList, array("\\Output"));         return implode("\\", $namespaceArray);     }      /**      * Get the requested module instance      *      * @param $requestedModuleName      * @return object      */     private function getModuleInstance($requestedModuleName)     {         try {             $this->module = new \ReflectionClass($requestedModuleName);         } catch (\ReflectionException $e) {             print_r($e);             exit;         }          if ($this->module->isInstantiable() === TRUE) {             return $this->module->newInstance();         } else         {             // todo: proper user-friendly error handler             echo 'Module is not instantiable';             exit;         }     }      /**      * Get the requested method of the requested module      *      * @return mixed      */     private function getModuleMethod()     {         $moduleMethods = $this->module->getMethods(\ReflectionMethod::IS_PUBLIC);          foreach ($moduleMethods as $methodKey => $method) {             if ($method->name == "__construct") {                 unset($moduleMethods[$methodKey]);             }         }         $moduleMethods = array_values($moduleMethods);          if (!empty($this->request) && $this->module->hasMethod(array_keys($this->request)[0])) {             // the method exists, load it             $moduleMethod = $this->module->getMethod(array_shift($this->request));         } else {             $moduleMethod = $moduleMethods[0];         }          return $moduleMethod;     }      /**      * Combines the full qualified namespace for requested module      * Recursive function      *      * @param array $moduleList      * @param array $namespaceArray      * @return array      */     private function getModuleNamespace(Array $moduleList, Array $namespaceArray = array()) {   //print_r(is_array($moduleList[array_keys($moduleList)[0]]));exit;     if (!empty($this->request) && (array_key_exists(array_keys($this->request)[0], $moduleList) || in_array(array_keys($this->request)[0], $moduleList))) {         $loader = array_shift($this->request);     } else if (is_array($moduleList[array_keys($moduleList)[0]])) {         $loader = array_keys($moduleList)[0];     } else {         $loader = array_values($moduleList)[0];     }      $namespaceArray[] = $loader;      if (array_key_exists($loader, $moduleList) && is_array($moduleList[$loader]) && !empty($moduleList[$loader])) {         return $this->getModuleNamespace($moduleList[$loader], $namespaceArray);     } else {         return $namespaceArray;     } }      /**      * Get the module properties' instances      * Recursive function      *      * @param array $propertyValue      * @param String $moduleName      * @return \stdClass      */     private function getModulePropertyInstance(Array $propertyValue, String $moduleName)     {         $propertyClass = new \stdClass();         foreach ($propertyValue as $moduleCaller => $moduleSubname) {             if (is_array($moduleSubname) === TRUE) {                 $propertyClass->$moduleCaller = $this->getModulePropertyInstance($moduleSubname, $moduleName . "\\" . $moduleCaller);             } else {                 $propertyClass->$moduleSubname = $this->getSubmodule($moduleName . "\\" . $moduleSubname);             }         }          return $propertyClass;     }      /**      * Get the parsed _$REQUEST array      *      * @return array      */     private function getRequest()     {         $request = array();         foreach ($_REQUEST as $key => $value) {             $key = htmlspecialchars($key, ENT_QUOTES | ENT_DISALLOWED | ENT_HTML5, "UTF-8");             $value = htmlspecialchars($value, ENT_QUOTES | ENT_DISALLOWED | ENT_HTML5, "UTF-8");              if (empty($value)) {                 $request[$key] = $key;             } else {                 $request[$key] = $value;             }         }          return $request;     }      /**      * Get submodule instance      *      * @param String $submoduleName      * @return object      */     private function getSubmodule(String $submoduleName)     {         $namespacePrefixList = array("\\Qobox\\", "\\Modules\\", "\\Output\\");         foreach ($namespacePrefixList as $namespacePrefix) {             $submoduleNamespace = $namespacePrefix . $submoduleName;              try {                 $submodule = new \ReflectionClass($submoduleNamespace);                 break;             } catch (\ReflectionException $e) {             }         }          $submoduleInstance = $submodule->newInstance();         $submoduleProperties = $submodule->getProperties(\ReflectionProperty::IS_PROTECTED);          foreach ($submoduleProperties as $submoduleProperty) {             $submoduleProperty->setAccessible(true);             if (empty($submoduleProperty->getValue($submoduleInstance))) {                 $submoduleName = $submoduleProperty->name;                 $submoduleProperty->setValue($submoduleInstance, $this->getSubmodule($submoduleName));             }             $submoduleProperty->setAccessible(false);         }         return $submoduleInstance;     }      /**      * Set requested module arguments      *      * @param $moduleMethod      * @return array      */     private function setMethodArguments($moduleMethod)     {         $argumentArray = array();         $moduleMethodArguments = $moduleMethod->getParameters();         foreach ($moduleMethodArguments as $Parameter) {             if (isset($request[$Parameter->name]) && !empty($request[$Parameter->name]) && $request[$Parameter->name] != $Parameter->name) {                 $argumentArray[$Parameter->name] = $request[$Parameter->name];             } else {                 if ($Parameter->isDefaultValueAvailable() === TRUE) {                     $argumentArray[$Parameter->name] = $Parameter->getDefaultValue();                 } else {                     $argumentArray[$Parameter->name] = "";                 }             }         }          return $argumentArray;     }      /**      * Set requested module properties      *      * @param $moduleInstance      */     private function setModuleProperties($moduleInstance)     {         $moduleProperties = $this->module->getProperties();         foreach ($moduleProperties as $property)         {             $moduleName = $property->name;             $property->setAccessible(true);             $propertyValue = $property->getValue($moduleInstance);              if (is_array($propertyValue) === TRUE)             {                 $propertyClass = $this->getModulePropertyInstance($propertyValue, $moduleName);                 $property->setValue($moduleInstance, $propertyClass);             } else             {                 $property->setValue($moduleInstance, $this->getSubmodule($moduleName . "\\" . $moduleName));             }         }     } } 

I intend to leave input sanitation as it is, putting GET and POST variables indistinguishably in one variable, only sanitizing each with htmlspecialchars($key, ENT_QUOTES | ENT_DISALLOWED | ENT_HTML5, "UTF-8"). FILES and SERVER variables are left as it is and are dealt with in another (kernel module) class.

The routing whitelist is put as mock data in the comment in the code. So,

  • Quering for index.php?Main will load class /Output/Main/Main.php
  • Quering for index.php?Bananaz will load class /Output/Main/Main.php (because Main is loaded by default)

Sure, you could just say that all public methods are, well, public.

Well, yes, only public functions are available, the required logic is in private and protected functions. I don't think users might mess something here up.

An extended example

Output/Example/Example.php

<?php  namespace Output\Main;  class Main {     private $Test;     private $Database;      public function runExample($hello)     {         echo $hello. ', ';         echo $this->Test->printWorld();         echo '<br><pre>';         print_r($this);     } } 

Modules/Test/Test.php

<?php  namespace Modules\Test;  class Test {     public function printWorld()     {         return 'World!';     } } 

Qobox/Database/Database.php

<?php  namespace Qobox\Database;  class Database {      private $Connection;     private $Statement;      public function __construct() {         include "Config/Database.php";          try {             $this->Connection = new \PDO($DatabaseConnect["DBEngine"].":host=".$DatabaseConnect["DBHost"].";dbname=".$DatabaseConnect["DBName"].";charset=utf8", $DatabaseConnect["DBUser"], $DatabaseConnect["DBPass"]);             $this->Connection->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);              $this->Connection->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);         } catch(\PDOException $e) {             echo "Connection to the database failed: ".$e->getMessage();         }     } ... } 

The output of calling index.php?Example&hello=Hello would be similar to this:

Hello, World Output\Main Object (     [Database:Output\Main:private] => Qobox\Database\Database Object         (             [Connection:Qobox\Database\Database:private] => PDO Object                 (                 )              [Statement:Qobox\Database\Database:private] =>          )      [Test:Output\Main:private] => Modules\Test\Test Object         (         ) ) 
     

Lista de respuestas


Relacionados problema

2  Paquetes 'TAG' y hazlos descubribles  ( Tag packages and make them discoverable ) 
Tenemos otro equipo que va a exponer los paquetes de clase para usar para escanear y recoger los detalles. Si deben agregar algunos paquetes nuevos o renombra...

12  Mapeo expandoObject a otro tipo de objeto  ( Mapping expandoobject to another object type ) 
Estoy trabajando en un método de ayuda que mapea las propiedades de un 9988776655544334 a un objeto suministrado por un usuario y se preguntaba si el código...

2  Lanzar una enumeración con descripciones en un diccionario  ( Casting an enumeration with descriptions into a dictionary ) 
La enumeración en cuestión se basa en int , por lo que la siguiente extensión devuelve un Dictionary<int, string> del valor y la descripción de Enum. ¿Ha...

5  Reflexión y proyecto EULER  ( Reflection and project euler ) 
He hecho un corredor de Project Euler para facilitar el funcionamiento de los diversos problemas. Nunca antes había usado la reflexión, y creo que he encontra...

18  Devolviendo los campos de clase groovy como un mapa  ( Returning groovy class fields as a map ) 
Quiero obtener un mapa de todos los campos en una clase (también conocido como objeto de valor) de una manera genérica. Los siguientes funcionan bien para mí:...

10  Implementación de Linq-To-Sage  ( Linq to sage implementation ) 
seguimiento de mi Última pregunta donde envié la API de SAITE con un 9988776665544334 < / Código> Interfaz, decidí empujar la abstracción un paso más allá,...

5  Método / Parámetro Tracer  ( Method parameter tracer ) 
Estoy escribiendo una clase que puede registrar la actividad de una solicitud durante el tiempo de ejecución. El plan es que la cadena 9988776665544330 se e...

8  Evaluar el mejor tipo común para adaptarse a ambos tipos  ( Evaluate the best common type to fit both of types ) 
Aquí hay un algoritmo para evaluar la mejor coincidencia System.Type para dos tipos en Heroarhy. Esta es una de las respuestas para esta pregunta de StackO...

3  Obtención de una lista de todos los campos en un objeto  ( Getting a list of all fields in an object ) 
Tengo el siguiente código que utilizo para generar una lista de todos los campos (públicos) en un objeto en una manera fácil (ISH) para leer. El problema con ...

4  Ruby Fibonacci (n) Cálculo recursivo optimizado con la reflexión  ( Ruby fibonaccin recursive computation optimized with reflection ) 
La idea es tomar el método recursivo de FibonAcci (N) conocido (y terriblemente malo): # recursively computate fibonacci(n) def fib(n) n <= 2 ? 1 : fib(n...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos