Tutorial de Laravel CRUD (Crear, leer, actualizar y eliminar)

requisitos previos

  • Familiarizado con PHP (Laravel está basado en PHP).
  • Algunos conocimientos de MySQL.
  • Una comprensión básica de Laravel MVC .

Consulte mi tutorial anterior sobre cómo instalar y configurar nuestro entorno local con todas las herramientas que necesitaremos para este ejercicio. Recuerda agregar un nuevo proyecto de Laravel usando Composer en nuestra carpeta htdocs.

composer create-project  --prefer-dist  laravel/laravel laravel-crud

Agregando y configurando nuestra Base de Datos

Agregar una nueva base de datos MySQL se hace fácilmente con Xampp.
Simplemente ingrese a PHPMyAdmin en localhost/phpmyadmin/ y cree una nueva base de datos usando la opción "Nuevo". Vamos a nombrarlo acciones para este tutorial, pero puede usar cualquier nombre que desee.

Ahora abra el archivo .env en la raíz de su proyecto y configure la información de la base de datos.

.env
8
9
10
11
12
13
14
15
...
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=stocks
DB_USERNAME=root
DB_PASSWORD=
...

De forma predeterminada, MySQL de Xampp utiliza un usuario raíz con una contraseña vacía. Obviamente, esta no es una buena práctica para proyectos reales, pero es perfecta para un tutorial rápido como este.

Creando nuestro modelo

Usemos Artisan para crear nuestro primer modelo.

php artisan make:model Stock --migration

Esto creará un modelo y un archivo de migración.

Vaya a base de datos/migraciones y abra el nuevo xxxxxxx_create_stocks_table.php. Necesitamos modificar este archivo para agregar nuestra estructura de tabla.

xxxxxxx_create_stocks_table.php
13
14
15
dieciséis
17
18
19
20
21
22
23
24
...   
public function up()
    {
        Schema::create('stocks', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->timestamps();
            $table->string('stock_name');
            $table->string('ticket');
            $table->decimal('value', 8, 2);           
        });
    }
...

Observe los campos resaltados que agregamos a la tabla.

Ahora podemos correr,

php artisan migrate

para agregar nuestras tablas a la base de datos de Acciones.

Vaya a la carpeta de la aplicación y actualice Stock.php.

Stock.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
 
namespace App;
 
use Illuminate\Database\Eloquent\Model;
 
class Stock extends Model
{
    protected $fillable = [
        'stock_name',
        'ticket',
        'value'       
    ];
}

Adición de controlador y enrutamiento

Estamos listos para crear nuestro Controlador ejecutando

php artisan make:controller StockController --resource

Esto agregará StockController.php en app/Http/Controllers/ . Puede echar un vistazo a este archivo que ya contiene algunos métodos predefinidos vacíos, pero los actualizaremos pronto.

Primero, abra rutas/web.php y agregue algo de código.

web.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
dieciséis
17
18
<?php
 
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
 
Route::get('/', function () {
    return view('welcome');
});
 
Route::resource('stocks', 'StockController');

El uso de resource() en la ruta asignará automáticamente los siguientes métodos en el controlador.

  • GET /stocks , asignado al método denominado index() .
  • GET /stocks/create , asignado a create() .
  • GET /stocks/{stock} , asignado a show() .
  • GET /stocks/{stock}/edit , asignado a edit() .
  • POST /stocks , asignado a store() .
  • PUT /stocks/{stock} , asignado a update() .
  • DELETE /stocks/{stock} , mapeado para destroy() .

 

Actualización del controlador

Así es como se ve StockController.php con todos los métodos completados.

StockController.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
dieciséis
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
sesenta y cinco
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
<?php
 
namespace App\Http\Controllers;
 
use Illuminate\Http\Request;
use App\Stock;
 
