Laravel 8 desde cero Parte VII - Agregando tema y autor a los posts
Introducción
En el anterior artículo, creamos la tabla Tema, junto con su migración y semillero fijo.
Sin embargo debemos prever la posible necesidad de crear temas adicionales, para lo cual se sigue un proceso muy similar al de la creación de Posts, como vimos en el artículo 'Laravel 8 desde cero Parte V - Proyecto Blog VIP', pero con base en el modelo de los Temas.
Modificaciones para agregar tema y autor a los posts
Primero que todo vamos al modelo 'App\Models\Post.php', y ponemos en el array fillable:
'title', 'content', 'tema', 'autor',
En la migración entre content y timestamps agregamos:
$table->string('tema');
$table->string('autor')->references('name')->on('users');
Para semilleros de los posts
Luego vamos al archivo 'Database\Factories\PostFactory,php', y agregamos:
use App\Models\Tema;
Dentro de la función definition antes de return agregamos:
$countema = Tema::count();
$tema = Tema::all();
$allusersdata = User::all();
$iduser = $this->faker->numberBetween(1, $count);
$userdata = $allusersdata->where('id', $iduser);
$username = $allusersdata->find($iduser)->name;
Y dentro de return modificamos:
'user_id' => $iduser,
Y añadimos después de content:
'tema' => $tema->find($this->faker->numberBetween(1, $countema))->nombretema,
'autor' => $username,
Para el controlador para vistas de los posts
En el archivo 'App\Http\Controllers\PostController.php' agregamos:
use App\Models\Tema;
Y reemplazamos en la función create por el siguiente código:
$temas = Tema::all();
return view('post\create', compact("temas"));
En la función store y update, después de content ($post->content = $request->input('content');), agregamos:
$post->tema = $request->input('tema');
$post->autor = $request->user()->name;
En la función edit reemplazamos por el siguiente código:
$temas = Tema::all();
return view('post\edit', compact("post"), compact("temas"));
Modificaciones en las vistas para agregar el tema en las vistas de Post
La ubicación de dichos archivos es: "Resources\Views\Post"
create.blade.php
Después de content agregamos:
<div class="form-group">
<label for="contentlbl">@lang('main.lbltemapost')</label>
<input list="temas" name="tema" value="{{ old('nombretema') }}">>
<datalist id="temas">
@foreach($temas as $tema)
<option value="{{ $tema->nombretema }}">
@endforeach
</datalist>
</div>
edit.blade.php
<div class="form-group">
<label for="contentlbl">@lang('main.lbltemapost')</label>
<input list="temas" name="tema" placeholder="{{ $post->tema }}" value="{{ $post->tema }}">
<datalist id="temas">
@foreach($temas as $tema)
<option value="{{ $tema->nombretema }}">
@endforeach
</datalist>
</div>
index.blade.php
my.blade.php
show.blade.php
<div class="card-header">{{ $post->autor }}</div>
Para redefinir las tablas con el campo tema y agregar semilleros
Eliminamos las tablas y ejecutamos:
php artisan migrate
php artisan db:seed
Creando el controlador y las vistas para la tabla tema
Para crear el controlador de los temas ejecutamos:
php artisan make:controller TemaController --resource --model=Tema
Vamos al archivo creado 'App\Http\Controllers\TemaController.php' y agregamos:
use App\Models\Post;
Redefinimos la función index así:
public function index(Request $request) {
$temas = Tema::all();
return view('tema\index', compact('temas'));
}
En create ponemos:
return view('tema\create');
En store iniciamos con:
$tema = new Tema();
$tema->nombretema = $request->input('nombretema');
$post->save();
return redirect()
->route('tema\index')
->with('message', 'lblcreado');
Y en show:
$allposts = Post::all();
$posts = $allposts->where('tema',$tema->nombretema);
return view('tema\indextema', compact('posts'));
Creamos vistas para tema Resources/Views/tema/
Resources/Views/tema/index.blade.php
@extends('layouts.compulg')
@section('title','Publicaciones por temas')
@section('mainttl')
@endsection
@section('content')
@if(Session::has('message'))
@if(Session::get('message') == 'lblcreado')
<div class="container alert alert-success">
@lang('main.lblcreado')
</div>
@else
<div class="container alert alert-success">
{{ Session::get('message') }}
</div>
@endif
@endif
<div>
<div>
@foreach($temas as $tema)
<div class="card-header">
<a href="{{route('temas.show', ['tema' => $tema])}}" class="btn">{{ $tema->nombretema }}</a>
</div><br>
@endforeach
</div>
<div>
<a href="{{route('tema/create')}}" class="btn
primary">@lang('main.lblbtncrear')</a>
</div>
</div>
@endsection
Resources/Views/tema/create.blade.php
@extends('layouts.compulg')
@section('title','Crear Tema')
@section('mainttl')
@endsection
@section('content')
@if(Session::has('message'))
<div class="container alert alert-success">
{{ Session::get('message') }}
</div>
@endif
@if($errors->any())
<div class="alert alert-danger">
<ul>
@foreach($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<form action="{{ route('temas.store') }}" method="post">
@csrf
<div>
<div>
<div class="form-group">
<label>for="contentlbl">@lang('main.lbltemapost')</label>
<input type="text" class="form-control" name="nombretembr>id="nombretema" value="{{ old('nombretema') }}">
</div>
</div>
<div>
<button class="btn btn-primary btn-blocbr>type="submit">@lang('main.lblbtnsnd')</button>
</div>
</div>
</form>
@endsection
Resources/Views/tema/indextema.blade.php
@extends('layouts.compulg')
@section('title')
@lang('main.lblttlpsts')
@endsection
@section('mainttl')
@endsection
@section('content')
@if(Session::has('message'))
<div class="container alert alert-success">
{{ Session::get('message') }}
</div>
@endif
<div>
<div>
@foreach($posts as $post)
<div class="card">
<div class="card-header">{{ $post->title }}</div>
<div class="card-body">{{ $post->content }}</div>
<div class="card-footer">{{ $post->tema }}</div>
<div class="card-header">{{ $post->autor }}</div>
</div><br>
@endforeach
</div>
</div>
@endsection
Registrando las rutas, vamos a Routes/web.php
Agregamos
use App\Http\Controllers\TemaController;
Y dentro del grupo "Route::group(['middleware' => 'verified']", agregamos:
Route::resource('temas', TemaController::class);
Route::get('/tema/index', [App\Http\Controllers\TemaController::class, 'index'])->name('tema/index');
Route::get('/tema/indextema', [App\Http\Controllers\TemaController::class, 'indextema'])->name('tema/indextema');
Route::get('/tema/create', [App\Http\Controllers\TemaController::class, 'create'])->name('tema/create');
En home.blade.php agregamos al final un acceso al índice de temas:
<a href="{{route('tema/index')}}" class="btn btn-primary btn-block">@lang('main.lbltemapost')s</a>
Aquí todo funciona bien. Sin embargo en caso de un tema duplicado, con más o menos caracteres de los permitidos o vacío, debemos validar y enviar mensajes según se necesite. Para ello necesitamos el TemaFormRequest.
Creando validaciones y mensajes de error para el formulario de creación de temas
php artisan make:request TemaFormRequest
Con esto creamos el archivo 'App\Http\Requests\TemaFormRequest.php'.
Primero en la función authorize, cambiamos false por true.
Dentro del array de rules agregamos:
'nombretema' => 'required|min:2|max:100',
Y la función:
public function messages(){
return[
'nombretema.required' => 'El tema es requerido - Title is required',
'nombretema.min' => 'El tema debe tener al menos 2 caracteres - The topic must be at least 2 characters',
'nombretema.max' => 'El tema no debe tener mas de 100 caracteres - The topic must not be more than 100 characters',
];
}
Es importante notar que utilizo generalmente dos idiomas, sin embargo para los archivos de tipo 'FormRequest', después de investigar existen varias opciones, que me parecieron un tanto complejas, por lo que desarrolle una forma propia.
Modifique la función messages, así:
public function messages(){
$locale = str_replace('_', '-', app()->getLocale());
if ($locale == 'es'){
return[
'nombretema.required' => 'El tema es requerido',
'nombretema.min' => 'El tema debe tener al menos 2 caracteres',
'nombretema.max' => 'El tema no debe tener mas de 100 caracteres',
];
} else {
return[
'nombretema.required' => 'The topic is required',
'nombretema.min' => 'The topic must be at least 2 characters',
'nombretema.max' => 'The topic must not be more than 100 characters',
];
}
}
Nota:
Al igual que en el FormRequest para temas, podemos implementar, los mensajes en PostFormRequest, para el idioma.
Luego vamos a TemaController
Agregamos:
use App\Http\Requests\TemaFormRequest;
Y en la función store modificamos así:
public function store(TemaFormRequest $request){
$temas = Tema::all();
$nametema = array();
foreach ($temas as $valuear){
array_push($nametema, $valuear->nombretema);
}
$tema = new Tema();
$tema->nombretema = $request->input('nombretema');
if (in_array($tema->nombretema, $nametema)) {
return redirect()
->route('tema/create')
->with('message', 'lblyacreado');
}
$tema->save();
return redirect()
->route('tema/index')
->with('message', 'lblcreado');
}
Observaciones:
- En el código anterior usando foreach, alimentamos un array con todos los nombretema existentes.
- Para evaluar si el tema ya está creado, de ser así, y por ser de tipo único, regresa a create con el mensaje que informa que ya existe, de lo contrario, va al index de los temas con el mensaje de creado.
Vemos resaltado en amarillo 'lblyacreado', etiqueta que agregamos en los idiomas, con el contenido en español (Resources\Lang\Es\main.php):
'lblyacreado' => 'Ya existe un registro con esos datos, y no admite duplicados',
Y en ingles (Resources\Lang\En\main.php):
'lblyacreado' => 'A record with that data already exists, and does not allow duplicates',
En la vista 'Resources\Views\Tema\create.blade.php' reemplazamos la parte correspondiente a los mensajes así:
@if(Session::has('message'))
@if(Session::get('message') == 'lblyacreado')
<div class="container alert alert-success">
@lang('main.lblyacreado')
</div>
@else
<div class="container alert alert-success">
{{ Session::get('message') }}
</div>
@endif
@endif
Observaciones:
- En este artículo se agregan campos a una tabla ya creada (posts), lo que requiere la modificación del modelo (Post) y la migración (AAAA_MM_DD_CODIGO_create_posts_table.php), de la tabla respectiva.
- Al igual que de tener un factory, este debe ser modificado, para que incluya el nuevo campo.
- Igualmente en el controlador, como en las vistas, es necesario agregar dicho campo.
- Se ha creado la tabla, el modelo y la migración para el nuevo campo, en este caso "tema" y "autor".
- Queda, si así se desea, por agregar el campo de la fecha de creación de la publicación o post.
- También creamos para el modelo "Tema" un controlador, unas vistas, al igual que las reglas y mensajes, en el caso de la creación de un nuevo tema.
- En el controlador de temas, de momento las funciones destroy, y update, no están programadas, la primera (destroy), porque debe evaluar que no haya posts o publicaciones con dicho tema, para permitir su eliminación, y la segunda (update), porque no sería conveniente cambiar el nombre de un tema, que ha sido usado por diversos usuarios, en diversas publicaciones.
- Por otra parte tenemos que tener en cuenta, que los usuarios deben tener un perfil, que incluya el roll asociado al usuario, permitiendo acceso total, regulado, o restringido, según el roll del mismo, en el anterior artículo ya creamos los roles.
En el próximo artículo veremos cómo hacerlo con el perfil del usuario.
Comentarios
Publicar un comentario