Platzi
Platzi

LA EDUCACIÓN ES UN REGALO ¡ACCEDE AL PRECIO ESPECIAL!

Antes: $249
$149
Currency
Antes: $249
Ahorras: $100
COMIENZA AHORA
Termina en: 17D : 18H : 2M : 17S

Laravel y Base de Datos

Entorno de trabajo y repaso de Laravel

1

Qué aprenderás sobre Laravel Avanzado

2

Repaso de Laravel y requisitos del curso

3

Configuración de la base de datos-SQLite en Laravel

4

Instalación, configuración y uso de Homestead

5

Instalar Laravel Sanctum

6

API de autenticación: laravel UI y laravel sanctum

Manejo de tu base de datos con Laravel

7

Capa de transformación con API Resources

8

Manejo de relaciones en bases de datos con Laravel

9

Relaciones Polimórficas en Eloquent

La terminal de Laravel

10

Cómo crear comandos para la terminal de Laravel

11

Ejecutando comandos desde la API

12

Programación de tareas

Eventos y tareas de Laravel

13

Eventos y Listeners en Laravel

14

Eventos de Eloquent

15

Introducción al uso de Queues y Jobs

16

Cómo disparar eventos en Queues

17

Laravel Horizon

Manejo de errores

18

Cómo capturar y leer errores con la clase Handler

19

Excepciones personalizadas

20

Excepciones HTTP personalizadas y debugging con Laravel Telescope

21

Configuración de logs y channels en Laravel

El corazón de Laravel

22

Ciclo de vida de una aplicación en Laravel

23

¿Qué son los service containers?

24

¿Cómo funciona un service container?

25

Registro y carga de clases con service providers

Creación de paquetes

26

¿Cómo crear mis propios paquetes de Laravel?

27

Propiedades para manejo de dependencias

28

Comprende el archivo composer.json

29

Extendiendo composer.json, autocarga de clases y PSR-4

30

Crear mis propios Services Providers

31

Publicación de archivos

32

Uso de repositorios locales

33

Publicación de paquetes en packagist

Configuración de la base de datos-SQLite en Laravel

3/33
Recursos

Aportes 48

Preguntas 6

Ordenar por:

Los aportes, preguntas y respuestas son vitales para aprender en comunidad. Regístrate o inicia sesión para participar.

Para los que usen Visual Studio Code, existe una extensión llamada SQLite, que nos permite visualizar la base de datos y ejecutar queries desde el editor.

Estoy usando Laravel v8.4 y el factory y seed son un poco diferentes, deben hacerlo así:

ProductFactory.php

    public function definition()
    {
        return [
            'name' => $this->faker->name,
            'price' => $this->faker->numberBetween(10000, 60000)
        ];
    }

ProductSeeder.php

    public function run()
    {
        \App\Models\Product::factory(10)->create();
    }

Para ejecutar los tests, para aquellos que no tengan phpstorm, lo pueden ejecutar desde la consola en la raíz del proyecto con el comando:

php artisan test

O también pueden ejecutar directamente php unit con el siguiente comando:

vendor/bin/phpunit

Además si quieren ver mejor la salid de esta forma, pueden agregar el parámetro --testdox

vendor/bin/phpunit --testdox

Licencia gratuita por un año de php storm para estudiantes.
https://www.jetbrains.com/es-es/community/education/#students
Licencia gratuita por un año de navicat(magnifico gestor de bases de datos) para estudiantes.
https://www.navicat.com/es/sponsorship/education/student.html

En el método test_update_product del ProductControllerTest me salía el siguiente error:

“1) Tests\Feature\ProductControllerTest::test_update_product
Header [content-type] was found, but value [text/html; charset=UTF-8] does not match [application/json].
Failed asserting that two strings are equal.”

Se soluciona agregando los headers directamente en la función de jsonPatch y no en una línea extra como en el ejemplo:

-------------------------------------------- ANTES -----------------------------------------------------
$response = $this->patchJson("/api/products/{$product->getKey()}", $data);
$response->assertHeader(‘content-type’, ‘application/json’);
$response->assertSuccessful();

------------------------------------------- DESPUÉS ----------------------------------------------------
$response = $this->patchJson("/api/products/{$product->getKey()}", $data, [‘content-type’, ‘application/json’]);
$response->assertSuccessful();

Aqui la clase para hacer el test con los metodos, me tome la libertad de hacer algunos ligeros cambios para hacer mas comodo el test y en algunos metodo solo cambie la forma de traer el response para fines ilustrativos:

