Inicio
Artículos
Categorias
Etiquetas
Mostrando y filtrando posts - V
publicado el: 2021-1-28   actualizado el: 2021-1-28   incluido en: Proyecto blog laravel
palabras totales: 1269   tiempo de lectura: 6 mins  

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.show.

PostController.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
    public function show(Post $post)
    {
        $similares = Post::where('category_id', $post->category_id)
                            ->where('status', 2)
                            ->where('id', '!=', $post->id)
                            ->latest('id')
                            ->take(4)
                            ->get();
        
        return view('posts.show', compact('post', 'similares'));
    }

Creo la vista laravel/blog_laravel/resources/views/posts/category.blade.php. Dentro de ella extiendo la plantilla principal muestro un listado paginado de los posts asociados a la categoría correspondiente.

 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
<x-app-layout>
    <div class=" micontainer py-8">
        <h1 class=" text-4xl font-bold text-gray-600">{{$post->name}}</h1>
        <div class=" text-lg text-gray-500 mb-2">
            {{$post->extract}}
        </div>
        <div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
            {{-- Contenido principal --}}
            <div class=" lg:col-span-2">
                <figure>
                    <img class=" w-full h-80 object-cover object-center" src="{{Storage::url($post->image->url)}}" alt="">
                </figure>
                <div class=" text-base text-gray-500 mt-4">
                    {{$post->body}}
                </div>
            </div>
            {{-- Contenido relacionado--}}
            <aside>
                <h1 class=" text-2xl font-bold text-gray-600 mb-4">Más en: {{$post->category->name}}</h1>
                <ul>
                    @foreach ($similares as $similar)
                        <li class=" mb-4">
                            <a class="flex" href="{{Route('posts.show', $similar)}}">
                                <img class=" w-40 h-20 object-cover object-center " src="{{Storage::url($similar->image->url)}}" alt="">
                                <span class=" ml-2 text-gray-600">{{$similar->name}}</span>
                            </a>
                        </li>
                    @endforeach
                </ul>
            </aside>
        </div>
    </div>
</x-app-layout>

Para poder mostrar el detalle del post debo añadir la ruta al enlace de cada post en el listado de la vista resources/views/posts/index.blade.php

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
<x-app-layout>

    <div class="micontainer py-8">
        <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
            @foreach ($posts as $post)
                <article class=" w-full h-80 bg-cover bg-center @if($loop->first) md:col-span-2 @endif" style="background-image: url({{Storage::url($post->image->url)}})">
                    <div class=" w-full h-full px-8 flex flex-col justify-center">
                        <div>
                            @foreach ($post->tags as $tag)
                        <a href="" class=" inline-block px-3 h-6 bg-{{$tag->color}}-600 text-white rounded-full">{{$tag->name}}</a>
                            @endforeach
                        </div>
                        <h1 class=" text-4xl text-white leading-8 font-bold">
                            {{-- Enlace al detalle del post--}}
                            <a href="{{route('posts.show', $post)}}">
                                {{$post->name}}
                            </a>
                        </h1>
                    </div>
                </article>
            @endforeach
        </div>
        <div class=" mt-4">
            {{$posts->links()}}
        </div>
    </div>
    
</x-app-layout>

Filtrando post por categorías

Creo una ruta en web.php para mostrar los post por categorías

web.php

1
Route::get('category/{category}', [PostController::class, 'category'])->name('posts.category');

Creo el método category en el controlador PostController.php al que le paso como parámetro un objeto de la clase category. Dentro de el recupero todos los posts que pertenecen a la categoría y se los paso en la variable $posts junto con la variable $category a la vista posts.category.

PostController.php

1
2
3
4
5
6
    public function category(Category $category)
    {
        $posts = Post::where('category_id', $category->id)->where('status', 2)->latest('id')->paginate(5);

        return view('posts.category', compact('posts', 'category'));
    }

