{"id":5355,"date":"2026-01-19T17:24:57","date_gmt":"2026-01-19T16:24:57","guid":{"rendered":"https:\/\/sutilweb.eu\/?page_id=5355"},"modified":"2026-01-19T17:24:58","modified_gmt":"2026-01-19T16:24:58","slug":"49-crear-un-simple-enrutador-con-php","status":"publish","type":"page","link":"https:\/\/sutilweb.eu\/index.php\/lenguajes\/php\/php-practico\/49-crear-un-simple-enrutador-con-php\/","title":{"rendered":"49. Crear un simple enrutador con PHP"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">En el cap\u00edtulo pasado hab\u00edamos logrado que nuestra aplicaci\u00f3n tuviera un \u00fanico <strong>punto de acceso<\/strong>, es decir, a que no importa lo que coloquemos luego de la URL principal, siempre se abrir\u00e1 el mismo archivo, el archivo <em>index.php<\/em>. incluido dentro de la carpeta <em>public<\/em>. Nuestro archivo <strong>index.php<\/strong> es un documento HTML que tiene una etiqueta <strong><em>&lt;h1>&lt;\/h1><\/em><\/strong> cuyo valor es Inicio punto de acceso.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><em>index.php<\/em><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;!DOCTYPE html>\n&lt;html lang=\"en\">\n&lt;head>\n  &lt;meta charset=\"UTF-8\">\n  &lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n  &lt;title>Document&lt;\/title>\n&lt;\/head>\n&lt;body>\n  &lt;h1>\u00danico punto de acceso&lt;\/h1>\n&lt;\/body>\n&lt;\/html><\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Lo siguiente que debemos hacer es que desde este archivo analizar la URL desde la cual estamos haciendo la petici\u00f3n, y dependiendo del valor de dicha URL deber\u00edamos llamar a uno u otro controlador. Este proceso en el cual analizamos la URL y dependiendo de dicha URL llamamos a uno u otro controlador se le conoce como <strong>enrutamiento<\/strong>, y cabe resaltar que no existe una \u00fanica forma de generar este enrutamiento, cada programador puede tener su propio estilo para este enrutamiento. En este curso vamos a ver un enrutamiento inspirado en el de <strong>Laravel,<\/strong> que es un <strong>framework PHP.<\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Generar el enrutamiento<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Para generar el enrutamiento&nbsp;vamos a utilizar la <strong>programaci\u00f3n orientada a objetos<\/strong> (<strong>OOP<\/strong>). Vamos a crear una clase especializada y que sea esa clase la que se encargue de todo este proceso de enrutar.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Cabe recalcar que&nbsp;hay que estar familiarizado con la programaci\u00f3n orientada a objetos.&nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Clase encargada del enrutamiento<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Vamos a crear una clase que va a ser la encargada del enrutamiento, para lo cual vamos a ir a nuestro directorio y vamos a crear una nueva carpeta en la ra\u00edz, denominada <em>lib&nbsp;<\/em>de librer\u00eda, y desde aqu\u00ed crear un nuevo archivo al que le vamos a dar el nombre <em>Route.php<\/em>. Dentro de este archivo vamos a crear la clase que se va a encargar de hacer el enrutamiento.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Tipos de peticiones<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Nosotros desde nuestra aplicaci\u00f3n vamos a poder hacer dos <strong>tipos de peticiones<\/strong>, de tipo <strong>GET<\/strong> y de tipo <strong>POST.<\/strong>&nbsp;Cuando definamos estas rutas tenemos que considerar a ambos tipos de peticiones, no solo las de tipo GET.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Esquema de nuestra app<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">El esquema de nuestra app hasta ahora es el siguiente:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>app<\/li>\n\n\n\n<li>lib\n<ul class=\"wp-block-list\">\n<li>Route.php (tendr\u00e1 una clase)<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>public\n<ul class=\"wp-block-list\">\n<li>css<\/li>\n\n\n\n<li>img<\/li>\n\n\n\n<li>js<\/li>\n\n\n\n<li>.htaccess<\/li>\n\n\n\n<li>index.php (archivo principal)<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>routes\n<ul class=\"wp-block-list\">\n<li>web.php (contiene las diferentes rutas)<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>.htaccess<\/li>\n\n\n\n<li>autoload (autocargador)<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Veamos la sintaxis de los archivos nuevos<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><em>public\/index.php <\/em>(archivo principal)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\n\n\/\/ Carga el archivo autoload.php que carga autom\u00e1ticamente archivos\n\/\/ Ver cap\u00edtulo autocargador para entender como funciona nuestro autoload\n\nrequire_once '..\/autoload.php';\nrequire_once('..\/routes\/web.php');<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><em>routes\/web.php\u00a0<\/em>(vamos agregando o modificando rutas)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\n\nuse Lib\\Route;\n\nRoute::get('\/', function(){\n  echo 'Hola desde la p\u00e1gina principal';\n});\n\nRoute::get('\/contact', function(){\n  echo 'Hola desde la p\u00e1gina de contacto';\n});\n\nRoute::get('\/about', function(){\n  echo 'Hola desde la p\u00e1gina de acerca de';\n});<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><em>autoload.php\u00a0<\/em>(se trata de un autocargador, que vimos en anteriores cap\u00edtulos)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\n\nspl_autoload_register(function($clase){\n  $ruta = '..\/' . str_replace(\"\\\\\", \"\/\", $clase) . \".php\";\n\n  if(file_exists($ruta)){\n    require_once($ruta);\n  } else {\n    die(\"No se pudo cargar la clase $clase\");\n  }\n});<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><em>lib\/Route.php\u00a0<\/em>(archivo que contiene la clase <strong><em>Route<\/em><\/strong>)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\n\nnamespace Lib;\n\nclass Route \n{\n  private static $routes = &#91;];\n\n  \/\/ M\u00e9todo encargado de agregar rutas GET\n  public static function get($uri, $callback){\n    self::$routes&#91;'GET']&#91;$uri] = $callback;\n  }\n\n  \/\/ M\u00e9todo encargado de agregar rutas POST\n  public static function post($uri, $callback){\n    self::$routes&#91;'POST']&#91;$uri] = $callback;\n  }\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Desde el archivo <em>web.php<\/em> iremos agregando o modificando rutas, y desde el archivo <em>index.php<\/em> s\u00f3lamente colocaremos importaciones, definiremos alguna que otra variable de configuraci\u00f3n&#8230;&nbsp;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Lo siguiente que vamos a hacer es ver como conforme vayamos ingresando a diferentes rutas, se nos muestren los mensajes que hemos definido dentro de la clase <strong><em>Route<\/em><\/strong>, para ello vamos a definir dentro de esta clase un nuevo m\u00e9todo de tipo <strong><em>estatic<\/em><\/strong> igualmente denominado <strong><em>dispatch(){};&nbsp;<\/em><\/strong>Con este m\u00e9todo lo que queremos hacer es recuperar la URI que el usuario ha escrito.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">La sintaxis de este m\u00e9todo dentro de la clase Route es la siguiente.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong><em>dispatch()<\/em><\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ M\u00e9todo para recuperar la URI\n  public static function dispatch() {\n    $uri = $_SERVER&#91;'REQUEST_URI'];\n\n    echo $uri;\n  }<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Posteriormente tenemos que ir al archivo <em>routes\/web.php<\/em> y llamar al m\u00e9todo<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><em>routes\/web.php (m\u00e9todo <strong>dispatch()<\/strong>)<\/em><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Route::dispatch();<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Lo que nos va a retornar ahora es la URI que se determina de la siguiente manera, primero muestra cual es del dominio, en nuestro caso es <em>localhost,<\/em> y todo lo que viene despu\u00e9s de <em>localhost<\/em> corresponde a la URI. El problema es que la URI muestra todo el contenido de carpetas y subcarpetas, y lo que queremos es que \u00fanicamente nos muestre la carpeta final, para ello lo que vamos a hacer es reemplazar todo ello con un dominio local, que en nuestro caso le vamos a dar el nombre <strong>mvc.test<\/strong>. Llegados a este punto vamos a hacer algunas modificaciones en algunos archivos de Windows.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Modificaciones en el archivo hosts<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Para ello buscamos el bloc de notas y lo abrimos como administrador, y seguimos la siguiente ruta<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\n<ul class=\"wp-block-list\">\n<li><em>C > Windows > System 32 > drivers > etc > hosts (archivo)<\/em><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">y hacemos clic donde dice&nbsp;<strong>Todos los archivos<\/strong>, y abrimos el archivo el archivo <em>hosts<\/em>. Estando aqu\u00ed veremos nombres de&nbsp;dominios, lo que vamos a hacer es agregar un nuevo nombre de dominio<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">127.0.0.1 mvc.test<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">el cual pondremos al final del archivo.&nbsp;Es importante utilizar la extensi\u00f3n <em>.text<\/em> para no provocar conflicto.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Avisar a Apache abriendo el archivo httpd-vhosts.conf<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Lo siguiente es avisarle a Apache que cada vez que escribamos mvc.test nos abra el proyecto localhost\/mvc\/public, para ello abrimos el archivo siguiendo la siguiente ruta<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><em>C >\u00a0xampp > apache > conf > extra > httpd-vhosts.conf<\/em><\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Y vamos a escribir al final la siguiente sintaxis<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong><em>&lt;VirtualHost *:80&gt;<\/em><\/strong><br><strong><em>&nbsp; &nbsp; DocumentRoot \u00abC:\/xampp\/htdocs\/mvc\/public\/\u00bb<\/em><\/strong><br><strong><em>&nbsp; &nbsp; ServerName mvc.test<\/em><\/strong><br><strong><em>&lt;\/VirtualHost&gt;<\/em><\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Podemos copiar ejemplos que vienen comentados y eliminar el resto de par\u00e1metros, qued\u00e1ndonos \u00fanicamente con los del ejm de arriba. Una vez hechos todos los cambios tenemos que reiniciar Apache para que la nueva configuraci\u00f3n se ejecute.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Qu\u00e9 tipo de petici\u00f3n hemos hecho<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Lo pr\u00f3ximo que nos gustar\u00eda saber es que tipo de petici\u00f3n hemos hecho, si es de tipo GET o de tipo POST. Para ello en nuestra clase Route vamos a modificar el m\u00e9todo dispatch() con la siguiente sintaxis.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ M\u00e9todo para recuperar la URI y el m\u00e9todo\n  public static function dispatch() {\n    $uri = $_SERVER&#91;'REQUEST_URI'];\n    $uri = trim($uri, \"\/\");\n\n    \/\/ Variable que nos mostrar\u00e1 el m\u00e9todo que hemos utilizado\n    $method = $_SERVER&#91;'REQUEST_METHOD'];\n\n    echo $uri;\n    echo \"&lt;br \/>\";\n    echo $method;\n  }<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Buscar&nbsp;si existe una ruta definida<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Lo pr\u00f3ximo que debemos hacer es buscar una ruta con su respectivo m\u00e9todo que hayamos definido en la clase, para ello vamos a volver a modificar el m\u00e9todo dispatch(). Os dejamos el archivo completo Route.php con la clase para que se familiaricen con el c\u00f3digo<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><em>lib\/Route.php<\/em><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\n\nnamespace Lib;\n\nclass Route \n{\n  private static $routes = &#91;];\n\n  \/\/ M\u00e9todo encargado de agregar rutas GET\n  public static function get($uri, $callback){\n    $uri = trim($uri, \"\/\");\n    self::$routes&#91;'GET']&#91;$uri] = $callback;\n  }\n\n  \/\/ M\u00e9todo encargado de agregar rutas POST\n  public static function post($uri, $callback){\n    $uri = trim($uri, \"\/\");\n    self::$routes&#91;'POST']&#91;$uri] = $callback;\n  }\n  \n  \/\/ M\u00e9todo para recuperar la URI y el m\u00e9todo\n  public static function dispatch() {\n    $uri = $_SERVER&#91;'REQUEST_URI'];\n    $uri = trim($uri, \"\/\");\n\n    \/\/ Variable que nos mostrar\u00e1 el m\u00e9todo que hemos utilizado\n    $method = $_SERVER&#91;'REQUEST_METHOD'];\n\n    foreach(self::$routes&#91;$method] as $route => $callback){\n      if($route == $uri){\n        $callback();\n        return;\n      }\n    }\n    echo \"404 Not Found\";\n  }\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">En el pr\u00f3ximo cap\u00edtulo veremos la forma de pasarle par\u00e1metros por nuestras rutas.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>En el cap\u00edtulo pasado hab\u00edamos logrado que nuestra aplicaci\u00f3n tuviera un \u00fanico punto de acceso, es decir, a que no importa lo&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":4518,"menu_order":48,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_uag_custom_page_level_css":"","footnotes":""},"class_list":["post-5355","page","type-page","status-publish","hentry"],"uagb_featured_image_src":{"full":false,"thumbnail":false,"medium":false,"medium_large":false,"large":false,"1536x1536":false,"2048x2048":false},"uagb_author_info":{"display_name":"Sutil Web","author_link":"https:\/\/sutilweb.eu\/index.php\/author\/sutilweb\/"},"uagb_comment_info":0,"uagb_excerpt":"En el cap\u00edtulo pasado hab\u00edamos logrado que nuestra aplicaci\u00f3n tuviera un \u00fanico punto de acceso, es decir, a que no importa lo...","_links":{"self":[{"href":"https:\/\/sutilweb.eu\/index.php\/wp-json\/wp\/v2\/pages\/5355","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sutilweb.eu\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/sutilweb.eu\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/sutilweb.eu\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/sutilweb.eu\/index.php\/wp-json\/wp\/v2\/comments?post=5355"}],"version-history":[{"count":3,"href":"https:\/\/sutilweb.eu\/index.php\/wp-json\/wp\/v2\/pages\/5355\/revisions"}],"predecessor-version":[{"id":5358,"href":"https:\/\/sutilweb.eu\/index.php\/wp-json\/wp\/v2\/pages\/5355\/revisions\/5358"}],"up":[{"embeddable":true,"href":"https:\/\/sutilweb.eu\/index.php\/wp-json\/wp\/v2\/pages\/4518"}],"wp:attachment":[{"href":"https:\/\/sutilweb.eu\/index.php\/wp-json\/wp\/v2\/media?parent=5355"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}