<?php

namespace Tests\Feature;

use App\Product;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;

class APIProductControllerTest extends TestCase
{
    use RefreshDatabase;

    const API_HEADER_NAME = 'content-type';
    const API_HEADER_VALUE = 'application/json';

    protected $data = [
        'name' => 'Product one',
        'price' => 1000
    ];

    public function setUp(): void
    {
        parent::setUp(); // TODO: Change the autogenerated stub
    }

    /**
     * A basic feature test example.
     *
     * @test
     */
    public function test_index()
    {
        factory(Product::class)->times(5)->create();
        $response = $this->json('get', '/api/products/');
        $response->assertSuccessful();
        $response->assertHeader(self::API_HEADER_NAME, self::API_HEADER_VALUE);
        $response->assertJsonCount(5);
    }

    /** @test */
    public function test_create_new_product()
    {
        $response = $this->json('post', '/api/products', $this->data);
        $response->assertSuccessful();
        $response->assertHeader(self::API_HEADER_NAME, self::API_HEADER_VALUE);
        $this->assertDatabaseCount('products', 1);
    }

    /**@test */
    public function test_update_product()
    {
        $product = factory(Product::class)->create();
        $response = $this->patchJson("/api/products/{$product->getKey()}", $this->data);
        $response->assertSuccessful();
//        $response->assertHeader(self::API_HEADER_NAME, self::API_HEADER_VALUE);
        $this->assertEquals($this->data['name'], Product::first()->name);
    }

    /**@test */
    public function test_show_product()
    {
        $product = factory(Product::class)->create();
        $response = $this->getJson(route('products.show', $product));
        $response->assertSuccessful();
        $response->assertHeader(self::API_HEADER_NAME, self::API_HEADER_VALUE);
        $this->assertEquals($product->name, $response->json('name'));
    }

