Cómo eliminar un registro de la base de datos

Deberíamos agregar una forma para que un usuario pueda eliminar su hilo de la base de datos si así lo desea. Este tutorial nos hará hacer exactamente eso. En primer lugar, configuraremos una o dos pruebas para ayudarnos a garantizar que la función de eliminación funcione según lo previsto. A continuación, aprenderemos un poco sobre el envío de códigos de respuesta, lo que es útil cuando se trata de escenarios en los que el back-end actúa como una API. Otro tema candente será aprender acerca de cómo eliminar modelos relacionados al eliminar un registro dado. Cuando eliminamos un hilo, también queremos considerar la relación con las respuestas y eliminar las respuestas asociadas también. Por último, echaremos un vistazo rápido a la eliminación con eventos modelo y configuraremos el enlace de la interfaz de usuario para que realmente active la eliminación.


Hilo puede ser eliminado Prueba

En el directorio de prueba de características ya tenemos una clase que trata con subprocesos. Para comenzar, podemos agregar una prueba llamada test_a_thread_can_be_deleted () a la clase CreateThreadsTest.
test_a_thread_can_be_deleted

¿Qué hará nuestra prueba? Aquí está el pseudocódigo.

  • Dado que un usuario ha iniciado sesión
  • Dado que hay un hilo
  • Cuando el usuario envía una solicitud json para eliminar el hilo
  • Entonces el hilo ya no debería existir en la base de datos

Con esos pasos en mente, aquí está nuestro primer intento de crear el código para esta prueba.

La ejecución de la prueba test_a_thread_can_be_deleted () nos da una MethodNotAllowedHttpException que sabemos que significa que nos falta una ruta.

vagrant @ homestead: ~ / Code / forumio $ phpunit --filter test_a_thread_can_be_deleted
PHPUnit 6.5.5 por Sebastian Bergmann y colaboradores.

E 1/1 (100%)

Tiempo: 993 ms, Memoria: 8.00MB

Hubo 1 error:

1) Pruebas \ Característica \ CreateThreadsTest :: test_a_thread_can_be_deleted
Symfony \ Component \ HttpKernel \ Exception \ MethodNotAllowedHttpException:

Como tal, abramos nuestro archivo de rutas y solucionemos eso de inmediato. A continuación se muestra la nueva ruta resaltada para nosotros.

Podemos ejecutar la prueba nuevamente, pero ahora encontramos un error diferente.

vagrant @ homestead: ~ / Code / forumio $ phpunit --filter test_a_thread_can_be_deleted
PHPUnit 6.5.5 por Sebastian Bergmann y colaboradores.

E 1/1 (100%)

Tiempo: 1.04 segundos, Memoria: 10.00MB

Hubo 1 error:

1) Pruebas \ Característica \ CreateThreadsTest :: test_a_thread_can_be_deleted
Symfony \ Component \ Debug \ Exception \ FatalThrowableError: Error de tipo: Argumento 1 pasado a App \ Http \ Controllers \ ThreadsController :: destroy () debe ser una instancia de App \ Thread, cadena dada

Estamos recibiendo un error fatal de tipo arrojadizo. Bueno, veamos el método de destrucción en ThreadsController y veamos qué tenemos.

Por supuesto, esta prueba fallaría. Solo tenemos un stub de método para destroy (). Necesitamos actualizar ese método para que realmente elimine un hilo.

Ejecutemos la prueba nuevamente para ver el resultado.

vagrant @ homestead: ~ / Code / forumio $ phpunit --filter test_a_thread_can_be_deleted
PHPUnit 6.5.5 por Sebastian Bergmann y colaboradores.

E 1/1 (100%)

Tiempo: 878 ms, Memoria: 10.00MB

Hubo 1 error:

