Inicio
Artículos
Categorias
Etiquetas
Creando el crud de categorías - VII
publicado el: 2021-1-30   actualizado el: 2021-1-30   incluido en: Proyecto blog laravel
palabras totales: 3208   tiempo de lectura: 16 mins  

Creando un crud para las categorías del blog

Genero en admin.php una ruta de tipo resources que me genere las rutas para el crud de las categorías. Antes creo un controlador para categorías que me genere ya los 7 métodos.

1
2
enrique@enrique-server:/var/www/laravel/blog_laravel$ php artisan make:controller Admin/CategoryController -r
Controller created successfully.

CategoryController.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;

class CategoryController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        //
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        //
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        //
    }

    /**
     * Display the specified resource.
     *
     * @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)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        //
    }
}

Dentro del archivo admin.php creo la ruta de tipo resources para categorías se la asigno al controlador CategoryController y le digo que los nombres de las rutas comiencen por admin.categories.

1
2
3
4
5
6
7
use App\Http\Controllers\Admin\CategoryController;
use App\Http\Controllers\Admin\HomeController;

use Illuminate\Support\Facades\Route;

Route::get('', [HomeController::class, 'index'])->name('admin.home');
Route::resource('categories', CategoryController::class)->names('admin.categories');

Si observo las rutas creadas veo que los parámetros que pasamos son de tipo categoy (en singular)

Esto no coincide con los parámetros que pasamos en los métodos del controlador. Los cambio en el controlador para que sean objetos de tipo Category, y añado las vistas que quiero que muestren los metodos index, show, edit y create

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\Category;
use Illuminate\Http\Request;

class CategoryController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        return view('admin.categories.index');
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        return view('admin.categories.create');
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        //
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show(Category $category)
    {
        return view('admin.categories.show', compact('category'));
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit(Category $category)
    {
        return view('admin.categories.edit', compact('category'));
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, Category $category)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy(Category $category)
    {
        //
    }
}

Creo las vistas de dichos métodos (index, show, edit y create) resources/views/admin/categories/index.blade.php, resources/views/admin/categories/show.blade.php, resources/views/admin/categories/edit.blade.php y resources/views/admin/categories/create.blade.php y extiendo la plantilla adminLTE a cada una de ellas. Por ejemplo:

create.blade.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
@extends('adminlte::page')

@section('title', 'Blog con Laravel')

@section('content_header')
    <h1>Crear categoría</h1>
@stop

@section('content')
    <p>Aqui va un formulario para Crear categoria.</p>
@stop

@section('css')
    <link rel="stylesheet" href="/css/admin_custom.css">
@stop

@section('js')
    <script> console.log('Hi!'); </script>
@stop

Quiero empezar mostrando el listado de las categorías en una tabla. Para ello modifico la plantilla resources/views/admin/categories/index.blade.php y el método index del controlador CategoryController.php.

método index de CategoryController.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $categories = Category::all();
        
        return view('admin.categories.index', compact('categories'));
    }

index.blade.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
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
@extends('adminlte::page')

@section('title', 'Blog con Laravel')

@section('content_header')
    <h1>Lista de categorías.</h1>
@stop

@section('content')
    <p>Aqui aparece un listado de categorías</p>
    <div class="card">
        <div class="card-header">
            <a class=" btn btn-secondary float-right" href="{{route('admin.categories.create')}}">Crear Categoría</a>
        </div>
        <div class="card-body">

            <table class=" table table-striped">
                <thead>
                    <tr>
                        <th>Id</th>
                        <th>Nombre</th>
                        <th colspan="2"></th>
                    </tr>
                </thead>
                <tbody>
                    @foreach ($categories as $category)
                    <tr>
                        <th>{{$category->id}}</th>
                        <th>{{$category->name}}</th>
                        <th width="10px"><a class=" btn btn-primary btn-sm" href="{{route('admin.categories.edit', $category)}}">Editar</a></th>
                        <th width="10px">
                            <form action="{{route('admin.categories.destroy', $category)}}" method="POST">
                                @csrf
                                @method('delete')
                                <button class="btn btn-danger btn-sm" type="submit">Eliminar</button>
                            </form>
                        </th>
                    </tr>
                @endforeach
                </tbody>
            </table>
        </div>
    </div>
@stop

@section('css')
    <link rel="stylesheet" href="/css/admin_custom.css">
@stop

@section('js')
  
@stop

En esta vista he creado una tabla dentro de la que listo las categorías por su id y su nombre. Le añado a cada una un botón para editarla que me dirige a ala vista edit.blade.php y otro botón mediante un formulario que me permite utilizar la ruta admin.categories.destroy y el método destroy del controlador. Este formulario lo envío usando el método delete que recomienda laravel para lo cual debo incluir @method('delete')en el formulario.

También he creado un botón para crear una nueva categoría que me redirige mediante la ruta admmin.categories.create a la vista create.blade.php donde un formulario me permite crear una nueva categoría. La vista index.blade.php se ve así.

Para crear los formularios del blog me voy a ayudar de un componente de laravel llamado laravelcollective cuyo sitio web me indica en su sección docs que para poder usar el paquete debo usando composer desde la linea de comandos y escribir el siguiente comando:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
enrique@enrique-server:/var/www/laravel/blog_laravel$ composer require laravelcollective/html
Using version ^6.2 for laravelcollective/html
./composer.json has been updated
Running composer update laravelcollective/html
Loading composer repositories with package information
Updating dependencies
Lock file operations: 1 install, 0 updates, 0 removals
  - Locking laravelcollective/html (v6.2.1)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
  - Downloading laravelcollective/html (v6.2.1)
  - Installing laravelcollective/html (v6.2.1): Extracting archive
Generating optimized autoload files
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover --ansi
Discovered Package: facade/ignition
Discovered Package: fideloper/proxy
Discovered Package: fruitcake/laravel-cors
Discovered Package: jenssegers/agent
Discovered Package: jeroennoten/laravel-adminlte
Discovered Package: laravel/fortify
Discovered Package: laravel/jetstream
Discovered Package: laravel/sail
Discovered Package: laravel/sanctum
Discovered Package: laravel/tinker
Discovered Package: laravelcollective/html
Discovered Package: livewire/livewire
Discovered Package: nesbot/carbon
Discovered Package: nunomaduro/collision
Package manifest generated successfully.
75 packages you are using are looking for funding.
Use the `composer fund` command to find out more!

Ahora ya puedo ir a resources/views/admin/categories/create.blade.php y crear el formulario.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@extends('adminlte::page')

@section('title', 'Blog con Laravel')

@section('content_header')
    <h1>Crear categoría</h1>
@stop

@section('content')
    <p>Aqui va un formulario para Crear categoria.</p>
    <div class="card">
        <div class="card-body">
            {!! Form::open(['route' => 'admin.categories.store']) !!}
                <div class="form-group">
                    {!! Form::label('name', 'Nombre') !!}
                    {!! Form::text('name', null, ['class' => 'form-control', 'placeholder' => 'ingresa el nombre de la categoria']) !!}
                </div>
                <div class="form-group">
                    {!! Form::label('slug', 'Slug') !!}
                    {!! Form::text('slug', null, ['class' => 'form-control', 'placeholder' => 'ingresa el slug de la categoria', 'readonly']) !!}
                </div>
                {!! Form::submit('Crear categoría', ['class' => 'btn btn-primary']) !!}
            {!! Form::close() !!}
        </div>
    </div>
@stop

Para automatizar la creación del slug voy a utilizar un pluging de JQuery, de manera que el usuario no tenga que escribir nada y evitar errores.

Lo descargo en la carpeta public/vendor desde su página web.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
enrique@enrique-server:/var/www/laravel/blog_laravel/public/vendor$ wget https://github.com/leocaseiro/jQuery-Plugin-stringToSlug/archive/1.3.zip
--2021-01-14 15:34:04--  https://github.com/leocaseiro/jQuery-Plugin-stringToSlug/archive/1.3.zip
Resolving github.com (github.com)... 140.82.121.4
Connecting to github.com (github.com)|140.82.121.4|:443... connected.
HTTP request sent, awaiting response... 302 Found
Location: https://codeload.github.com/leocaseiro/jQuery-Plugin-stringToSlug/zip/1.3 [following]
--2021-01-14 15:34:04--  https://codeload.github.com/leocaseiro/jQuery-Plugin-stringToSlug/zip/1.3
Resolving codeload.github.com (codeload.github.com)... 140.82.121.10
Connecting to codeload.github.com (codeload.github.com)|140.82.121.10|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [application/zip]
Saving to: ‘1.3.zip’

1.3.zip                                              [ <=>                                                                                                      ]  27.88K  --.-KB/s    in 0.09s   

2021-01-14 15:34:05 (312 KB/s) - ‘1.3.zip’ saved [28544]

lo descomprimo

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
enrique@enrique-server:/var/www/laravel/blog_laravel/public/vendor$ unzip 1.3.zip 
Archive:  1.3.zip
b553fe235853f0afb4fcfa2b5d08d9381a274e7e
   creating: jQuery-Plugin-stringToSlug-1.3/
  inflating: jQuery-Plugin-stringToSlug-1.3/README.md  
  inflating: jQuery-Plugin-stringToSlug-1.3/jquery.StringToSlug.jquery.json  
  inflating: jQuery-Plugin-stringToSlug-1.3/jquery.stringToSlug.js  
  inflating: jQuery-Plugin-stringToSlug-1.3/jquery.stringToSlug.min.js  
  inflating: jQuery-Plugin-stringToSlug-1.3/samples.html  
   creating: jQuery-Plugin-stringToSlug-1.3/tests/
  inflating: jQuery-Plugin-stringToSlug-1.3/tests/index.html  
  inflating: jQuery-Plugin-stringToSlug-1.3/tests/minimal-test.html  
  inflating: jQuery-Plugin-stringToSlug-1.3/tests/qunit.css  
  inflating: jQuery-Plugin-stringToSlug-1.3/tests/qunit.js  
  inflating: jQuery-Plugin-stringToSlug-1.3/tests/tests.js 

Creo una sección js debajo de la sección content y copio dos script, uno para importar el archivo jquery.stringToSlug.min.js y otra donde escribo el código que relaciona los inputs de name y slug.

create.blade.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
@extends('adminlte::page')

@section('title', 'Blog con Laravel')

@section('content_header')
    <h1>Crear categoría</h1>
@stop

@section('content')
    <p>Aqui va un formulario para Crear categoria.</p>
    <div class="card">
        <div class="card-body">
            {!! Form::open(['route' => 'admin.categories.store']) !!}
                <div class="form-group">
                    {!! Form::label('name', 'Nombre') !!}
                    {!! Form::text('name', null, ['class' => 'form-control', 'placeholder' => 'ingresa el nombre de la categoria']) !!}
                </div>
                <div class="form-group">
                    {!! Form::label('slug', 'Slug') !!}
                    {!! Form::text('slug', null, ['class' => 'form-control', 'placeholder' => 'ingresa el slug de la categoria', 'readonly']) !!}
                </div>
                {!! Form::submit('Crear categoría', ['class' => 'btn btn-primary']) !!}
            {!! Form::close() !!}
        </div>
    </div>
@stop

@section('js')
    <script src="{{asset('vendor/jQuery-Plugin-stringToSlug-1.3/jquery.stringToSlug.min.js')}}"></script>
    <script>
        $(document).ready( function() {
            $("#name").stringToSlug({
                setEvents: 'keyup keydown blur',
                getPut: '#slug',
                space: '-'
            });
        });
    </script>
@endsection

Al hacer clic en el botón de submit los datos del formulario se envían por la ruta admin.categories.storeal método store del controlador CategoryController.php. En este método valido los datos y los almaceno en la tabla categories de la base de datos. Dedo habilitar la asignación masiva en el modelo app/Models/Category.php. Para lo cual declaro la propiedad fillable dentro de la entidad Category.php.

Category.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Category extends Model
{
    use HasFactory;

    protected $fillable = ['name', 'slug']; //habilito la asignación masiva en name y slug

    // Relaccion uno a muchos posts
    public function posts()
    {
        return $this->hasMany(Post::class);
    }
}

Ambos campos son requeridos y ademas el campo slug debe de ser único en la tabla categorias.

CategoryController.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
......
    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $request->validate([
            'name' => 'required',
            'slug' => 'required|unique:categories'
        ]);

        Category::create($request->all());

        return redirect()->route('admin.categories.index');
    }
.....

Inserto los posibles errores de validación (dentro de la directiva de blade @error) de los campos name y slug en la vista

create.blade.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
..........
@section('content')
    <p>Aqui va un formulario para Crear categoría.</p>
    <div class="card">
        <div class="card-body">
            {!! Form::open(['route' => 'admin.categories.store']) !!}
                <div class="form-group">
                    {!! Form::label('name', 'Nombre') !!}
                    {!! Form::text('name', null, ['class' => 'form-control', 'placeholder' => 'ingresa el nombre de la categoria']) !!}
                    @error('name')
                        <span class=" text-danger">{{$message}}</span>
                    @enderror
                </div>
                <div class="form-group">
                    {!! Form::label('slug', 'Slug') !!}
                    {!! Form::text('slug', null, ['class' => 'form-control', 'placeholder' => 'ingresa el slug de la categoria', 'readonly']) !!}
                    @error('slug')
                        <span class=" text-danger">{{$message}}</span>
                    @enderror
                </div>
                {!! Form::submit('Crear categoría', ['class' => 'btn btn-primary']) !!}
            {!! Form::close() !!}
        </div>
    </div>
@stop
..........

Compruebo el funcionamiento del formulario para crear una categoría haciendo clic en el botón crear categoría de la lista de categorias. Aparece una vista donde puedo crear una nueva categoría.

Al rellenar el campo de nombre, se auto rellena el de slug y al hacer clic en el botón Crear categoría se validan los campos antes de crear el registro en la tabla, si hay errores en algún campo se muestran debajo de el.

Si la validación ha sido correcta, guarda el registro en la tabla categories y me redirige al listado de categorías.

Actualizar o editar un registro

Hago clic en el boton editar de una categoria cualquiera y la ruta admin.categories.edit me dirige al método edit del controllador el cual pasa a la vista edit.blade.php el objeto almacenado en la variable $category para mostrarlo en el formulario de la vista en el que se va a editar sus campos. Me baso en el formulario realizado para la vista create.blade.php y lo modifico.

edit.blade.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
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
@extends('adminlte::page')

@section('title', 'Blog con Laravel')

@section('content_header')
    <h1>Edita una categoría.</h1>
@stop

@section('content')
    <p>Editar detalle de la categoría.</p>
    <div class="card">
        <div class="card-body">
            {!! Form::model($category, ['route' => ['admin.categories.update', $category], 'method' => 'put']) !!}
                <div class="form-group">
                    {!! Form::label('name', 'Nombre') !!}
                    {!! Form::text('name', null, ['class' => 'form-control', 'placeholder' => 'ingresa el nombre de la categoría']) !!}
                    @error('name')
                        <span class=" text-danger">{{$message}}</span>
                    @enderror
                </div>
                <div class="form-group">
                    {!! Form::label('slug', 'Slug') !!}
                    {!! Form::text('slug', null, ['class' => 'form-control', 'placeholder' => 'ingresa el slug de la categoría', 'readonly']) !!}
                    @error('slug')
                        <span class=" text-danger">{{$message}}</span>
                    @enderror
                </div>
                {!! Form::submit('Actualizar categoría', ['class' => 'btn btn-primary']) !!}
            {!! Form::close() !!}
        </div>
    </div>
@stop

@section('js')
    <script src="{{asset('vendor/jQuery-Plugin-stringToSlug-1.3/jquery.stringToSlug.min.js')}}"></script>
    <script>
        $(document).ready( function() {
            $("#name").stringToSlug({
                setEvents: 'keyup keydown blur',
                getPut: '#slug',
                space: '-'
            });
        });
    </script>
@endsection

El método utilizado para enviar este formulario es el método put y la ruta debe de ser admin.categories.update a la que debo pasar como parámetro $category. Para rellenar los campos con los datos de la categoría a editar para ello cambio Form::open por Form::model y le paso la variable $category. Quedaría así: {!! Form::model($category, ['route' => ['admin.categories.update', $category], 'method' => 'put']) !!}.

Si hago clic en el botón actualizar categoría la información del formulario se envía a la ruta admin.categories.updateque es administrada por el método update del controlador CategoryController.php. En este método valido la información recibida y si pasa la validación la actualizo en la base de datos y que me redireccione a la ruta admin.categories.edit. Además quiero que ignore el slug del registro que quiero actualizar (cambio 'required|unique:categories' por "required|unique:categories,slug,$category->id" ignorando el slug de la categoría que quiero actualizar).

Por último quiero que se muestre una alerta indicando que se ha actualizado el registro con éxito. Lo condigo enviando un mensaje de sesión (with('info', 'La categoría se actualizó con éxito.')) que debo de recoger la vista admin.categories.edit.

Método update de CategoryController.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
........
	/**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, Category $category)
    {
        $request->validate([
            'name' => 'required',
            'slug' => "required|unique:categories,slug,$category->id" //ignora el slug de la categoria que quiero actualizar
        ]);

        $category->update($request->all());

        return redirect()->route('admin.categories.edit', $category)->with('info', 'La categoría se actualizó con éxito.');
    }
.........

edit.blade.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@section('content')
    <p>Editar detalle de la categoría.</p>
    @if (session('info'))
        <div class=" alert alert-success">
            <strong>{{session('info')}}</strong>
        </div>
    @endif
    <div class="card">
        <div class="card-body">
            {!! Form::model($category, ['route' => ['admin.categories.update', $category], 'method' => 'put']) !!}
                <div class="form-group">
                    {!! Form::label('name', 'Nombre') !!}
                    {!! Form::text('name', null, ['class' => 'form-control', 'placeholder' => 'ingresa el nombre de la categoría']) !!}
                    @error('name')
                        <span class=" text-danger">{{$message}}</span>
                    @enderror
                </div>
                <div class="form-group">
                    {!! Form::label('slug', 'Slug') !!}
                    {!! Form::text('slug', null, ['class' => 'form-control', 'placeholder' => 'ingresa el slug de la categoría', 'readonly']) !!}
                    @error('slug')
                        <span class=" text-danger">{{$message}}</span>
                    @enderror
                </div>
                {!! Form::submit('Actualizar categoría', ['class' => 'btn btn-primary']) !!}
            {!! Form::close() !!}
        </div>
    </div>
@stop

Esta alerta se puede crear en el método store para que se muestre en la plantilla index al crear una categoría nueva.

Eliminar una categoría

Si hago clic en el botón eliminar la información de la categoría se envía a la ruta admin.categories.destroyque es administrada por el método destroy del controlador CategoryController.php. En este método elimino el registro en la base de datos y que me redirecciona a la ruta admin.categories.index donde me muestra una alerta de borrado del registro.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy(Category $category)
    {
        $category->delete();

        return redirect()->route('admin.categories.index')->with('info-del', 'La categoría se ha eliminado con éxito');
    }

En la vista añado una condición al if para que recoja la variable de sesión infodel y muestre la alerta de borrado de la categoría.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
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
@section('content')
    <p>Aqui aparecerán las categorías</p>
    @if (session('info'))
        <div class=" alert alert-success">
            <strong>{{session('info')}}</strong>
        </div>
    @elseif(session('info-del'))
        <div class=" alert alert-danger">
            <strong>{{session('info-del')}}</strong>
        </div>
    @endif
    <div class="card">
        <div class="card-header">
            <a class=" btn btn-secondary" href="{{route('admin.categories.create')}}">Crear Categoría</a>
        </div>
        <div class="card-body">

            <table class=" table table-striped">
                <thead>
                    <tr>
                        <th>Id</th>
                        <th>Nombre</th>
                        <th colspan="2"></th>
                    </tr>
                </thead>
                <tbody>
                    @foreach ($categories as $category)
                    <tr>
                        <th>{{$category->id}}</th>
                        <th>{{$category->name}}</th>
                        <th width="10px"><a class=" btn btn-primary btn-sm" href="{{route('admin.categories.edit', $category)}}">Editar</a></th>
                        <th width="10px">
                            <form action="{{route('admin.categories.destroy', $category)}}" method="POST">
                                @csrf
                                @method('delete')
                                <button class="btn btn-danger btn-sm" type="submit">Eliminar</button>
                            </form>
                        </th>
                    </tr>
                @endforeach
                </tbody>
            </table>
        </div>
    </div>
@stop

Pantalla después de haber borrado una categoría.

URL amigables en categorías

Para que el la url no aparezca el id de la categoría sino su lug debo crear un método getRouteKeyName en el modelo app/Models/Category.php

Category.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Category extends Model
{
    use HasFactory;

    protected $fillable = ['name', 'slug'];

    public function getRouteKeyName()
    {
        return "slug";
    }
    
    // Relaccion uno a muchos posts
    public function posts()
    {
        return $this->hasMany(Post::class);
    }
}

Ahora ya muestra el slug como se puede apreciar el la siguiente imagen.

ESC
«No se puede enseñar nada a un hombre; sólo se le puede ayudar a encontrar la respuesta dentro de sí mismo». Galileo Galilei (1564 - 1642)
Tabla de contenidos
Artículos relacionados
Creando el crud de posts - IX
Creando un crud para los post del blog Creo el controlador con los siete métodos 1 2 enrique@enrique-server:/var/www/laravel/blog_laravel$ php artisan make:controller Admin/PostController -r Controller created successfully. Lo modifico para recibir objetos post y las vistas a los métodos correspondientes. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 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 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 <?
2021-2-3
Creando el crud de etiquetas - VIII
Creando un crud para las etiquetas del blog Sigo los mismos pasos que para las categorias. Desde la consola de comandos y situado dentro del proyecto creo el controlador con sus 7 métodos para administrar las etiquetas desde el backend. 1 2 enrique@enrique-server:/var/www/laravel/blog_laravel$ php artisan make:controler Admin/TagController -r Controller created successfully.
2021-1-31
Creando el backend del blog -VI
Integrando AdminLTE en el proyecto Para la gestión de la parte administrativa voy a usar el paquete AdminLTE 3 Voy a generar una url llamada admin que utilizaré para desarrollar la parte de administración del blog. Esta url no la voy a declarar en el fichero web.php sino que creo uno nuevo llamado routes/admin.
2021-1-29
Mostrando y filtrando posts - V
Mostrando el detalle de un post Creo una ruta en web.php para mostrar el detalle de un post. web.php 1 Route::get('posts/{post}', [PostController::class, 'show'])->name('posts.show'); Creo en método show en el controllador PostController.php al que le paso como parámetro un objeto post. Dentro de el recupero los post que pertenecen a la misma categoría que el en la variable $similares y se los paso junto con la variable $post a la vista posts.
2021-1-28
Crear un listado de post en la página principal - IV
Listado de posts Voy a mostrar un listado con los pos almacenados en la base de datos, para ello debo empezar creando un controlador en el que recogeré una variable con los post y desde donde llamar a una vista para mostrarlos. Creo un controlador llamado PostController. 1 enrique@enrique-server:/var/www/laravel/blog_laravel$ php artisan make:controller PostController entro en la clase app/Http/Controllers/PostController.
2021-1-28