    /**@test */
    public function test_delete_product()
    {
        $product = factory(Product::class)->create();
        $response = $this->deleteJson(route('products.destroy', $product));
        $response->assertSuccessful();
        $response->assertHeader(self::API_HEADER_NAME, self::API_HEADER_VALUE);
        $this->assertDatabaseCount('products', 0);
    }

En Laravel 8, los models factories cambian, ahí se debe usar:

Product::factory(5)->create()

Y para usar faker en un archivo de Factory debes accederlo mediante $this : $this->faker->name

Les dejo los archivos completos de esta clase en este commit:

https://github.com/RetaxMaster/platzi-api/commit/01c746ab1cfae7eec24f668009d38b0d05d9362c

Código del test en Laravel 8

<?php

namespace Tests\Feature;

use App\Models\Product;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class ProductControllerTest extends TestCase
{
    use RefreshDatabase;

    protected function setUp(): void
    {
        parent::setUp();
    }

    public function test_index()
    {
        $product = Product::factory()->count(5)->create();

        $response = $this->json('GET', '/api/products');

        $response
            ->assertSuccessful()
            ->assertHeader('content-type', 'application/json')
            ->assertJsonCount(5);
    }

    public function test_create_new_product()
    {
        $data = [
            'name' => 'Hola',
            'price' => 1000,
        ];
        $response = $this->json('POST', '/api/products', $data);

        $response
            ->assertSuccessful()
            ->assertHeader('content-type', 'application/json');

        $this->assertDatabaseHas('products', $data);
    }

    public function test_update_product()
    {
        /** @var Product $product */
        $product = Product::factory()->create();

        $data = [
            'name' => 'Update Product',
            'price' => 20000,
        ];

        $response = $this->json('PATCH', "/api/products/{$product->getKey()}", $data);

        $response
            ->assertSuccessful()
            ->assertHeader('content-type', 'application/json');
    }

    public function test_show_product()
    {
        /** @var Product $product */
        $product = Product::factory()->create();;

        $response = $this->json('GET', "/api/products/{$product->getKey()}");

        $response
            ->assertSuccessful()
            ->assertHeader('content-type', 'application/json');
    }

    public function test_delete_product()
    {
        /** @var Product $product */
        $product = Product::factory()->create();

        $response = $this->deleteJson("/api/products/{$product->getKey()}");

        $response
            ->assertSuccessful()
            ->assertHeader('content-type', 'application/json');

        $this->assertDeleted($product);
    }
}

Usando Laravel 8, el sistema de rutas tambien varia, por lo que en nuestro archivo routes/api.php quedaria asi:

use App\Http\Controllers\ProductController;
use App\Http\Controllers\CategoryController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/

Route::middleware('auth:api')->get('/user', function (Request $request) {
    return $request->user();
});

Route::resource('products', ProductController::class);

Route::resource('categories', CategoryController::class);

que le cambia al Model el flag --api?

No supe como ejecutar los test con el debugger de Visual Studio Code y busque otra manera, si tienes el mismo problema que yo puedes utilizar el comando “php vendor/phpunit/phpunit/phpunit --filter test_update_product ProductController tests\Feature\ProductControllerTest.php” para ejecutar cada uno de los test en Windows:
php vendor/phpunit/phpunit/phpunit/ para ejectura todos los test.
Puedes especificar la clase y que método en especifico quieres ejecutar con la etiqueta --filter <método_de_la_clase> <dirección_del_<archivo>.

Si les ocurre un error en el test en el apartado “update” es porque faltó el return

public function update(Request $request, Product $product)
    {
        $product->update($request->all());

        return $product;
    }```

No está de más visitar el Repositorio oficial de faker para ver su documentación y los métodos que se pueden usar.

No se deberían usar para este curso software licenciado como lo es Php Storm, ya que todos no tienen esa posibilidad.

es facil configurarlo y me gusta sqlite

Para los que utilizan una consola de una maquina virtual como yo puede ejecutar el comando

  • php artisan test
    Para ejecutar todas las pruebas unitarias

Super repaso, todo un curso en una clase jajaja

Me encantaría conocer la razon de utilizar en el modelo el atributo $guarded en lugar de $fillable

Cual es la extensión donde permite mostrar el nombre como class/app

Me aparece este error cuando ejecuto las pruebas:
Header [content-type] was found, but value [text/html; charset=UTF-8] does not match [application/json]. Failed asserting that two strings are equal.
Si alguien sabe como solucionarlo…

A mi me daba error al migrar
Illuminate\Database\QueryException
could not find driver (SQL: PRAGMA foreign_keys = ON;)

La solución

sudo apt-get install php-sqlite3

Si alguien tiene problemas con los tests una manera sencilla de debuggear es implementando el metodo getContent:

dd(json_decode($response->getContent()));

Con esto pueden obtener la salida de su response, si alguien no tiene configurado PHPStorm puede usar tambien el comando:

php artisan test

Si alguien no tiene PHPStorm como editor puede probarlo gratis por 30 dias o si tiene un correo educativo solicitar la licencia para estudiante, si quieren saber mas de esta herramienta tambien les recomiendo en youtube la playlist de PHPStorm de Christopher Rumpel.

.env es donde estan nuestros valores de entorno

php artisan r:l es el shortcut de php artisan route:list y en los modelos no es muy recomendable usar la propiedad de $guarded []; ya que quedas desprotegido contra la asignación masiva, para definir que atributos se pueden asignar en masa es mejor usar protected $fillable = [‘atributo1, atributo2’];

Otra forma de visualizar datos para sqlite es usar el paquete sqlitebrowser funciona para diferentes sistemas operativos. lo puede descargar de: https://sqlitebrowser.org/dl/

Para los que usan VS code les recomiendo que instalen esta extensión https://vscode-sqltools.mteixeira.dev/

no pude instalar la extensión de sqllite en visual studio code, pero estoy usando este browser de sqlite
https://sqlitebrowser.org/blog/

A los que les da error en el test_index, no le agreguen key al assertJsonCount, ya que desde ya toma la respuesta para contar lo que trae… deberia quedar asi (Laravel 8)

public function test_index()
    {

        Product::factory(5)->create();

        $response = $this->getJson('/api/products');

        $response->assertSuccessful();
        $response->assertHeader('content-type', 'application/json');
        $response->assertJsonCount(5);
    }

Para los que quieren tener una visual mas cómoda en VScode sobre la base de datos, instalen la siguiente extensión

Name: MySQL
Id: cweijan.vscode-mysql-client2
Description: Database Client for vscode
Version: 3.9.4
Publisher: cweijan
VS Marketplace Link: https://marketplace.visualstudio.com/items?itemName=cweijan.vscode-mysql-client2

Da múltiples opciones de base de datos entre estas esta SQLite, en donde seleccionan el archivo que se crea en clases, y así ver todo su contenido igual a un gestor

Para lxs que no sepan como visualizar la base de datos de SQLite, os recomiendo que descarguéis la aplicación de DB Browser, os da una vista muy cómoda para ver la base de datos así como añadir, modificar o eliminar cualquier dato.

Recomiendo crear los modelos en una carpeta Models/ con el mismo comando y sin complicaciones para mantener el orden más adelante:

php artisan make:model Models/Product --api --all

buen profe 😃

Comando para crear un modelo con controller, factory, migrations, seeders

Por alguna razón que desconozco me estaba dando un error en la ruta del controlador. Tuve que crear la carpeta Api y dentro colocar el controlador para pasar el test.

Si alguien sabe en concreto el origen del error agradecería la ayuda.

OJO ya funciona, solo quiero saber por que me pide tener la carpeta Api dentro de Controllers

Soy yo o no dijo donde que datos tendría category

Compañeros, como siempre os dejo por aqui mi repositorio de github por si a alguien le puede servir.
https://github.com/alessandrostfr/ArgusRates

No se por que pero a mi el metodo $response->assertSuccesful() no me ha funcionado, si a alguien le ocurre yo lo solucione cambiando esa funcion por esta $response->assertStatus(200);

Pues no veo el archivo de los tests por ningún lado.

En ubuntu tenia un error sobre, sqlite no activado. lo solucione instalando sudo apt-install sqlite

Buenas me pudieran ayudar tengo el siguiente error

Header [content-type] was found, but value [text/html; charset=UTF-8] does not match [application/json]

agradecería conocer de que se trata el error

Se supone que es avanzado en php, pero si por alguna razón no sabes porque te sale 404 en el test, revisa si se genero las rutas en el Api route
Route::apiResource(‘products’, “productController”);
debe estar esta linea

Les recomiendo mejor utilizar en el archivo api.php, esta linea:

Route::apiResource('products', 'ProductController');

y cuando ejecuten el comando php artisan route:list, no van existir las rutas para la funcion de create y edit, ya que en una api no son necesarias

Para poder ver las bases de datos en Visual Studio Code se necesita instalar la extensión de SQLite y aqui en mencionan como se utiliza con todo y capturas!
https://stackoverflow.com/questions/40993895/how-to-see-a-sqlite-database-content-with-visual-studio-code
En este post de stackoverflow mencionan como se utiliza esta extension.

Si están usando Laravel 8 con Mysql como el driver de DB, recuerden des-comentar las lineas del archivo phpunit.xml para que puedan usar sqlite como base de datos de prueba.

Usando el Patron Repository
links:
links:

Hablando del migration y el price del tipo float. Esto es importante:

For Business Oriented Math, always use Decimal. The FLOAT and DOUBLE types represent approximate numeric data values. MySQL uses four bytes for single-precision values and eight bytes for double-precision values.

No dejen de leer lo siguiente: https://floating-point-gui.de/
Enjoy!

Si estan trabajando con Laravel8 los test que deja el profesor estan desactualizados, dejo el codigo modificado para funcionen las factories dentro de los test. Saludos!

<?php

namespace Tests\Feature;

use App\Models\Product;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class ProductControllerTest extends TestCase
{
    use RefreshDatabase;

    protected function setUp(): void
    {
        parent::setUp();
    }

    public function test_index()
    {
        $product = Product::factory()->count(5)->create();

        $response = $this->getJson('/api/products');

        $response->assertSuccessful();
        $response->assertHeader('content-type', 'application/json');
        $response->assertJsonCount(5);
    }

    public function test_create_new_product()
    {
        $data = [
            'name' => 'Hola',
            'price' => 1000,
        ];
        $response = $this->postJson('/api/products', $data);

        $response->assertSuccessful();
        //$response->assertHeader('content-type', 'application/json');
        $this->assertDatabaseHas('products', $data);
    }

    public function test_update_product()
    {
        /** @var Product $product */
        $product = Product::factory()->create();

        $data = [
            'name' => 'Update Product',
            'price' => 20000,
        ];

        $response = $this->patchJson("/api/products/{$product->getKey()}", $data);
        $response->assertSuccessful();
        //$response->assertHeader('content-type', 'application/json');
    }

    public function test_show_product()
    {
        /** @var Product $product */
        $product = Product::factory()->create();

        $response = $this->getJson("/api/products/{$product->getKey()}");

        $response->assertSuccessful();
        //$response->assertHeader('content-type', 'application/json');
    }

    public function test_delete_product()
    {
        /** @var Product $product */
        $product = Product::factory()->create();

        $response = $this->deleteJson("/api/products/{$product->getKey()}");

        $response->assertSuccessful();
        //$response->assertHeader('content-type', 'application/json');
        $this->assertDeleted($product);
    }

}