1) Pruebas \ Característica \ CreateThreadsTest :: test_a_thread_can_be_deleted
Illuminate \ Database \ QueryException: SQLSTATE [HY000]: Error general: 25 enlaces o índice de columna fuera de rango (SQL: seleccione el recuento (*) como agregado de "hilos" donde ("user_id" = 2 y "channel_id" = 1 y "title" = Ea maxime et omnis. y "body" = Id velit sequi nulla est officiis sed. Laborum sit quas velit aliquid. Fugit culpa rerum enim. Quos dicta ut est maiores. y "updated_at" = 2018-01-24 23 : 02: 50 y "created_at" = 2018-01-24 23:02:50 e "id" = 1 y "channel" = 1))

Esto en realidad podría ser un problema en el código de prueba. Cambiemos la prueba a esto:

Ejecutar la prueba una vez más nos da un verde para aprobar, por lo que parece que ese cambio nos solucionó.
hermoso resultado de aprobación de prueba verde


Establecer código de respuesta

Cuando los datos se cambian en el servidor como resultado de una solicitud que se le envía, tiene sentido devolver un código de estado para indicar el resultado de esa solicitud. Podemos actualizar la prueba y el método destroy () para facilitar esta idea.


Cómo eliminar modelos relacionados

Los hilos pueden tener respuestas. Si un usuario elimina un hilo, pero ese hilo tiene respuestas asociadas, bueno, eso es un problema en este momento. En este momento, esas respuestas se dejarán en la base de datos como registros fantasmas. No quiere eso, por lo que debemos ver cómo eliminar las respuestas relacionadas a cualquier tema dado. La primera opción es simplemente hacer referencia a la relación en el método destroy () y hacer una llamada para eliminar:

Como ahora estamos eliminando las respuestas asociadas, también actualice nuestra prueba para reflejar eso.

Eso debería hacerlo, hagamos la prueba.

vagrant @ homestead: ~ / Code / forumio $ phpunit --filter test_a_thread_can_be_deleted
PHPUnit 6.5.5 por Sebastian Bergmann y colaboradores.

E 1/1 (100%)

Tiempo: 1.11 segundos, Memoria: 8.00MB

Hubo 1 error:

1) Pruebas \ Característica \ CreateThreadsTest :: test_a_thread_can_be_deleted
InvalidArgumentException: no se pudo encontrar un año de cuatro dígitos
Datos faltantes

¿Que demonios? Ese es un error extraño. "InvalidArgumentException: no se pudo encontrar un año de cuatro dígitos Datos faltantes". Ok, parece que se pasó el argumento incorrecto al método create () para la fábrica de modelos. create ('App \ Reply', ['thread_id', $ thread-> id]) debe cambiarse para crear ('App \ Reply', ['thread_id' => $ thread-> id]). Aquí está la prueba correcta con las líneas resaltadas que tratan con las relaciones de modelo relacionadas, y cuando ejecutamos la prueba, pasa. ¡Si!


Eliminar con eventos modelo

A medida que Eloquent interactúa con la base de datos, desencadena varios eventos durante el ciclo de vida de la interacción. Podemos conectarnos a esos eventos y tomar varias medidas si lo deseamos. De hecho, podemos usar Model Events para escuchar la eliminación de un hilo y luego eliminar también las respuestas asociadas. Continúe y abra el modelo Thread.php, y podemos ver cómo configurar esto.

En el código anterior, vemos el fragmento resaltado dentro del método boot () en el Modelo. Esto es básicamente aprovechar esos eventos modelo para nosotros. Se está diciendo, cuando el hilo se encuentra en proceso de ser eliminado , seguir adelante y también eliminar todas las respuestas. Muy bien, ¿verdad? Ahora puede eliminar la llamada a $ thread-> replies () -> delete () del método destroy () en ThreadsController y todo debería funcionar. Ejecutar nuestra prueba nos muestra que todavía está funcionando. Agradable.

vagrant @ homestead: ~ / Code / forumio $ phpunit --filter test_a_thread_can_be_deleted
PHPUnit 6.5.5 por Sebastian Bergmann y colaboradores.

. 1/1 (100%)

Tiempo: 828 ms, Memoria: 10.00MB

OK (1 prueba, 3 afirmaciones)

