54. Crud de categorías

En este capítulo aprenderás cómo crear un CRUD de categorías en tu proyecto de Laravel. Aprenderás a crear las migraciones y modelos necesarios, definir las rutas y controladores para crear, leer, actualizar y eliminar categorías, y crear las vistas correspondientes para mostrar y validar los datos de entrada del usuario. Al final del capítulo, tendrás una comprensión completa de cómo implementar un CRUD de categorías en Laravel, lo que te permitirá crear y administrar fácilmente categorías en tu proyecto.


15 comentarios

Inicia sesión para comentar

Comentarios:

  • Manuel Medina

    Manuel Medina hace 1 año

    Hola! estoy siguiendo paso a paso el curso lo vengo haciendo bien. el problema que estoy teniendo es que cuando hago click en el logo para redirigirme a los blogs me figura el boton donde dice perfil, dashboard y cerrar sesion como con el click on, si corto el npm run dev me funciona correctamente ese boton pero veo todo mal ya que no veo los estilos de jetstream

    • Manuel Medina hace 1 año

      digo tailwind me equivoque

  • Walter

    Walter hace 1 año

    ? 10° Actualizamos el método update del controlador 

     

    Permitiendo que la validación no tenga en cuenta el propio slug para la condición unique y un mensaje de confirmación:

    	public function update(Request $request, Category $category)
    	{
    		$request->validate([
    			'name' => 'required',
    			'slug' => "required|unique:categories,slug,$category->id"
    		]);
    		$category->update($request->all());
    		
    		return redirect()->route('admin.categories.edit', $category)
    			->with('info', 'La categoría se actualizó con éxito');
    	}

     

  • Walter

    Walter hace 1 año

    ? 6° Autogeneramos los slugs

     

    ? Descargamos el plugin de jQuery stringToSlug, lo descomprimimos y copiamos la carpeta dentro de public/vendor/.

     

    ? Añadimos una nueva sección al final del archivo create.blade.php con el código JS necesario:

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

     

    • Francesc Pineda Segarra hace 1 mes

      A mi en concreto, me hace el getPut pero no me hace el slugify que se espera, y no veo motivo aparente.

      He encontrado esta alternativa, sin necesidad de tirar de código externo:

       

      <script>
          document.getElementById('name').addEventListener('keyup', (e) => {
              let slug = String(e.target.value)
                  .normalize('NFKD') // split accented characters into their base characters and diacritical marks
                  .replace(/[\u0300-\u036f]/g, '') // remove all the accents, which happen to be all in the \u03xx UNICODE block.
                  .trim() // trim leading or trailing whitespace
                  .toLowerCase()
                  .replace(/[^a-z0-9-]/g, '-')
                  .replace(/-+/g, '-')
                  .replace(/(^-|-$)/, '');
              document.getElementById('slug').value = slug;
          });
      </script>

  • Walter

    Walter hace 1 año

    ? 8° Configuramos el método store con validación

     

    	public function store(Request $request)
    	{
    		$request->validate([
    			'name' => 'required',
    			'slug' => 'required|unique:categories'
    		]);
    		$category = Category::create($request->all());
    		
    		return redirect()->route('admin.categories.edit', $category)
    			->with('info', 'La categoría se creó con éxito');
    	}

     

  • Walter

    Walter hace 1 año

    ? 7° Habilitamos la asignación masiva

     

    ? En el archivo app/Models/Category.php:

    <?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 posts(){
    		return $this->hasMany(Post::class);
    	}
    }

     

  • Walter

    Walter hace 1 año

    ? 5° Formulario de creación de nueva categoría 

     

    ? Para el formulario instalaremos el paquete Laravel Collective:

     

    composer require laravelcollective/html

    Este paquete nos permite trabajar con todas las etiquetas que utilizamos en un formulario pero le agrega de cierta lógica, por ejemplo si creamos un formulario con Laravel Collective no tendríamos que especificar el token csrf ya que L.C. se encarga de agregarlo. Tampoco tendríamos que poner el método old en los inputs para que se mantengan sus valores en caso que la validación falle. Cuando queramos editar alguna información de alguna categoría L.C. se encarga de recuperar la información de la B.D. y colocarla en los inputs.

    Donde más ventaja vamos a sacarle a L.C. es cuando trabajemos con relaciones, ya que se encarga de recuperar la información de las relaciones y colocarlos dentro de nuestros inputs y de esa manera nos evitamos escribir la lógica necesaria para poder recuperar esa información.

     

    ? Ahora configuramos la vista /resources/views/admin/categories/create.blade.php:

    @extends('adminlte::page')
    
    @section('title', 'Coders Free')
    
    @section('content_header')
    <h1>Crear nueva Categoría</h1>
    @stop
    
    @section('content')
    <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' => 'Ingrese 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 disabled',
    					'placeholder' => 'Ingrese el slug de la categoría',
    					'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

     

    • Francesc Pineda Segarra hace 1 mes

      Estoy viendo que actualmente ese repositorio lleva mucho tiempo sin actualizarse, a pesar de seguir siendo compatible con Laravel 10 sin problemas. Sólo para dejar constancia de ello, existe este otro repositorio alternativo: https://github.com/LaravelLux/html y básicamente requiere cambiar namespace y el paquete requerido para composer.

  • Walter

    Walter hace 1 año

    ? 4° Trabajamos con la vista del listado de categorías 

     

    Comenzamos con la vista /resources/views/admin/categories/index.blade.php y utilizamos clases de Bootstrap:

    @extends('adminlte::page')
    
    @section('title', 'Coders Free')
    
    @section('content_header')
    <h1>Lista de Categorías</h1>
    @stop
    
    @section('content')
    
    	@if (session('info'))
    		<div class="alert alert-success">
    			<strong>{{ session('info') }}</strong>
    		</div>
    	@endif
    	
    <div class="card">
    	<div class="card-header">
    		<a class="btn btn-secondary"
    			href="{{route('admin.categories.create')}}"
    		>Agregar categoría</a>
    	</div>
    	<div class="card-body">
    		<table class="table table-striped">
    			<thead>
    				<tr>
    					<th>Id</th>
    					<th>Name</th>
    					<th colspan="2"></th>
    				</tr>
    			</thead>
    			<tbody>
    			@foreach ($categories as $category)
    				<tr>
    					<td>{{ $category->id }}</td>
    					<td>{{ $category->name }}</td>
    					<td width="10px">
    					<a 
    					class="btn btn-primary btn-sm" 
    					href="{{route('admin.categories.edit', $category)}}"
    					>Editar</a>
    					</td>
    					<td width="10px">
    					<form 
    					action="{{route('admin.categories.destroy', $category)}}" 
    					method="POST">
    						@csrf
    						@method('delete')
    						<button type="submit" class="btn btn-danger btn-sm">
    							Eliminar
    						</button>
    					</form>
    					</td>
    				</tr>
    			@endforeach
    			</tbody>
    		</table>
    	</div>
    </div>
    @stop

     

  • Walter

    Walter hace 1 año

    ? 3° Vamos a generar las vistas que hemos indicado. 

     

    ? Creamos la carpeta resources/views/admin/categories/ y dentro de esta los archivos

    • index.blade.php
    • show.blade.php, 
    • edit.blade.php
    • create.blade.php.

     

    ? Extenderemos la plantilla AdminLTE a cada una de esas vistas.

     

  • Walter

    Walter hace 1 año

    ? 2° Generación de las 7 rutas para el CRUD

     

    ? Creamos un controlador:

    php artisan make:controller Admin/CategoryController -r

    Se crea el archivo CategoryController.php en app/Http/Controllers/Admin/.

     

    ? En el archivo routes/admin.php generamos una ruta tipo resource usando el controlador anterior:

    use App\Http\Controllers\Admin\CategoryController;
    
    Route::resource('categories', CategoryController::class)
    	->names('admin.categories');

     

    ? Consultamos las rutas generadas:

    php artisan r:l --name=admin.categories

     

    ? En los métodos del controlador cambiamos las variables $id por $category según las rutas listadas. Además importamos el modelo Category y hacemos que las variables sean instancias de este.

    <?php
    namespace App\Http\Controllers\Admin;
    
    use App\Http\Controllers\Controller;
    use Illuminate\Http\Request;
    use App\Models\Category;
    
    class CategoryController extends Controller
    {
    	public function index() {}
    	public function create() {}
    	public function store(Request $request) {}
    	public function show(Category $category) {}
    	public function edit(Category $category) {}
    	public function update(Request $request, Category $category) {}
    	public function destroy(Category $category) {}
    }

     

    ? Configuramos el método index:

    	public function index()
    	{
    		$categories = Category::all();
    		
    		return view('admin.categories.index', compact('categories'));
    	}

     

    ? Configuramos el método create:

    	public function create()
    	{
    		return view('admin.categories.create');
    	}

     

    ? Configuramos el método show:

    	public function show(Category $category)
    	{
    		return view('admin.categories.show', compact('category'));
    	}

     

    ? Configuramos el método edit:

    	public function edit(Category $category)
    	{
    		return view('admin.categories.edit', compact('category'));
    	}

     

  • Walter

    Walter hace 1 año

    ? 12° Refactorizando el modelo Category

     

    En el archivo app/Models/Category.php agregamos el método getRouteKeyName:

    	public function getRouteKeyName()
    	{
    		return "slug";
    	}

    De esta forma Laravel no tomará el id sino el slug.