add comments to Libs.
This commit is contained in:
		| @@ -1,4 +1,16 @@ | ||||
| <?php | ||||
| /* | ||||
| * DuckBrain - Microframework | ||||
| *  | ||||
| * Clase diseñada para crear y devolver una única instancia mysqli. | ||||
| * Depende de manera forzada de que estén definidas las constantes: | ||||
| * dbhost, dbname, dbpass y dbuser | ||||
| * | ||||
| * Autor: KJ | ||||
| * Web: https://kj2.me | ||||
| * Licencia: MIT | ||||
| */ | ||||
|  | ||||
| namespace Libs; | ||||
|  | ||||
| class Database { | ||||
| @@ -10,7 +22,8 @@ class Database { | ||||
|     if (!isset(self::$db)) { | ||||
|       self::$db = new \mysqli(dbhost, dbuser, dbpass, dbname); | ||||
|       if (self::$db->connect_errno) { | ||||
|         exit('No se ha podido conectar a la base de datos.'); | ||||
|         echo '<style>body{white-space: pre-line;}</style>'; | ||||
|         throw new \Exception('No se ha podido conectar a la base de datos.'); | ||||
|       } | ||||
|     } | ||||
|     return self::$db; | ||||
|   | ||||
| @@ -1,4 +1,14 @@ | ||||
| <?php | ||||
| /* | ||||
| * DuckBrain - Microframework | ||||
| *  | ||||
| * Modelo ORM para objetos que hagan uso de una base de datos MySQL. | ||||
| * Depende de que exista Libs\Database para poder funcionar. | ||||
| * | ||||
| * Autor: KJ | ||||
| * Web: https://kj2.me | ||||
| * Licencia: MIT | ||||
| */ | ||||
|  | ||||
| namespace Libs; | ||||
|  | ||||
| @@ -26,7 +36,12 @@ class ModelMySQL { | ||||
|                     'groupBy'=>'', | ||||
|                     'limit' => '', | ||||
|                    ]; | ||||
|                     | ||||
|  | ||||
|   /* | ||||
|   * Sirve para obtener la instancia de la base de datos  | ||||
|   * | ||||
|   * @return mysqli | ||||
|   */ | ||||
|   private static function db(){ | ||||
|     if (is_null(self::$db)) | ||||
|       self::$db = Database::getConnection(); | ||||
| @@ -34,20 +49,38 @@ class ModelMySQL { | ||||
|     return self::$db; | ||||
|   } | ||||
|    | ||||
|   /* | ||||
|   * Ejecuta una sentencia SQL en la base de datos. | ||||
|   * | ||||
|   * @param string $query | ||||
|   *   Contiene la sentencia SQL que se desea ejecutar | ||||
|   * | ||||
|   * @throws \Exception | ||||
|   *   En caso de que la sentencia SQL falle, devolverá un error en pantalla. | ||||
|   * | ||||
|   * @return mysqli_result | ||||
|   *   Contiene el resultado de la llamada SQL. | ||||
|   */ | ||||
|   private static function query($query){ | ||||
|     $db = self::db(); | ||||
|      | ||||
|     $result = $db->query($query); | ||||
|     if ($db->errno){ | ||||
|       	echo 'Fallo al consultar la base de datos.<br> | ||||
|       	      Errno: ' . addslashes ($db->errno).'<br> | ||||
|       	      Error: ' . addslashes ($db->error).'<br>'.$query; | ||||
|       exit(); | ||||
|         echo '<style>body{white-space: pre-line;}</style>'; | ||||
|       	throw new \Exception( | ||||
|   	      "\nFallo al consultar la base de datos\n" . | ||||
|   	      "Errno: $db->errno\n" . | ||||
|   	      "Error: $db->error\n" . | ||||
|   	      "Query: $query\n" | ||||
|   	    ); | ||||
|     } | ||||
|      | ||||
|     return $result; | ||||
|   } | ||||
|    | ||||
|   /* | ||||
|   * Reinicia la configuración de la sentencia SQL. | ||||
|   */ | ||||
|   private static function resetQuery(){ | ||||
|     self::$querySelect = [ | ||||
|                     'select' => '*', | ||||
| @@ -62,6 +95,13 @@ class ModelMySQL { | ||||
|                    ]; | ||||
|   } | ||||
|    | ||||
|   /* | ||||
|   * Construye la sentencia SQL a partir self::$querySelect y una vez | ||||
|   * construída, llama a resetQuery. | ||||
|   * | ||||
|   * @return string | ||||
|   *   Contiene la sentencia SQL. | ||||
|   */ | ||||
|   private static function buildQuery(){ | ||||
|     $sql = 'SELECT '.self::$querySelect['select'].' FROM '.self::table(); | ||||
|      | ||||
| @@ -98,7 +138,16 @@ class ModelMySQL { | ||||
|     return $sql; | ||||
|   } | ||||
|    | ||||
|    | ||||
|   /* | ||||
|   * Crea una instancia del objeto actual a partir de un arreglo. | ||||
|   * | ||||
|   * @param mixed $elem | ||||
|   *   Puede recibir un arreglo o un objeto que contiene los valores | ||||
|   *   que tendrán sus atributos. | ||||
|   * | ||||
|   * @return ModelMySQL | ||||
|   *   Retorna un objeto de la clase actual. | ||||
|   */ | ||||
|   public function getInstance($elem = []){ | ||||
|     $class = get_called_class(); | ||||
|     $instace = new $class; | ||||
| @@ -110,7 +159,10 @@ class ModelMySQL { | ||||
|     return $instace; | ||||
|   } | ||||
|  | ||||
|  | ||||
|   /* | ||||
|   * @return array | ||||
|   *   Contiene los atributos indexados del objeto actual. | ||||
|   */ | ||||
|   private function getVars(){ // Source: https://stackoverflow.com/questions/10009015/show-all-public-attributes-name-and-value-of-an-object | ||||
|     $get_vars_proxy = create_function('$obj', 'return get_object_vars($obj);'); | ||||
|     $result = $get_vars_proxy($this); | ||||
| @@ -125,19 +177,30 @@ class ModelMySQL { | ||||
|     return $result; | ||||
|   } | ||||
|    | ||||
|    | ||||
|   /* | ||||
|   * @return string | ||||
|   *   Devuelve el nombre de la clase actual | ||||
|   */ | ||||
|   public static function className(){ | ||||
|     return strtolower(substr(strrchr(get_called_class(), '\\'), 1)); | ||||
|   } | ||||
|    | ||||
|    | ||||
|   /* | ||||
|   * Construye (a partir del nombre de la clase y el sufijo en self::$tableSufix)  | ||||
|   * y/o develve el nombre de la tabla de la BD en la que se alojará o | ||||
|   * se aloja el objeto actual. | ||||
|   *  | ||||
|   * @return string | ||||
|   */ | ||||
|   private static function table(){ | ||||
|     if (isset(self::$table)) | ||||
|       return self::$table; | ||||
|     return self::className().self::$tableSufix; | ||||
|   } | ||||
|  | ||||
|  | ||||
|   /* | ||||
|   * Actualiza los valores en la BD con los valores del objeto actual | ||||
|   */ | ||||
|   private function update(){ | ||||
|     $atts = $this->getVars(); | ||||
|      | ||||
| @@ -153,7 +216,10 @@ class ModelMySQL { | ||||
|     self::query($sql); | ||||
|   } | ||||
|    | ||||
|    | ||||
|   /* | ||||
|   * Inserta una nueva fila en la base de datos a partir del | ||||
|   * objeto actual. | ||||
|   */ | ||||
|   private function add(){ | ||||
|     $db = self::db(); | ||||
|     $atts = $this->getVars(); | ||||
| @@ -171,7 +237,10 @@ class ModelMySQL { | ||||
|     $this->$pk = $db->insert_id; | ||||
|   } | ||||
|    | ||||
|    | ||||
|   /* | ||||
|   * Revisa si el objeto a guardar es nuevo o no y según el resultado | ||||
|   * llama a update para actualizar o add para insertar una nueva fila. | ||||
|   */ | ||||
|   public function save(){ | ||||
|     $pk = $this->primaryKey; | ||||
|     if (isset($this->$pk)) | ||||
| @@ -180,7 +249,9 @@ class ModelMySQL { | ||||
|       $this->add(); | ||||
|   } | ||||
|    | ||||
|    | ||||
|   /* | ||||
|   * Elimina el objeto actual de la base de datos. | ||||
|   */ | ||||
|   public function delete(){ | ||||
|     $atts = $this->getVars(); | ||||
|      | ||||
| @@ -196,12 +267,17 @@ class ModelMySQL { | ||||
|     self::query($sql); | ||||
|   } | ||||
|    | ||||
|    | ||||
|   public static function select($value){ | ||||
|   /* | ||||
|   * Define SELECT en la sentencia SQL. | ||||
|   * | ||||
|   * @param array $columns | ||||
|   *   Columnas que se selecionarán en la consulta SQL. | ||||
|   */ | ||||
|   public static function select($columns){ | ||||
|     $db = self::db(); | ||||
|     $select = []; | ||||
|     foreach($value as $elem){ | ||||
|       $select[] = $db->real_escape_string($elem); | ||||
|     foreach($columns as $column){ | ||||
|       $select[] = $db->real_escape_string($column); | ||||
|     } | ||||
|      | ||||
|     self::$querySelect['select'] = join(', ', $select); | ||||
| @@ -210,11 +286,21 @@ class ModelMySQL { | ||||
|   } | ||||
|    | ||||
|   /* | ||||
|   * Sintaxis permitidas:  | ||||
|   *  - Class::where(columna, operador, valor) | ||||
|   *  - Class::where(columna, valor)  // Operador por defecto "=" | ||||
|   * Define el WHERE en la sentencia SQL. | ||||
|   * | ||||
|   * @param string $column | ||||
|   *   La columna a comparar. | ||||
|   * | ||||
|   * @param string $operador | ||||
|   *   El operador o el valor a comparar en la columna en caso de que eloperador sea "=". | ||||
|   * | ||||
|   * @param string $value | ||||
|   *   El valor el valor a comparar en la columna. | ||||
|   * | ||||
|   * Sintaxis posibles:  | ||||
|   *  - self::where(columna, operador, valor) | ||||
|   *  - self::where(columna, valor)  // Operador por defecto "=" | ||||
|   */ | ||||
|    | ||||
|   public static function where($column, $operator, $value=null){ | ||||
|     if (is_null($value)){ | ||||
|       $value = $operator; | ||||
| @@ -228,7 +314,18 @@ class ModelMySQL { | ||||
|     return new static(); | ||||
|   } | ||||
|    | ||||
|    | ||||
|   /* | ||||
|   * Define WHERE usando IN en la sentencia SQL. | ||||
|   * | ||||
|   * @param string $column | ||||
|   *   La columna a comparar. | ||||
|   * | ||||
|   * @param array $arr | ||||
|   *   Arreglo con todos los valores a comparar con la columna. | ||||
|   * | ||||
|   * @param boolean $in | ||||
|   *   Define si se usará IN o NOT IN en la sentencia SQL. | ||||
|   */ | ||||
|   public static function where_in($column,$arr, $in = true){ | ||||
|     foreach($arr as $index => $value){ | ||||
|       $arr[$index] = self::db()->real_escape_string($value); | ||||
| @@ -242,6 +339,25 @@ class ModelMySQL { | ||||
|     return new static(); | ||||
|   } | ||||
|    | ||||
|   /* | ||||
|   * Define LEFT JOIN en la sentencia SQL. | ||||
|   * | ||||
|   * @param string $table | ||||
|   *   Tabla que se va a juntar a la del objeto actual. | ||||
|   * | ||||
|   * @param string $columnA | ||||
|   *   Columna a comparar para hacer el join. | ||||
|   * | ||||
|   * @param string $operador | ||||
|   *   Operador o columna a comparar para hacer el join en caso de que el operador sea "=". | ||||
|   * | ||||
|   * @param string $columnB | ||||
|   *   Columna a comparar para hacer el join. | ||||
|   * | ||||
|   * Sintaxis posibles:  | ||||
|   *  - self::leftJoin(tabla,columnaA, operador, columnB) | ||||
|   *  - self::leftJoin(tabla,columnaA, columnB) // Operador por defecto "=" | ||||
|   */ | ||||
|   public static function leftJoin($table, $columnA, $operator, $columnB = null){ | ||||
|     if (is_null($columnB)){ | ||||
|       $columnB = $operator; | ||||
| @@ -258,6 +374,25 @@ class ModelMySQL { | ||||
|     return new static(); | ||||
|   } | ||||
|    | ||||
|   /* | ||||
|   * Define RIGHT JOIN en la sentencia SQL. | ||||
|   * | ||||
|   * @param string $table | ||||
|   *   Tabla que se va a juntar a la del objeto actual. | ||||
|   * | ||||
|   * @param string $columnA | ||||
|   *   Columna a comparar para hacer el join. | ||||
|   * | ||||
|   * @param string $operador | ||||
|   *   Operador o columna a comparar para hacer el join en caso de que el operador sea "=". | ||||
|   * | ||||
|   * @param string $columnB | ||||
|   *   Columna a comparar para hacer el join. | ||||
|   * | ||||
|   * Sintaxis posibles:  | ||||
|   *  - self::rightJoin(tabla,columnaA, operador, columnB) | ||||
|   *  - self::rightJoin(tabla,columnaA, columnB) // Operador por defecto "=" | ||||
|   */ | ||||
|   public static function rightJoin($table, $columnA, $operator, $columnB = null){ | ||||
|     if (is_null($columnB)){ | ||||
|       $columnB = $operator; | ||||
| @@ -274,6 +409,23 @@ class ModelMySQL { | ||||
|     return new static(); | ||||
|   } | ||||
|    | ||||
|   /* | ||||
|   * Define AND en la sentencia SQL (se puede anidar). | ||||
|   * | ||||
|   * @param string $column | ||||
|   *   La columna a comparar. | ||||
|   * | ||||
|   * @param string $operador | ||||
|   *   El operador o el valor a comparar en la columna en caso de que eloperador sea "=". | ||||
|   * | ||||
|   * @param string $value | ||||
|   *   El valor el valor a comparar en la columna. | ||||
|   * | ||||
|   * Sintaxis posibles:  | ||||
|   *  - self::and(columna, operador, valor) | ||||
|   *  - self::and(columna, valor)  // Operador por defecto "=" | ||||
|   *  - self::and(columna, valor)->and(columna, valor)->and(columna, valor) // anidado | ||||
|   */ | ||||
|   public static function and($column, $operator, $value=null){ | ||||
|     if (is_null($value)){ | ||||
|       $value = $operator; | ||||
| @@ -287,7 +439,23 @@ class ModelMySQL { | ||||
|     return new static(); | ||||
|   } | ||||
|    | ||||
|    | ||||
|   /* | ||||
|   * Define OR en la sentencia SQL (se puede anidar). | ||||
|   * | ||||
|   * @param string $column | ||||
|   *   La columna a comparar. | ||||
|   * | ||||
|   * @param string $operador | ||||
|   *   El operador o el valor a comparar en la columna en caso de que eloperador sea "=". | ||||
|   * | ||||
|   * @param string $value | ||||
|   *   El valor el valor a comparar en la columna. | ||||
|   * | ||||
|   * Sintaxis posibles:  | ||||
|   *  - self::or(columna, operador, valor) | ||||
|   *  - self::or(columna, valor)  // Operador por defecto "=" | ||||
|   *  - self::or(columna, valor)->or(columna, valor)->or(columna, valor) // anidado | ||||
|   */ | ||||
|   public static function or($column, $operator, $value=null){ | ||||
|     if (is_null($value)){ | ||||
|       $value = $operator; | ||||
| @@ -301,6 +469,12 @@ class ModelMySQL { | ||||
|     return new static(); | ||||
|   } | ||||
|    | ||||
|   /* | ||||
|   * Define GROUP BY en la sentencia SQL | ||||
|   * | ||||
|   * @param array $arr | ||||
|   *   Columnas por las que se agrupará. | ||||
|   */ | ||||
|   public static function groupBy($arr){ | ||||
|     self::$querySelect['groupBy'] = join(', ', $arr); | ||||
|     return new static(); | ||||
| @@ -318,7 +492,16 @@ class ModelMySQL { | ||||
|     return new static(); | ||||
|   } | ||||
|    | ||||
|    | ||||
|   /* | ||||
|   * Define ORDER BY en la sentencia SQL | ||||
|   * | ||||
|   * @param string $value | ||||
|   *   Columna por la que se ordenará. | ||||
|   *  | ||||
|   * @param string $order | ||||
|   *   Define si el orden será de manera ascendente (ASC),  | ||||
|   *   descendente (DESC) o aleatorio (RAND). | ||||
|   */ | ||||
|   public static function orderBy($value, $order = 'ASC'){ | ||||
|     if ($value == "RAND"){ | ||||
|       self::$querySelect['orderBy'] = 'RAND()'; | ||||
| @@ -335,7 +518,11 @@ class ModelMySQL { | ||||
|     return new static(); | ||||
|   } | ||||
|    | ||||
|    | ||||
|   /* | ||||
|   * Retorna la cantidad de filas que hay en un query. | ||||
|   * | ||||
|   * @return int | ||||
|   */ | ||||
|   public static function count(){ | ||||
|     self::$querySelect['select'] = 'count(*) as quantity'; | ||||
|     $sql = self::buildQuery(); | ||||
| @@ -343,18 +530,29 @@ class ModelMySQL { | ||||
|     return $result['quantity']; | ||||
|   } | ||||
|    | ||||
|    | ||||
|   /* | ||||
|   * Obtiene una instancia según su id. | ||||
|   * | ||||
|   * @param int $id | ||||
|   * @return ModelMySQL | ||||
|   */ | ||||
|   public static function getById($id){ | ||||
|     return self::where('id', $id)->getFirst(); | ||||
|   } | ||||
|    | ||||
|    | ||||
|   /* | ||||
|   * Realiza una búsqueda en la tabla de la instancia actual. | ||||
|   * | ||||
|   * @param string $search | ||||
|   *   Contenido a buscar. | ||||
|   * | ||||
|   * @param array $in | ||||
|   *   Columnas en las que se va a buscar (null para buscar en todas) | ||||
|   */ | ||||
|   public static function search($search, $in = null){ | ||||
|     $className = get_called_class(); | ||||
|     $objAtts = array_keys((new $className())->getVars()); | ||||
|      | ||||
|     if ($in == null){ | ||||
|       $in = $objAtts; | ||||
|       $className = get_called_class(); | ||||
|       $objAtts = array_keys((new $className())->getVars()); | ||||
|     } | ||||
|      | ||||
|     $db = self::db(); | ||||
| @@ -376,7 +574,11 @@ class ModelMySQL { | ||||
|     return new static(); | ||||
|   } | ||||
|    | ||||
|    | ||||
|   /* | ||||
|   * Obtener los resultados de la consulta SQL. | ||||
|   * | ||||
|   * @return ModelMySQL[] | ||||
|   */ | ||||
|   public static function get(){ // Devuelve array vacío si no encuentra nada | ||||
|     $sql = self::buildQuery(); | ||||
|     $result = self::query($sql); | ||||
| @@ -390,14 +592,23 @@ class ModelMySQL { | ||||
|     return $instaces; | ||||
|   } | ||||
|    | ||||
|    | ||||
|   /* | ||||
|   * El primer elemento de la consulta SQL. | ||||
|   * | ||||
|   * @return mixed | ||||
|   *   Puede retornar un objeto ModelMySQL o null. | ||||
|   */ | ||||
|   public static function getFirst(){ // Devuelve null si no encuentra nada | ||||
|     self::limit(1); | ||||
|     $instaces = self::get(); | ||||
|     return empty($instaces) ? null : $instaces[0]; | ||||
|   } | ||||
|  | ||||
|  | ||||
|   /* | ||||
|   * Obtener todos los elementos del la tabla de la instancia actual. | ||||
|   * | ||||
|   * @return ModelMySQL[] | ||||
|   */ | ||||
|   public static function all(){ | ||||
|     $sql = 'SELECT * FROM '.self::table(); | ||||
|      | ||||
|   | ||||
| @@ -1,4 +1,20 @@ | ||||
| <?php | ||||
| /* | ||||
| * DuckBrain - Microframework | ||||
| * | ||||
| * Params (nombre temporal, a falta de uno mejor), sirve para  | ||||
| * crear un objeto con la característica especial de que al | ||||
| * intentar acceder a un atributo que no está definido devolerá  | ||||
| * nulo en lugar de generar un error php notice que indica que | ||||
| * se está intentando acceder a un valor no definido. | ||||
| * | ||||
| * El constructor recibe un objeto o arreglo con los valores que | ||||
| * sí estarán definidos. | ||||
| * | ||||
| * Autor: KJ | ||||
| * Web: https://kj2.me | ||||
| * Licencia: MIT | ||||
| */ | ||||
|  | ||||
| namespace Libs; | ||||
|  | ||||
| @@ -15,7 +31,8 @@ class Params { | ||||
|     } | ||||
|      | ||||
|     public function __get($index){ | ||||
|         return (isset($this->data[$index]) && $this->data[$index] != '') ? $this->data[$index] : null; | ||||
|         return (isset($this->data[$index]) && $this->data[$index] != '') | ||||
|                ? $this->data[$index] : null; | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,19 +1,44 @@ | ||||
| <?php | ||||
| /* | ||||
| * DuckBrain - Microframework | ||||
| * | ||||
| * Librería de Enrrutador.  | ||||
| * Depende de manera forzada de que la constante ROOT_DIR esté definida | ||||
| * y de manera optativa de que la constante SITE_URL lo esté también. | ||||
| * | ||||
| * Autor: KJ | ||||
| * Web: https://kj2.me | ||||
| * Licencia: MIT | ||||
| */ | ||||
|  | ||||
| namespace Libs; | ||||
|  | ||||
| use Libs\Request; | ||||
|  | ||||
| class Router{ | ||||
| class Router { | ||||
|   private static $get = []; | ||||
|   private static $post = []; | ||||
|   private static $put = []; | ||||
|   private static $delete = []; | ||||
|   private static $last; | ||||
|    | ||||
|   private function __construct(){} | ||||
|   private function __construct() {} | ||||
|    | ||||
|   private static function parse($path, $callback){ | ||||
|   /* | ||||
|   * Parsea para deectar las pseudovariables (ej: {variable}) | ||||
|   * | ||||
|   * @param string $path | ||||
|   *   URI con pseudovariables | ||||
|   * | ||||
|   * @param function $callback | ||||
|   *   Función en formato Clase::Método que será llamada cuando la url y el método coincidan | ||||
|   * | ||||
|   * @return array | ||||
|   *   Arreglo con 2 índices: | ||||
|   *     path        - Contiene la URI con la pseudovariables reeplazadas por expresiones regulares | ||||
|   *     callback    - Contiene el callback en formato Namespace\Clase::Método | ||||
|   */ | ||||
|   private static function parse($path, $callback) { | ||||
|     $path = preg_quote($path, '/'); | ||||
|     $path = preg_replace( | ||||
|             ['/\\\{[\w-]+\\\}/s'], | ||||
| @@ -29,15 +54,38 @@ class Router{ | ||||
|     ]; | ||||
|   } | ||||
|    | ||||
|   public static function baseURI(){ | ||||
|    | ||||
|   /* | ||||
|   * Devuelve el path o URI base sobre la que trabajará el router. | ||||
|   * | ||||
|   * Ej: Si la url del sistema está en "https://ejemplo.com/duckbrain" | ||||
|   *     entonces la URI base sería "/duckbrain"  | ||||
|   */ | ||||
|   public static function baseURI() { | ||||
|     if (defined('SITE_URL')) | ||||
|       return parse_url(SITE_URL, PHP_URL_PATH); | ||||
|     return str_replace($_SERVER['DOCUMENT_ROOT'],'/', ROOT_DIR); | ||||
|   } | ||||
|    | ||||
|   public static function redirect($uri){ | ||||
|   /* | ||||
|   * Redirije a una ruta relativa interna. | ||||
|   * | ||||
|   * @param string $uri | ||||
|   *   La URI relativa a la URI base. | ||||
|   * | ||||
|   * Ej: Si nuesto sistema está en "https://ejemplo.com/duckbrain" | ||||
|   *     llamamos a Router::redirect('/docs'), entonces seremos | ||||
|   *     redirigidos a "https://ejemplo.com/duckbrain/docs". | ||||
|   */ | ||||
|   public static function redirect($uri) { | ||||
|     header('Location: '.self::baseURI().substr($uri,1)); | ||||
|   } | ||||
|    | ||||
|   public static function middleware($middleware){ // Solo soporta un middleware a la vez | ||||
|   /* | ||||
|   * Añade un middleware a la última ruta usada. | ||||
|   * Solo se puede usar un middleware a la vez. | ||||
|   */ | ||||
|   public static function middleware($middleware){ | ||||
|     if (!isset(self::$last)) return; | ||||
|      | ||||
|     $method = self::$last[0]; | ||||
| @@ -45,14 +93,16 @@ class Router{ | ||||
|      | ||||
|     self::$$method[$index]['middleware'] = 'Middlewares\\'.$middleware; | ||||
|   } | ||||
|  | ||||
|   public static function get($path, $callback){ | ||||
|     self::$get[] = self::parse($path, $callback); | ||||
|     self::$last = ['get', count(self::$get)-1]; | ||||
|     return new static(); | ||||
|   } | ||||
|    | ||||
|   private static function params(){ | ||||
|   /* | ||||
|   * @return object | ||||
|   *   Devuelve un objeto que contiene los atributos: | ||||
|   *     post  - Donde se encuentran los valores enviados por $_POST | ||||
|   *     get   - Donde se encuentran los valores enviados por $_GET | ||||
|   *     json  - Donde se encuentran los valores JSON enviados en el body | ||||
|   * | ||||
|   */ | ||||
|   private static function params() { | ||||
|     $args             = (object) ''; | ||||
|     $args->get        = new Params($_GET); | ||||
|     $args->post       = new Params($_POST); | ||||
| @@ -60,37 +110,120 @@ class Router{ | ||||
|     return $args; | ||||
|   } | ||||
|    | ||||
|   private static function get_json(){ | ||||
|   /* | ||||
|   * @return object | ||||
|   *   Devuelve un objeto con los datos recibidos en JSON | ||||
|   */ | ||||
|   private static function get_json() { | ||||
|     $contentType = isset($_SERVER["CONTENT_TYPE"]) ? trim($_SERVER["CONTENT_TYPE"]) : ''; | ||||
|     if ($contentType === "application/json"){ | ||||
|     if ($contentType === "application/json") { | ||||
|       return json_decode(trim(file_get_contents("php://input"))); | ||||
|     } | ||||
|     return (object) ''; | ||||
|   } | ||||
|    | ||||
|   public static function post($path, $callback){ | ||||
|   /* | ||||
|   * Define los routers para el método GET. | ||||
|   * | ||||
|   * @param string $path | ||||
|   *   URI con pseudovariables | ||||
|   * | ||||
|   * @param function $callback | ||||
|   *   Función en formato Clase::Método que será llamada cuando la url y el método coincidan | ||||
|   * | ||||
|   * @return static | ||||
|   *   Devuelve un enlace estático | ||||
|   */ | ||||
|   public static function get($path, $callback) { | ||||
|     self::$get[] = self::parse($path, $callback); | ||||
|     self::$last = ['get', count(self::$get)-1]; | ||||
|     return new static(); | ||||
|   } | ||||
|    | ||||
|   /* | ||||
|   * Define los routers para el método POST. | ||||
|   * | ||||
|   * @param string $path | ||||
|   *   URI con pseudovariables | ||||
|   * | ||||
|   * @param function $callback | ||||
|   *   Función en formato Clase::Método que será llamada cuando la url y el método coincidan | ||||
|   * | ||||
|   * @return static | ||||
|   *   Devuelve un enlace estático | ||||
|   */ | ||||
|   public static function post($path, $callback) { | ||||
|     self::$post[] = self::parse($path, $callback); | ||||
|     self::$last   = ['post', count(self::$post)-1]; | ||||
|     return new static(); | ||||
|   } | ||||
|    | ||||
|   public static function put($path, $callback){ | ||||
|   public static function put($path, $callback) { | ||||
|     self::$put[]  = self::parse($path, $callback); | ||||
|     self::$last   = ['put', count(self::$put)-1]; | ||||
|     return new static(); | ||||
|   } | ||||
|    | ||||
|   public static function delete($path, $callback){ | ||||
|   /* | ||||
|   * Define los routers para el método DELETE. | ||||
|   * | ||||
|   * @param string $path | ||||
|   *   URI con pseudovariables | ||||
|   * | ||||
|   * @param function $callback | ||||
|   *   Función en formato Clase::Método que será llamada cuando la url y el método coincidan | ||||
|   * | ||||
|   * @return static | ||||
|   *   Devuelve un enlace estático | ||||
|   */ | ||||
|   public static function delete($path, $callback) { | ||||
|     self::$delete[] = self::parse($path, $callback); | ||||
|     self::$last     = ['delete', count(self::$put)-1]; | ||||
|     return new static(); | ||||
|   } | ||||
|    | ||||
|   public static function apply(){ | ||||
|   /* | ||||
|   * Aplica los routers. | ||||
|   *  | ||||
|   * Este método ha de ser llamado luego de que todos los routers hayan sido configurados. | ||||
|   * | ||||
|   * En caso que la URI actual coincida con un router configurado, | ||||
|   * pueden suecedor los siguientes casos: | ||||
|   * | ||||
|   * 1. Tiene pseudovariables por URI | ||||
|   * | ||||
|   *   1.1. Tiene middleware, por lo que se llama al middleware enviándole los datos | ||||
|   *        en el siguiente orden: | ||||
|   *           - Función callback del router | ||||
|   *           - Objeto que contiene $_POST, $_GET y el JSON recibido | ||||
|   *           - Todas las pseudovariables (en el mismo orden que están escritas) | ||||
|   * | ||||
|   *   1.1. No tiene middleware, por lo que se llama a la función callback del router | ||||
|   *        enviándole los datos en el siguiente orden: | ||||
|   *           - Todas las pseudovariables (en el mismo orden que están escritas) | ||||
|   *           - Objeto que contiene $_POST, $_GET y el JSON recibido | ||||
|   *    | ||||
|   * 2. No tiene pseudovariables por URI | ||||
|   * | ||||
|   *   2.1. Tiene middleware, por lo que se llama al middleware enviándole los datos | ||||
|   *        En el siguiente orden: | ||||
|   *           - Función callback del router | ||||
|   *           - Todas las pseudovariables (en el mismo orden que están escritas) | ||||
|   * | ||||
|   *   2.2. No tiene middleware, por lo que se llama a la función callback del router | ||||
|   *        enviándole solo ún parámetro: | ||||
|   *           - Objeto que contiene $_POST, $_GET y el JSON recibido | ||||
|   * | ||||
|   * Nota: Gracias a que se usa call_user_func_array, los callbacks no es necesario que reciban | ||||
|   *       la misma cantidad de parámetros que se les envía. De ese modo, pueden recibir solo | ||||
|   *       los parámetros que van a utilizar, con el detalle de que siempre se respeta el orden | ||||
|   *       especificado anteriormente a la hora de recibirlos. | ||||
|   */ | ||||
|   public static function apply() { | ||||
|     $uri =  preg_replace('/'.preg_quote(self::baseURI(), '/').'/', | ||||
|             '/', strtok($_SERVER['REQUEST_URI'], '?'), 1); | ||||
|     $routers = []; | ||||
|     switch ($_SERVER['REQUEST_METHOD']){ | ||||
|     switch ($_SERVER['REQUEST_METHOD']){ // Según el método selecciona un arreglo de routers configurados | ||||
|       case 'POST': | ||||
|         $routers = self::$post; | ||||
|         break; | ||||
| @@ -105,35 +238,35 @@ class Router{ | ||||
|         break; | ||||
|     } | ||||
|      | ||||
|     foreach ($routers as $router){ | ||||
|     foreach ($routers as $router) { // revisa todos los routers para ver si coinciden con la URI actual | ||||
|       if (preg_match_all('/^'.$router['path'].'\/?$/si',$uri, $matches)){ | ||||
|         unset($matches[0]); | ||||
|         $args = self::params(); | ||||
|          | ||||
|         if (isset($matches[1])){ | ||||
|         if (isset($matches[1])) { // Caso 1 - Con pseudovariables por URI | ||||
|           $params = []; | ||||
|           foreach ($matches as $match){ | ||||
|           foreach ($matches as $match) { | ||||
|             if (!empty($match)) | ||||
|               $params[] = "$match[0]"; | ||||
|           } | ||||
|            | ||||
|           if (isset($router['middleware'])){ | ||||
|           if (isset($router['middleware'])) { // Caso 1.1 - Con middleware | ||||
|             $middleware = explode('::',$router['middleware']); | ||||
|             $data = call_user_func_array($middleware, [$router['callback'], $args, $params]); | ||||
|           } else { | ||||
|           } else { // Caso 1.2 - Sin middleware | ||||
|             $params[] = $args; | ||||
|             $data = call_user_func_array($router['callback'], $params);  | ||||
|           } | ||||
|         }else{ | ||||
|           if (isset($router['middleware'])){ | ||||
|         } else { // Caso 2 - Sin Pseudo variables por URI | ||||
|           if (isset($router['middleware'])) { // Caso 2.1 - Con middleware | ||||
|             $middleware = explode('::',$router['middleware']); | ||||
|             $data = call_user_func_array($middleware, [$router['callback'], $args]); | ||||
|           } else { | ||||
|           } else { // Caso 2.2 - Sin middleware | ||||
|             $data = call_user_func_array($router['callback'], [$args]); | ||||
|           } | ||||
|         } | ||||
|          | ||||
|         if (isset($data)){ | ||||
|         if (isset($data)) { | ||||
|           header('Content-Type: application/json'); | ||||
|           print(json_encode($data)); | ||||
|         } | ||||
| @@ -141,7 +274,7 @@ class Router{ | ||||
|         return; | ||||
|       } | ||||
|     } | ||||
|     header("HTTP/1.0 404 Not Found"); | ||||
|     header("HTTP/1.0 404 Not Found"); // Si no hay router que coincida, se devuelve error 404 | ||||
|     echo '<h2 style="text-align: center;margin: 25px 0px;">Error 404 - Página no encontrada</h2>'; | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -1,13 +1,32 @@ | ||||
| <?php | ||||
| /* | ||||
| * DuckBrain - Microframework | ||||
| *  | ||||
| * Manejador de vistas simplificado. | ||||
| * | ||||
| * Autor: KJ | ||||
| * Web: https://kj2.me | ||||
| * Licencia: MIT | ||||
| */ | ||||
|  | ||||
| namespace Libs; | ||||
|  | ||||
| defined('ROOT_DIR') || die('8)'); | ||||
|  | ||||
| class View { | ||||
|   public static function render($viewName, $params = array()){ | ||||
|  | ||||
|   /* | ||||
|   * Función que "renderizar" las vistas | ||||
|   * | ||||
|   * @param string $viewName | ||||
|   *   Ruta relativa y el nommbre sin extensión del archivo ubicado en src/Views | ||||
|   * | ||||
|   * @param array $params | ||||
|   *   Arreglo que podrá ser usado en la vista mediante $view ($param['index'] se usaría así: $view->index) | ||||
|   * | ||||
|   */ | ||||
|   public static function render($viewName, $params = []) { | ||||
|     $view = new Params($params); | ||||
|     unset($params); | ||||
|     include(ROOT_DIR.'src/Views/'.$viewName.'.php'); | ||||
|     include(ROOT_DIR.'/src/Views/'.$viewName.'.php'); | ||||
|   } | ||||
| } | ||||
| ?> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user