Creo la vista laravel/blog_laravel/resources/views/posts/category.blade.php. Dentro de ella extiendo la plantilla principal muestro un listado paginado de los posts asociados a la categoría correspondiente.

category.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
<x-app-layout>
    <div class=" max-w-5xl mx-auto px-2 sm:px-6 lg:px-8 py-8">
        <h1 class=" uppercase text-center text-3xl font-bold">Categoria: {{$category->name}}</h1>
        @foreach ($posts as $post)
            <article class="mb-8 bg-white shadow-lg rounded-lg overflow-hidden">
                <img class=" w-full h-72 object-cover object-center" src="{{Storage::url($post->image->url)}}" alt="">
                <div class="px-6 py-4">
                    <h1 class=" font-bold text-xl mb-2">
                        <a href="{{route('posts.show', $post)}}">{{$post->name}}</a>
                    </h1>
                    <div class=" text-gray-700 text-base">
                        {{$post->extract}}
                    </div>
                </div>
                <div class="px-6 pt-4 pb-2">
                    @foreach ($post->tags as $tag)
                        <a href="" class=" inline-block bg-gray-200 rounded-full px-3 py-1 text-sm text-gray-700 mr-2">{{$tag->name}}</a>
                    @endforeach
                </div>
            </article>            
        @endforeach
        <div class=" mb-4">
            {{$posts->links()}}
        </div>
    </div>
</x-app-layout>

Para poder acceder a la ruta debo de añadir el enlace en el menú navigation desarrollado con livewire . abro el archivo laravel/blog_laravel/resources/views/livewire/navigation.blade.phpy modifico el enlace

navigation.blade.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
.............. 
		<!-- barra de menu lg-->
          <div class="hidden sm:block sm:ml-6">
            <div class="flex space-x-4">
              @foreach ($categorias as $categoria)              
                <!-- Current: "bg-gray-900 text-white", Default: "text-gray-300 hover:bg-gray-700 hover:text-white" -->
                <!--<a href="#" class="bg-gray-900 text-white px-3 py-2 rounded-md text-sm font-medium">Dashboard</a>-->
                <a href="{{route('posts.category', $categoria)}}" class="text-gray-300 hover:bg-gray-700 hover:text-white px-3 py-2 rounded-md text-sm font-medium">{{$categoria->name}}</a>
              @endforeach
            </div>
          </div>
.....................

Para reutilizar mejor el código voy a llevar el código que utilizo para crear la tarjeta que muestra los post por categorías a un componente anónimo blade, para ello creo la carpeta resources/views/components y dentro de ella el componente resources/views/components/card-post.blade.php.

Dentro de este componente pego el código que me genera la tarjeta de cada post y que se encontraba en category.blade.php

card-post.blade.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<article class="mb-8 bg-white shadow-lg rounded-lg overflow-hidden">
    <img class=" w-full h-72 object-cover object-center" src="{{Storage::url($post->image->url)}}" alt="">
    <div class="px-6 py-4">
        <h1 class=" font-bold text-xl mb-2">
            <a href="{{route('posts.show', $post)}}">{{$post->name}}</a>
        </h1>
        <div class=" text-gray-700 text-base">
            {{$post->extract}}
        </div>
    </div>
    <div class="px-6 pt-4 pb-2">
        @foreach ($post->tags as $tag)
            <a href="" class=" inline-block bg-gray-200 rounded-full px-3 py-1 text-sm text-gray-700 mr-2">{{$tag->name}}</a>
        @endforeach
    </div>
</article> 

Llamo al componente creado <x-card-post :post="$post"/> desde la vista resources/views/posts/category.blade.php

category.blade.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<x-app-layout>
    <div class=" max-w-5xl mx-auto px-2 sm:px-6 lg:px-8 py-8">
        <h1 class=" uppercase text-center text-3xl font-bold">Categoria: {{$category->name}}</h1>
        @foreach ($posts as $post)
            <x-card-post :post="$post"/>           
        @endforeach
        <div class=" mb-4">
            {{$posts->links()}}
        </div>
    </div>