class StockController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $stocks = Stock::all();
 
        return view('stocks.index', compact('stocks')); // -> resources/views/stocks/index.blade.php
    }
 
    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        return view('stocks.create'); // -> resources/views/stocks/create.blade.php
    }
 
    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        // Validation for required fields (and using some regex to validate our numeric value)
        $request->validate([
            'stock_name'=>'required',
            'ticket'=>'required',
            'value'=>'required|max:10|regex:/^-?[0-9]+(?:\.[0-9]{1,2})?$/'
        ]);
        // Getting values from the blade template form
        $stock = new Stock([
            'stock_name' => $request->get('stock_name'),
            'ticket' => $request->get('ticket'),
            'value' => $request->get('value')
        ]);
        $stock->save();
        return redirect('/stocks')->with('success', 'Stock saved.');   // -> resources/views/stocks/index.blade.php
    }
 
    /**
     * Display the specified resource. We don't need this one for this tutorial.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        //
    }
 
    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        $stock = Stock::find($id);
        return view('stocks.edit', compact('stock'));  // -> resources/views/stocks/edit.blade.php
    }
 
    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
        // Validation for required fields (and using some regex to validate our numeric value)
        $request->validate([
            'stock_name'=>'required',
            'ticket'=>'required',
            'value'=>'required|max:10|regex:/^-?[0-9]+(?:\.[0-9]{1,2})?$/'
        ]);
        $stock = Stock::find($id);
        // Getting values from the blade template form
        $stock->stock_name =  $request->get('stock_name');
        $stock->ticket = $request->get('ticket');
        $stock->value = $request->get('value');
        $stock->save();
 
        return redirect('/stocks')->with('success', 'Stock updated.'); // -> resources/views/stocks/index.blade.php
    }
 
    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        $stock = Stock::find($id);
        $stock->delete(); // Easy right?
 
        return redirect('/stocks')->with('success', 'Stock removed.');  // -> resources/views/stocks/index.blade.php
    }
}

Como puede ver, agregué algunos comentarios con referencias a todas las vistas que vamos a necesitar. Vamos a crearlos en el siguiente paso.

Creación de vistas (también conocido como "casi llegamos")

Primero necesitamos agregar resources/views/base.blade.php . Bootstrap ya está incluido, por lo que podemos usar su cuadrícula y estilos predefinidos.

Esta va a ser nuestra plantilla principal muy básica.

base.blade.php
1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html lang="en">
<head>
  <title>Laravel CRUD Tutorial</title>
  <link href="{{ asset('css/app.css') }}" rel="stylesheet" type="text/css" />
</head>
<body>
  <div class="container">
    @yield('main')
  </div>
  <script src="{{ asset('js/app.js') }}" type="text/js"></script>
</body>
</html>

Ahora agregue una carpeta para las vistas de acciones denominadas (sorpresa, sorpresa) acciones.
Agregue un nuevo archivo blade como este: resources/views/stocks/index.blade.php.

índice.blade.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
dieciséis
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
@extends('base')
 
@section('main')
<div class="row">
<div class="col-sm-12">
    <h1 class="display-3">Stocks</h1>
    <div>
    <a href="{{ route('stocks.create')}}" class="btn btn-primary mb-3">Add Stock</a>
    </div>    
    @if(session()->get('success'))
    <div class="alert alert-success">
      {{ session()->get('success') }} 
    </div>
  @endif
  <table class="table table-striped">
    <thead>
        <tr>
          <td>ID</td>
          <td>Stock Name</td>
          <td>Stock Ticket</td>
          <td>Stock Value</td>
          <td>Updated at</td>
          <td colspan = 2>Actions</td>
        </tr>
    </thead>
    <tbody>
        @foreach($stocks as $stock)
        <tr>
            <td>{{$stock->id}}</td>
            <td>{{$stock->stock_name}} </td>
            <td>{{$stock->ticket}}</td>
            <td>{{$stock->value}}</td>
            <td>{{$stock->updated_at}}</td>
            <td>
                <a href="{{ route('stocks.edit',$stock->id)}}" class="btn btn-primary">Edit</a>
            </td>
            <td>
                <form action="{{ route('stocks.destroy', $stock->id)}}" method="post">
                  @csrf
                  @method('DELETE')
                  <button class="btn btn-danger" type="submit">Delete</button>
                </form>
            </td>
        </tr>
        @endforeach
    </tbody>
  </table>
<div>
</div>
@endsection

Esta será nuestra plantilla de listado que muestra todos los datos y acciones de las acciones. Cuando tenga algunos datos, se verá similar a la siguiente imagen.

Ahora, solo necesitamos crear un par de plantillas de hoja más para agregar y editar nuestros registros.

Agregue la plantilla de creación de stock: resources/views/stocks/create.blade.php

crear.blade.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
dieciséis
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
@extends('base')
 
@section('main')
<div class="row">
 <div class="col-sm-8 offset-sm-2">
    <h1 class="display-3">Add Stock</h1>
  <div>
    @if ($errors->any())
      <div class="alert alert-danger">
        <ul>
            @foreach ($errors->all() as $error)
              <li>{{ $error }}</li>
            @endforeach
        </ul>
      </div><br />
    @endif
      <form method="post" action="{{ route('stocks.store') }}">
          @csrf
          <div class="form-group">   
              <label for="stock_name">Stock Name:*</label>
              <input type="text" class="form-control" name="stock_name"/>
          </div>
 
          <div class="form-group">
              <label for="ticket">Stock Ticket:*</label>
              <input type="text" class="form-control" name="ticket"/>
          </div>
 
          <div class="form-group">
              <label for="value">Stock Value:</label>
              <input type="text" class="form-control" name="value"/>
          </div>
          <button type="submit" class="btn btn-primary">Add Stock</button>
      </form>
  </div>
</div>
</div>
@endsection

Agregue finalmente la plantilla de stock de edición: resources/views/stocks/edit.blade.php

editar.blade.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
dieciséis
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
@extends('base')
@section('main')
<div class="row">
    <div class="col-sm-8 offset-sm-2">
        <h1 class="display-3">Editing Stock</h1>
 
        @if ($errors->any())
        <div class="alert alert-danger">
            <ul>
                @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
                @endforeach
            </ul>
        </div>
        <br />
        @endif
        <form method="post" action="{{ route('stocks.update', $stock->id) }}">
            @method('PATCH')
            @csrf
            <div class="form-group">
 
                <label for="stock_name">Stock Name:*</label>
                <input type="text" class="form-control" name="stock_name" value="{{ $stock->stock_name }}" />
            </div>
 
            <div class="form-group">
                <label for="ticket">Stock Ticket:*</label>
                <input type="text" class="form-control" name="ticket" value="{{ $stock->ticket }}" />
            </div>
 
            <div class="form-group">
                <label for="value">Stock Value:</label>
                <input type="text" class="form-control" name="value" value="{{ $stock->value }}" />
            </div>
            <button type="submit" class="btn btn-primary">Update</button>
        </form>
    </div>
</div>
@endsection

Continúe y pruebe su aplicación.

En los próximos tutoriales, aprenderemos cómo importar datos desde una API de servicios financieros para actualizar automáticamente los valores de nuestras acciones.