Eliminar recursos en una API REST es un proceso esencial que completa el ciclo CRUD (Crear, Leer, Actualizar, Eliminar). Este proceso se realiza mediante el método HTTP DELETE. Al implementar este método, podemos gestionar eficientemente los datos en nuestros servidores y garantizar que la API sea escalable y manejable en el tiempo.
¿Cómo funciona el método HTTP DELETE?
El método DELETE se utiliza para eliminar un recurso específico de una colección. Aquí hay un proceso general:
Verificación de existencia: Antes de intentar eliminar un recurso, es crucial verificar si el recurso existe. Si el recurso no está presente, debemos manejar adecuadamente esta situación, sin intentar una operación fallida.
Ejecutar eliminación: Una vez verificado, podemos proceder a eliminar el recurso. En un sistema real, esto implicaría ejecutar un comando SQL para eliminar el registro de la base de datos. Sin embargo, en implementaciones más simples, como un arreglo en la memoria, se puede utilizar una función como unset() en PHP para eliminar la clave directamente.
<?php// Supongamos que tenemos un arreglo$libros=['libro1','libro2','libro3'];// Queremos eliminar 'libro1'if(array_key_exists(0,$libros)){unset($libros[0]);}// Verificar que el libro haya sido eliminadoechocount($libros);// Output: 2?>
Retorno del estado: Finalmente, después de la eliminación, la API debería devolver el estado actual de la colección para confirmar que el recurso ha sido efectivamente eliminado.
¿Cuáles son las diferencias con los métodos PUT o POST?
Aunque los métodos PUT, POST y DELETE son parte del ciclo CRUD, cada uno tiene un uso y comportamiento distintos. Aquí algunas diferencias clave:
PUT vs DELETE: Mientras PUT reemplaza un recurso existente con uno nuevo, DELETE simplemente elimina el recurso sin reemplazo.
POST vs DELETE:POST se usa para crear nuevos recursos o entidades, mientras que DELETE los elimina.
¿Qué considerar al eliminar recursos?
Es importante tener en cuenta varios aspectos al implementar el método DELETE en una API REST:
Autorización: No todas las solicitudes a la API deberían poder eliminar recursos. Asegúrate de que solo los usuarios con los permisos adecuados puedan realizar esta acción.
Eliminación en cascada: Si el recurso eliminado está vinculado a otros recursos, considera cómo estos vínculos se gestionarán. Podría ser necesario eliminar o actualizar recursos relacionados.
Optimización y consistencia: La eliminación en bases de datos de grandes volúmenes de datos debe ser manejada cuidadosamente para evitar bloqueos y problemas de consistencia.
¿Cuál es el siguiente paso?
Con el entendimiento de cómo eliminar recursos usando el método DELETE, el próximo desafío es determinar quién tiene acceso a estas operaciones. La autenticación y autorización robusta son fundamentales para proteger la integridad de tus datos. ¡Te animamos a seguir aprendiendo y profundizando en estos temas críticos para el desarrollo de una API REST segura y eficiente!
<?php
$allowedResourceTypes =['books','authors','genres'];$resourceType = $_GET['resource_type'];if(!in_array($resourceType, $allowedResourceTypes)){ 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 correcto y devilvemos en formafo jsonswitch(strtoupper($_SERVER['REQUEST_METHOD'])){case'GET':// en caso de que no pidan ningun recursoif(empty( $resourceId )){ echo json_encode( $books );}else{// si llegan a pedir un recurso en especificoif(array_key_exists( $resourceId, $books)){ echo json_encode( $books[ $resourceId ]);}}break;case'POST': $json =file_get_contents('php://input');// transformamos el json recibido a un nuevo elemento del arreglo $books[]=json_decode($json,true);// emitimos hacia la salida la ultima clave del arreglo de los libros// echo array_keys( $books )[count($books) -1]; echo json_encode($books);break;case'PUT'://validamos que el recurso buscado existaif(!empty($resourceId)&&array_key_exists($resourceId, $books)){// Tomamos la entrada cruda $json =file_get_contents('php://input');// transformamos el json recibido a un nuevo elemento del arreglo $books[$resourceId]=json_decode($json,true);// Retornamos la coleccion modificada en formato json echo json_encode($books);}break;case'DELETE':// validamos que el recurso existaif(!empty($resourceId)&&array_key_exists($resourceId, $books)){// Eliminamos el recursounset( $books[ $resourceId]);// Aquí verificamos que los cambios se han realizado echo json_encode($books);}break;}// Inicio el servidor en la terminal 1, aqui le asignamos el puerto 8000// php -S localhost:8000 server.php// Terminal 2 ejecutar // curl http://localhost:8000 -v// curl http://localhost:8000/\?resource_type\=books// curl http://localhost:8000/\?resource_type\=books | jq// ver la comunicacion a través de los encabezados:// $ curl http://localhost:8000/\?resource_type\=books -v > /dev/null// consulta//$curl "http://localhost:8000?resource_type=books&resource_id=1"// Método POST//curl -X 'POST' http://localhost:8000/books -d '{"titulo":"Nuevo Libro","id_autor":1,"id_genero":2}'// Método Put - el recurso 1 será reemplazado por el libro que estoy creando// $ curl -X 'PUT' http://localhost:8000/books/1 -d '{"titulo": "Nuevo Libro", "id_autor": 1, "id_genero": 2}'// Método Delete// curl -X 'DELETE' http://localhost:8000/books/1?>
hola, corri este codigo, pero tiene errores,
PHPNotice:Undefined index: resource_type in/home/ruroni/Documents/server2.php on line 9
alguien realmente logro obtener los resultados? Aparte del PHP 7.4 hay algo mas que deba estar instalado en ubuntu? creo que antes de ahcer todo este curso, es necesario que muestren como debuggear estos ejemplos en php, :(
Sebastian El código aparenta estar bien, si bien es importante hacer validaciones de momento te recomiendo eliminar el código de la validación del recurso para que puedas seguir probando
Yo traté de implementar todos los métodos en un API en python usando flask para poder entender co se hacía eso en ese lenguaje. Es algo sencillo pero funciona. Este es el resultado:
from flask import Flask
from flask_restful import Api, Resource, reqparse
app = Flask(__name__)
api = Api(app)
malwares = [
{
"name" : "spyfocus.js",
"type" : "adware",
"media" : "url",
},
{
"name" : "greencard.zip",
"type" : "trojan",
"media" : "zip",
},
{
"name" : "credit_card.rar",
"type" : "trojan",
"media" : "zip",
},
{
"name" : "system35.dll",
"type" : "virus",
"media" : "exe",
},
{
"name" : "registry_mode.bat",
"type" : "worm",
"media" : "msi",
}
]
class Malware(Resource):
def get (self, name):
for malware in malwares:
if (name == malware["name"]):
return malware, 200
return "Marlware not found", 404
def post (self, name):
parser = reqparse.RequestParser()
parser.add_argument("type")
parser.add_argument("media")
args = parser.parse_args()
for malware in malwares:
if(name == malware["name"]):
return"Malware with name {} already exits".format(name), 400
malware = {
"name" : name,
"type" : args["type"],
"media" : args["media"]
}
malwares.append(malware)
return malware, 201
def put (self, name):
parser = reqparse.RequestParser()
parser.add_argument("type")
parser.add_argument("media")
args = parser.parse_args()
for malware in malwares:
if (name==malware["name"]):
malware["type"] = args["type"]
malware["media"] = args["media"]
return malware, 200
malware = {
"name" : name,
"type" : args["type"],
"media" : args["media"]
}
malwares.append(malware)
return malware, 201
def delete (self, name):
global malwares
malwares = [malware for malware in malwares if malware["name"] != name]
return "{} is deleted.".format(name), 200
api.add_resource(Malware, "/malware/<string:name>")
app.run(debug = True) #enable flask to reload after a change, only develoing mode.
Mira mi versión lo estoy haciendo un poco mas escalable y usando flask_restful
API REST FLASK
Puedes evitar el for por un
if book_id not inBOOKS:abort(404, message='El libro con id {} no existe'.format(book_id))```
Con este curso me ha comenzado ha gustar php, qué es esto? :0
y con cada clase me gusta más. Se siente geniaaaaal
Bienvenido al lado oscuro.
Por el contrario, a mí no puede llegar a gustar PHP XD
Eliminar datos a través de HTTP DELETE:
$ curl -X 'DELETE' http://localhost:8000/books/1
DELETE: Este método se utiliza para eliminar un registro existente, es similar a DELETE a la base de datos. No soporta el envío del payload.
GET optener recursos, tabnto colecciones como recursos puntulaes
POST crear recursos en tu servivod
PUT remplazo de recursos existentes por uno nuevo
Delete borra el recurso
Que sencillo es PHP cuando tienes conocimientos previos de programación.
me encanta
Vale, DELETE lo que hace es eliminar un recurso especificado.
Realmente no se suelen eliminar los recursos de una base de datos, una buena práctica es manejar estos datos con flags, en plan 1 es que está activo y 0 que está inactivo, y el método DELETE se encarga de poner en 0 las flags ^^
Fragmento de código en javascript:
app.delete('/books/:id',(req, res)=>{const paramId = req.params.id// Verifica si se ha puesto un id y que este existaif(paramId && books[paramId]){// Remueve el indice enviado y lo guarda en "deleted_book"const deleted_book = books.splice(paramId -1,1);// Envia un ok, el libro eliminado y la colección de libros actual res.send({status:'ok', deleted_book, books })}else{// En caso de no encontrar, devuelve error res.json({status:'Failed',error:'missing or invalid param: id'});}})
Y para eliminar solo es poner:
curl -X 'DELETE' localhost:5000/books/1 | jq, siendo el /books/1 el ID a eliminar.
Listo, Ya se fue ese 'Odioso Libro' de mi Biblioteka de Libros.
\nEsta Clase estuvo muy Buena junto colas anteriores tambien.
Una pregunta compañeros, en que caso se debe usar la opción json_encode y json_decode?
Gracias :D
¡Hola!, json_encode se usa para "codificar" un array a un JSON, básicamente recibe un array y te devuelve un JSON, recuerda que en cualquier API la comunicación se hace por medio de JSON, no puedes mandar un array de PHP como respuesta jaja
Por otra parte, json_decode se usa para "decodificar" un JSON hacia un array, es decir, recibe cualquier JSON y lo transforma a un array de PHP.
En PHP no existen los objetos JSON, por lo que necesitamos una forma fácil de trabajar con objetos JSON que son muy importantes, entonces para eso son estas funciones, básicamente son como los traductores de PHP para que pueda comunicarse con cualquier otro lenguaje usando JSON.
En PHP lo más parecido que tenemos a los JSON son los arreglos asociativos, es por eso que estas funciones trabajan con arreglos :D
El repositorio de la clase no funciona. ¿Podrian proporcionarmelo? Gracias!
Yo hice el mio en el framework de Lumen/PHP, espero seguir aprendiendo y que este aporte le sirva a alguien ;) .
En el archivo routes/web.php :
<?php
/** @var \Laravel\Lumen\Routing\Router $router *//*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| Here is where you can register all of the routes for an application.
| It is a breeze. Simply tell Lumen the URIs it should respond to
| and give it the Closure to call when that URI is requested.
|
*///Definicion de las rutas para el API REST$router->get('/{resource_type}','APIController@index');$router->get('/{resource_type}/{resource_id}','APIController@index');$router->post('/{resource_type}','APIController@index');$router->put('/{resource_type}/{resource_id}','APIController@index');$router->delete('/{resource_type}/{resource_id}','APIController@index');
Luego cree un controlador llamado app/Http/Controllers/APIController.php con el siguiente conteido:
<?php
namespace App\Http\Controllers;use Illuminate\Http\Request;classAPIControllerextendsController{//Se define los tipos de recursos permitidosprivate $allowedResourceTypes =['books','authors','genres',];//se define los libros almacenadosprivate $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 define la funcion principal que determinara que acción se realizara segun el metodofunctionindex($resource_type, $resource_id =null,Request $request){//Si el tipo de recurso no es encontrado devolvera un mensaje de error y un estado de 404if(!in_array($resource_type, $this->allowedResourceTypes)){returnresponse()->json(['error'=>"resource type $resource_type is unknow"],404);}//Si el id del libro no es nulo y no existe en el arreglo de libros devolvera un mensaje de error y un estado de 404if(!is_null($resource_id)){if(!array_key_exists($resource_id, $this->books)){returnresponse()->json(['error'=>"resource $resource_id doesn't exist"],404);}}//Se hace el analisis del metodo y se deriva la respuesta segun el metodoswitch(strtoupper($request->method())){case'GET':return $this->get($resource_type, $resource_id, $request);break;case'POST':return $this->post($resource_type, $request);break;case'PUT':return $this->put($resource_type, $resource_id, $request);break;case'DELETE':return $this->delete($resource_type, $resource_id, $request);break;}}//Metodo GETfunctionget($resource_type, $resource_id, $request){//Si existe un id de recurso retornara solo ese elementoif(!is_null($resource_id)){returnresponse()->json($this->books[$resource_id]);}//De lo contrario retornara todos los librosreturnresponse()->json($this->books);}//Metodo POSTfunctionpost($resource_type, $request){//Lee todo el contenido de la peticion $new_book = $request->all();//La agraga al arreglo de libros $this->books[]= $new_book;//Retorna una respuesta de codigo 201 confirmando la creacion del elemento y todos los librosreturnresponse()->json(['message'=>'new element created','books'=> $this->books
],201);}//Metodo PUTfunctionput($resource_type, $resource_id, $request){//Lee todo el contenido de la peticion $update_book = $request->all();//Actualiza el elemento del arreglo de libros $this->books[$resource_id]= $update_book;//Retorna una respuesta de codigo 201 confirmando la actualizacion del elemento y todos los librosreturnresponse()->json(['message'=>'element updated','books'=> $this->books
],201);}functiondelete($resource_type, $resource_id, $request){//Elimina el elemento del arreglo segun el id de recursounset($this->books[$resource_id]);//Retorna una respuesta de codigo 200 confirmando la eliminacion del elemento y todos los librosreturnresponse()->json(['message'=>'element eliminated','books'=> $this->books
],200);return"Adios";}}
Se puede enviar archivos como por ejemplo una imagen a través de PUT a una API y en caso de poderse es recomendable hacerlo?
No estoy 100% seguro pero creo que la app cliente debe hacer eso y pasarle la ubicación al backend para que la guarde
Si se pueden pasar imágenes por API, tu manejas el servidor y defines en que lugar almacenarla.
Hola a todos. En el código me sale este error:
Pensé que de pronto era un error en mi código, pero intenté usar el archivo que está en los recursos y aun así me sale el error. Por si acaso les pongo el código que yo escribí:
El error era curl: (52) Empty reply from server, por si no se ve la imagen
Tengo una pregunta, ustedes se aprenden como tal cada uno de los metodos que hay que utilizar de una forma sistematica, o con el tiempo de tanto realizarlo de cierta manera se acostumbran y por ende escriben todo eso sin un referente.
Las personas que conozco que programan dicen que normalmente la mayoría de cosas es por la costumbre algunas cosas ya las hacen en automática, pero que cuando tienen alguna duda siempre van y buscan en la documentación :)
que bonito , solo falta el patch method, para modificar solo una parte de la entidad no toda como lo hace put
En Go:
func deleteBook(w http.ResponseWriter, r *http.Request, id int){if id >=len(Books){ w.WriteHeader(http.StatusNotFound) fmt.Fprint(w,"<h2>Not Found</h2>")return}Books=append(Books[:id],Books[id+1:]...) w.WriteHeader(http.StatusOK) fmt.Fprint(w,"OK")}