</x-app-layout>

Y lo recibo en el componente card-post.blade.php utilizando la directiva de blade @props(['post']).

card-post.blade.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
@props(['post'])

<article class="mb-8 bg-white shadow-lg rounded-lg overflow-hidden">
    <img class=" w-full h-72 object-cover object-center" src="{{Storage::url($post->image->url)}}" alt="">
    <div class="px-6 py-4">
        <h1 class=" font-bold text-xl mb-2">
            <a href="{{route('posts.show', $post)}}">{{$post->name}}</a>
        </h1>
        <div class=" text-gray-700 text-base">
            {{$post->extract}}
        </div>
    </div>
    <div class="px-6 pt-4 pb-2">
        @foreach ($post->tags as $tag)
            <a href="" class=" inline-block bg-gray-200 rounded-full px-3 py-1 text-sm text-gray-700 mr-2">{{$tag->name}}</a>
        @endforeach
    </div>
</article> 

Ahora ya puedo aplicar este componente anónimo de blade a la plantilla que me muestre los post por etiquetas.

Filtrando post por etiquetas

Lo primero es crear una ruta en web.php

web.php

1
Route::get('tag/{tag}', [PostController::class, 'tag'])->name('posts.tag');

Luego creo el método tag en el controlador PostController.php al que paso como parámetro un objeto tipo tag . Dentro de el recupero coleccion de post publicados que tienen la etiqueta pasada por parametro. Por ultimo devuelvo la vista tag.blade.php a la que paso las variables $posts y $tag.

PostController.php

1
2
3
4
5
6
    public function tag(Tag $tag)
    {
        $posts = $tag->posts()->where('status', 2)->latest('id')->paginate(5);

        return view('posts.tag', compact('posts', 'tag'));
    }

Creo la lista resources/views/posts/tag.blade.php dentro de la cual extiendo la plantilla principal del proyecto y muestro los posts ayudándome del componente anónimo de blade recién creado para mostrar tarjetas <x-card-post :post="$post"/>

tag.blade.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<x-app-layout>
    <div class=" max-w-5xl mx-auto px-2 sm:px-6 lg:px-8 py-8">
        <h1 class=" uppercase text-center text-3xl font-bold">Etiqueta: {{$tag->name}}</h1>
        @foreach ($posts as $post)
            <x-card-post :post="$post"/>           
        @endforeach
        <div class=" mb-4">
            {{$posts->links()}}
        </div>
    </div>
</x-app-layout>

Para completar este filtrado debo añadir las rutas a los enlaces en las vistas index.blade.phpy car-post.blade.php

card-post.blade.php

1
2
3
4
5
<div class="px-6 pt-4 pb-2">
        @foreach ($post->tags as $tag)
            <a href="{{route('posts.tag', $tag)}}" class=" inline-block bg-gray-200 rounded-full px-3 py-1 text-sm text-gray-700 mr-2">{{$tag->name}}</a>
        @endforeach
</div>

index.blade.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
          ..............................
			@foreach ($posts as $post)
                <article class=" w-full h-80 bg-cover bg-center @if($loop->first) md:col-span-2 @endif" style="background-image: url({{Storage::url($post->image->url)}})">
                    <div class=" w-full h-full px-8 flex flex-col justify-center">
                        <div>
                            @foreach ($post->tags as $tag)
                        <a href="{{route('posts.tag', $tag)}}" class=" inline-block px-3 h-6 bg-{{$tag->color}}-600 text-white rounded-full">{{$tag->name}}</a>
                            @endforeach
                        </div>
                        <h1 class=" text-4xl text-white leading-8 font-bold pt-2">
                            <a href="{{route('posts.show', $post)}}">
                                {{$post->name}}
                            </a>
                        </h1>
                    </div>
                </article>
            @endforeach
..................................
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 crud de categorías - VII
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.
2021-1-30
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
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