Los invitados no pueden eliminar hilos

Solo los usuarios registrados deben poder eliminar su hilo. No queremos que los visitantes aleatorios de la aplicación puedan simplemente explorar un hilo, hacer clic en un enlace y eliminar el hilo. Podemos configurar una prueba para admitir esta función. Una vez más, intentamos seguir el formato Dado, Cuándo, Luego de configurar una prueba.

  • Dado que hay un invitado
  • Dado que hay un hilo
  • Cuando un invitado envía una solicitud json para eliminar el hilo
  • Entonces la respuesta debería ser una redirección

La prueba puede verse así:

función pública test_guests_can_not_delete_threads ()
{
    $ thread = create ('App \ Thread');

    $ respuesta = $ this-> json ('DELETE', $ thread-> path ());

    $ respuesta-> afirmarRedirecto ('/');
}

Al ejecutar la prueba, recibimos un error de "El código de estado de respuesta [401] no es un código de estado de redireccionamiento". Ok, esto se debe a que la solicitud en la prueba es una solicitud json y no una solicitud estándar.

vagrant @ homestead: ~ / Code / forumio $ phpunit --filter test_guests_can_not_delete_threads
PHPUnit 6.5.5 por Sebastian Bergmann y colaboradores.

F 1/1 (100%)

Tiempo: 993 ms, Memoria: 10.00MB

Hubo 1 falla:

1) Pruebas \ Característica \ CreateThreadsTest :: test_guests_can_not_delete_threads
El código de estado de respuesta [401] no es un código de estado de redireccionamiento.
No se pudo afirmar que falso es verdadero.

/home/vagrant/Code/forumio/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestResponse.php:93
/home/vagrant/Code/forumio/tests/Feature/CreateThreadsTest.php:61

FALLOS!
Pruebas: 1, Afirmaciones: 1, Fallos: 1.

Para solucionar esto, vamos a actualizar la prueba así:

función pública test_guests_can_not_delete_threads ()
{
    $ thread = create ('App \ Thread');

    $ respuesta = $ this-> delete ($ thread-> path ());

    $ respuesta-> afirmarRedirecto ('/ login');
}

Ejecute la prueba, vea cómo se pasa y asegúrese de que los invitados no puedan eliminar un hilo que no deberían poder. Agradable.
ejemplo de prueba de filtro phpunit


Configurar un enlace para eliminar un modelo

La plomería está en su lugar para que los hilos se eliminen, sin embargo, la interfaz de usuario necesita un enlace o botón real en el que el usuario pueda hacer clic para enviar la solicitud de eliminación al servidor. Podemos agregar esto fácilmente en threads / show.blade.php. Arreglaremos algunas cosas para manejar el diseño correctamente, pero la marca clave está resaltada.

Hay un par de cosas a tener en cuenta aquí. Esto es en realidad un formulario, que envía una solicitud de publicación al punto final del hilo en cuestión. El estilo del botón simplemente lo hace ver como un enlace en el navegador. Como estamos tratando con el envío de un formulario, debemos incluir la llamada a csrf_field () para generar un token de falsificación de solicitud entre sitios para proteger la sesión. También puede notar la llamada a method_field ('DELETE'). Esto es para informar a Laravel que la intención es eliminar algo del servidor.


Redireccionando al borrar

Una última cosa que queremos configurar es redirigir al usuario a algún lugar después de eliminar un hilo. En este caso redirigiremos a la página principal de hilos. Actualicemos el método destroy () en ThreadsController así:


Preparándose para eliminar un hilo

eliminar ejemplo de enlace de modelo


Redirección exitosa después de eliminar el modelo

redirigir después de eliminar el modelo


Cómo eliminar un registro del resumen de la base de datos

Llegamos a todos los temas que necesitábamos cubrir en este tutorial con respecto a la configuración de un usuario para eliminar un hilo de la base de datos. Desde la creación de las pruebas de soporte hasta la creación del enlace para enviar la solicitud de eliminación desde la interfaz de usuario, lo cubrimos. Agradable.