¿Cómo consultar un recurso específico en una aplicación?
Explorar recursos en una aplicación web es una habilidad esencial para los desarrolladores. En esta sesión, vamos a profundizar en cómo consultar un recurso en particular dentro de una colección, utilizando PHP.
¿Cuál es la lógica detrás de la consulta de un recurso?
Para obtener la información de un libro específico, es crucial identificar cuál es el recurso requerido. Esto se logra a través de una variable extraída de la URL, generalmente conocida como identificador de recurso (resource_id). Es importante validar si este parámetro realmente existe para evitar errores en la aplicación.
¿Cómo validar la existencia del parámetro?
PHP ofrece una función útil llamada array_key_exists, que verifica si una clave específica está presente dentro de un array. La implementación sería la siguiente:
Utilizando esta validación, puedes determinar si el usuario ha solicitado ver un recurso en particular, o si se desea mostrar toda la colección.
¿Cuál es la respuesta adecuada para un recurso individual?
Si el resource_id coincide con una clave dentro de un array de libros, se debe retornar solamente el libro solicitado. Aquí es crucial utilizar json_encode para asegurarse de que la respuesta sea en formato JSON, que es estándar para APIs:
¿Cómo probar las consultas utilizando la consola y cURL?
El uso de herramientas como cURL permite probar y verificar el comportamiento del servidor al manejar diferentes consultas HTTP. Por ejemplo, para solicitar un libro específico:
curl http://localhost:8000/libros/1
Esto debe devolver los datos del libro con id 1 como un objeto JSON.
¿Qué pasa con las URLs amigables?
Las URLs amigables mejoran la legibilidad y son preferidas en aplicaciones modernas. Configurar URLs amigables implica el uso de expresiones regulares que procesan y transforman las URLs recibidas. En PHP, esto a menudo se puede manejar con un router inicial que procesa las peticiones antes de ser pasadas al controlador principal:
if(preg_match('/^\/libros\/\d+$/',$request_uri)){// Lógica para devolver un único libro}
Con estas configuraciones, ejecutar el servidor con el router nuevo permite definir caminos más simplificados como /libros/1 en vez de rutas con parámetros explícitos.
¿Cómo reconfigurar el servidor para usar un router?
Cuando se implementan URLs amigables, es necesario especificar un nuevo archivo de ruta al iniciar el servidor:
php -S localhost:8000 rutas.php
Esto asegura que las solicitudes pasen primero por tu sistema de rutas que maneja de forma eficiente todas las peticiones entrantes.
Estos son los pasos básicos para manejar recursos específicos dentro de una aplicación web. Recuerda practicar y experimentar con diferentes configuraciones para dominar esta habilidad esencial. ¡Continúa explorando y perfeccionando tu conocimiento en desarrollo web! estudiantes y mejora tus habilidades.
Para los que estén corriendo en localhost tienen que agregar mas opciones a la condicional
en esta parte :
preg_match('//([^/]+)/([^/]+)/([^/]+)/([^/]+)/'
antes del ultimo slash -> /
agregar: /([^/]+)
por cada directorio adicional que tengan
Este comentario debería destacar mucho más, gracias!
Versión con python
from flask importFlask, jsonify, make_response
from flask_restful importResource,Api, abort
app =Flask(__name__)api =Api(app)BOOKS={'1':{'isbn':'744586','title':'Cien años de soledad','description':'Lorem insup lol.','autor':'Gabriel Garcia Marquez'},'2':{'isbn':'7894546','title':'De animales a dioses','description':'Lorem insup lol.','autor':'Yuval Noah Harari'}}def abort_if_book_doesnt_exits(book_id):if book_id not inBOOKS:abort(404, message='El libro con id {} no existe'.format(book_id))classBookList(Resource): def get(self):returnjsonify({'data':BOOKS})classBook(Resource): def get(self, book_id):abort_if_book_doesnt_exits(book_id)returnjsonify({'data':BOOKS[book_id]})classAuthors(Resource): pass
classGeneres(Resource): pass
api.add_resource(BookList,'/books')api.add_resource(Book,'/books/<book_id>')api.add_resource(Authors,'/authors')api.add_resource(Generes,'/generes')if __name__ =='__main__': app.run(debug=True)
Me alegra poderte ayudar, te dejo el repo donde esta todo por si necesitas guiarte un poco sobre todo en la auth con hmac no hay mucha información sobre ello en internet
API REST REPO
Viaja entre las ramas o por los commits y vas viendo, Suerte!
Excelente, agregue comentarios para entender un poco mejor:
# Importsfrom flask importFlask, jsonify, make_response
from flask_restful importResource,Api, abort
# Create app and api
app =Flask(__name__)api =Api(app)# Data base
BOOKS={'1':{'isbn':'744586','title':'Cien años de soledad','description':'Lorem insup lol.','autor':'Gabriel Garcia Marquez'},'2':{'isbn':'7894546','title':'De animales a dioses','description':'Lorem insup lol.','autor':'Yuval Noah Harari'}}# Aborts the request and returns an error
def abort_if_book_doesnt_exits(book_id):if book_id not inBOOKS:abort(404, message='El libro con id {} no existe'.format(book_id))# Returns the whole book list
classBookList(Resource): def get(self):returnjsonify({'data':BOOKS}) # Returnsas json in data variables
# Returns an especific id book
classBook(Resource): def get(self, book_id):abort_if_book_doesnt_exits(book_id)returnmake_response(jsonify(BOOKS[book_id]),200) # Returns a response as json with some info code
classAuthors(Resource): pass
classGeneres(Resource): pass
# Add resources asREST arquitecture
api.add_resource(BookList,'/books')api.add_resource(Book,'/books/<book_id>') #<> means it's a variable
api.add_resource(Authors,'/authors')api.add_resource(Generes,'/generes')if __name__ =='__main__': app.run(debug=True)
Archivo server.php
<?php
// Definimos los recursos disponibles$allowedResourceType =['books','authors','genres',];// Validamos que el recurso este disponible$resourceType = $_GET['resource_type'];if(!in_array($resourceType, $allowedResourceType)){ die;}// Defino los recursos$books =[1=>['titulo'=>'Lo que el viento se llevo','id_autor'=>2,'id_genero'=>2,],2=>['titulo'=>'La Iliada','id_autor'=>1,'id_genero'=>1,],3=>['titulo'=>'La Odisea','id_autor'=>1,'id_genero'=>1,],];// Se indica al cliente que lo que recibirá es un jsonheader('Content-Type: application/json');// Levantamos el id del recurso buscado$resourceId =array_key_exists('resource_id', $_GET)? $_GET['resource_id']:'';// Generamos la respuesta asumiendo que el pedido es correctoswitch(strtoupper($_SERVER['REQUEST_METHOD'])){case'GET':if(empty( $resourceId )){ echo json_encode( $books );}else{if(array_key_exists( $resourceId, $books)){ echo json_encode( $books[ $resourceId ]);}}break;case'POST':break;case'PUT':break;case'DELETE':break;}
Este video es oro puro.
La conversion a url amigables esta hecha de manera sencilla y precisa.
@beco tiene un curso, aqui en platzi, de expresiones regulares muy bueno, para comprender a fondo las lineas del preg_match
el micrófono es muy potente... me distrae como traga saliva al hablar XD
Del carajo esta clase.! Es como hacer una autopsia al código, así se aprende medicina.! Excelente.
Hola iacostaco ¿De qué país eres? yo soy de México, y tu expresión se escucha algo agresiva de manera negativa, pero al final del enunciado das a entender que lo dijiste de manera positiva, lo cual me confundió, jeje... Simplemente me dio curiosidad la manera en que nos expresamos los hispanohablantes en diferentes países.
Hola @jose122088! Soy de Colombia y en verdad tengo muchos amigos y allegados de México. Una disculpa por mi expresión (jajaja), pero te explico. En Colombia se usa mucho para expresar felicidad y estar bien frente a un tema. Sin embargo como todo, depende del contexto. Así somos los latinos!
Gracias por tu mensaje. Un abrazo.
Para escapar el caracter & (Ampersand) en el CMD de windows se utiliza el caracter ^. Por lo que la petición completa quedaría de la siguiente manera:
En lugar de usar preg_match use el método explode() algo así
explode('/', $_SERVER['REQUEST_URI']);
Lo que hace esto es dividir mi URL en array cada que se encuentra un /, recomiendo hacer un var_dump para que veas que posición ocupa books y el id
Bueno eso fue todo
Les dejo el código del router con comentarios de lo que hace para que no se confundan ni les queden lagunas
<?php
/* El router nos va a permitir configurar el servidor para
* poder gestionar las URL de las peticiones. Es decir, podremos
* pasar de una petición con parametros:
* https://example.com/?resource_type=books&resource_id=1
* a una sin parámetros y más estética:
* https://example.com/book/1
* para que sea más agradable al usuario final.
*/ $matches =[];// Si la URI coincide con la expresión regular (String que empieza con// una diagonal, seguido del tipo de recurso, seguido de otra diagonal,// seguido del recurso en particular, y que termine con otra diagonal),// entonces se agregan el tipo de recurso y el recurso particular al// arreglo de matches.if(preg_match('/\/([^\/]+)\/([^\/]+)/', $_SERVER['REQUEST_URI'], $matches)){// Creamos una URL con parámetros cuayos valores se obtendrán de lo que// la funcion preg_match agregó al arreglo $_GET['resource_type']= $matches[1]; $_GET['resource_id']= $matches[2];// Si algo falla el error se envia a un correo (supuestamente).// Ver documentacion de error_log() y leer la descripcioón del// parámetro message_type.error_log(print_r($matches,1));// Despues de hacer este análisis, se ejecuta el código del archivo// server.php para continuar con la ejecución de la API require 'server.php';}// Si la URI coincide con la expresión regular (String que empieza con// una diagonal, seguido del tipo de recurso,y que termine con otra // diagonal), entonces se agrega el tipo de recurso arreglo de matches.elseif(preg_match('/\/([^\/]+)\/?/', $_SERVER['REQUEST_URI'], $matches)){ $_GET['resource_type']= $matches[1];error_log(print_r($matches,1)); require 'server.php';}else{// Si nada coincidió, agregamos la cadena 'No matches' al error log// y devolvemos un error 404error_log('No matches');http_response_code(404);}?>
Apuntes:
Basicamente la expresion regular evalua, si despues de la primera barra de la URL, existe cualquier conjunto de caracteres que permita una URL, y luego repite el mismo proceso en caso de que haya un parámetro despues de una segunda barra, en caso tal de que no haya una segunda barra, solamente capturará lo contenido despues de la primera barra (que seria el parametro y en este caso, el parametro de books.
NOTA: En el caso de usar IIS, debemos crear un archivo .htaccess para la reescritura de URL
La operación del if en la misma linea se usa con el operador mas conocido como operador ternario.
Y ahora podemos hacer nuestra petición de la siguiente manera:
curl http ://localhost:8000/books/1
Si tienes problemas con "jp" y estas en Mac, instala.
brew install jq
Link de donde lo resolví
En el caso de Ubuntu/Debian 🐧
sudo apt-get install jq
LEs dejo mi codigo en php, para validar ademas de libros autores, generos y libros
<?php
//definimos los recursos disponibles$allowedResourceTypes =['books','authors','genders'];//validamos que el recurso este disponible$resourceType = $_GET['resource_type'];if(!in_array($resourceType, $allowedResourceTypes)){ die;}//definos los recursos$books =[0=>['title'=>'Lo que el viento se llevo','id_author'=>1,'id_gender'=>1],1=>['title'=>'La iliada','id_author'=>0,'id_gender'=>0,],2=>['title'=>'La riqueza de las naciones','id_author'=>2,'id_gender'=>2,],3=>['title'=>'El diario de Ana Frank','id_author'=>3,'id_gender'=>3,],4=>['title'=>'La odisea','id_author'=>0,'id_gender'=>0,],5=>['title'=>'Teoría de los sentimientos morales','id_autor'=>2,'id_gender'=>2,]]; $genders =[0=>['id_genders'=>0,'genero'=>'poeseia/epopeya',],1=>['id_genders'=>1,'genero'=>'novela',],2=>['id_genders'=>2,'genero'=>'politica/naturaleza humana',],3=>['id_genders'=>3,'genero'=>'autobiografia',]]; $authors =[0=>['id_authors'=>0,'athors'=>'Homero',],1=>['id_authors'=>1,'athors'=>'Margaret Mitchell',],2=>['id_authors'=>2,'athors'=>'Adam Smith',],3=>['id_authors'=>3,'athors'=>'Ana frank',],];header('Content-Type:application/json');//levantamos el id del recurso buscado $resourceId =array_key_exists('resource_id',$_GET)? $_GET['resource_id']:'';// Generamos la respuesta asumiendo que el pedido es correctoswitch(strtoupper($_SERVER['REQUEST_METHOD'])){case'GET'://Validar que tipo de recurso esswitch($resourceType){case'books':if(empty($resourceId)){ echo json_encode($books);}{if(array_key_exists($resourceId, $books)){ echo json_encode($books[$resourceId]);}}break;case'authors':if(empty($resourceId)){ echo json_encode($authors);}{if(array_key_exists($resourceId, $authors)){ echo json_encode($authors[$resourceId]);}}break;case'genders':if(empty($resourceId)){ echo json_encode($genders);}{if(array_key_exists($resourceId, $genders)){ echo json_encode($genders[$resourceId]);}}break;}break;case'POST':break;case'PUT':break;case'DELETE':break;}```
¿Tengo xampp instalado, quiero probar las url amigables en localhost como podria hacerlo?
Lo resolvi añadiendo a las variables de entorno de windows la carpeta de php que esta en mi directorio de xampp, luego ejecute la consola como administrador y ejecute los comandos que indican en el video, todo ok.
Como puedo hacer para poder hacer q me funcione desde xampp o un hosting, ya que no logo hacer que me funcione el router.php
lo pudiste solucionar ?
¿alguien mas lo esta probando en un servidor (hosting) real y no le funciona lo ultimo?
me sale erro 404, no se que se deba hacer en este caso
Probablemente hay algún error en URL o en tu servidor que tienes en hosting está teniendo un error y por eso no encuentra la ruta. Podría ser por varias razones que esté dando 404.