How to display the posts of all users on one page - php

Here is the code I used in a user's profile page and it works fine
#foreach ($user->posts as $post)
<div class="col-4 mb-4">
<a href="{{ route('posts.show', ['post' => $post->id]) }}">
<img src="{{ asset('storage') . '/' . $post->image }}" class="w-100 h-100">
</a>
</div>
#endforeach
Now I would like to display the posts of all users on the home page
How to do ?

If you have a Post model in the controller you could something like this.
public function index()
{
$posts = Post::all();
return view('home')->with('posts', posts);
}
<ul>
#foreach($posts as $post)
<li>
<img src="{{ asset('storage') . '/' . $post->image }}" class="w-100 h-100">
</li>
#endforeach
</ul>
Hope it helps you.

If you have the relation in Post model like:
public function users()
{
return $this -> belongsToMany(User::class, 'user_posts');
}
//where 'user_posts' is your db table with foreign keys
In Controller use:
$posts=Post::with('users')->get();
Then in view:
#foreach ($posts as $post)
<div class="col-4 mb-4">
<a href="{{ route('posts.show', ['post' => $post->id]) }}">
<img src="{{ asset('storage') . '/' . $post->image }}" class="w-100 h-100">
</a>
<a href="{{ route('users.show', ['user' => $post-> user -> id]) }}">
{{ $post-> user -> name }}
</a>
</div>
#endforeach

Just call the post model in your controller like
$posts = Post::select('columns_name')->get();
compact the variable and you can use like
#forelse($posts as $post)
{{$post->id}}
#empty
No post found
#endforelse

Related

How to show image from database with eager loading?

I want to display multiple product image from database with eager loading, and when i tried to displaying it, console said localhost:8000/storage/ 404 not found. Any ideas how to solve this? this is my first time using eager loading & relationship on Laravel. Thank you!
Here is my controller :
public function homeProduct(){
$products = Product::with('productCategory')->get();
$images = Product::with('productImage')->get();
return view('home.index', compact('products', 'images'));
}
Product Model :
public function productImage()
{
return $this->hasMany(ProductImage::class, 'product_id', 'id');
}
Product Image Model :
public function product()
{
return $this->belongsTo(Product::class, 'id');
}
Here are the index.blade.php View :
#foreach ($products as $p)
<div class="col-lg-6 col-12">
<div class="portfolio-thumb mb-5" data-aos="fade-up">
<div id="yoreBeans" class="carousel slide" data-bs-ride="carousel">
<div class="carousel-inner">
#foreach ($images as $key => $image)
<div class="carousel-item {{ $key == 0 ? 'active' : '' }}">
<a href="{{ asset('storage/'.$image->path) }}" class="image-popup">
<img src="{{ asset('storage/'.$image->path) }}" class="img-fluid portfolio-image" alt="">
</a>
</div>
#endforeach
</div>
</div>
<div class="portfolio-info">
<h3 class="text-black">{{ $p->name }}</h3>
<h4 class="text-danger">{{ $p->productCategory->name }}</h4>
</div>
</div>
</div>
#endforeach
Your method $images = Product::with('productImage')->get(); will also return Product objects with images.
What you exactly want is to eager load both realtions and then reference it at the same time:
public function homeProduct(){
$products = Product::with(['productCategory', 'productImage'])->get();
return view('home.index', compact('products'));
}
And your view like this:
#foreach ($products as $p)
<div class="col-lg-6 col-12">
<div class="portfolio-thumb mb-5" data-aos="fade-up">
<div id="yoreBeans" class="carousel slide" data-bs-ride="carousel">
<div class="carousel-inner">
<!-- // this line changed --->
#foreach ($p->productImage as $key => $image)
<div class="carousel-item {{ $key == 0 ? 'active' : '' }}">
<a href="{{ asset('storage/'.$image->path) }}" class="image-popup">
<img src="{{ asset('storage/'.$image->path) }}" class="img-fluid portfolio-image" alt="">
</a>
</div>
#endforeach
</div>
</div>
<div class="portfolio-info">
<h3 class="text-black">{{ $p->name }}</h3>
<h4 class="text-danger">{{ $p->productCategory->name }}</h4>
</div>
</div>
</div>
#endforeach

show single page by using id

I want to go to specific page after click show button but after click show will get this error Undefined offset: 1
web.php
Route::get('/product/{id}', 'ProductController#show')->name('product.show');
ProductController.php
public function show($id)
{
$product = Product::find($id);
return view('product.show')->with(compact('product'));
}
home.blade.php
<div class="row">
#foreach($products as $product)
<div class="col-lg-4 col-md-6 mb-4">
<div class="card h-100">
<img class="card-img-top" src="http://placehold.it/700x400" alt="">
<div class="card-body">
<h4 class="card-title">
{{ $product->name }}
</h4>
<h5>{{ $product->price }}</h5>
<p class="card-text">{{ $product->description }}</p>
<td><a class="btn btn-primary" href="{{ route('product.show', $product->id ) }}">Show</a></td>
</div>
<div class="card-footer">
<small class="text-muted">★ ★ ★ ★ ☆</small>
</div>
</div>
</div>
#endforeach
</div>
Your are doing wrong in blade file. Note here php array start from 0. So array is [0,1,2,3] and database id is start from 1.
this is the correct link
{{ route('product.show', ['Product' => $product->id]) }}
You have to use like below code
{{ route('product.show', ['id' => $product->id]) }}
return view('product.show', compact('product'));
And in your show.blade.php you have to use like below
{{$product->id}} or {{$product->name}} //etc //But not use foorloop
The find method will return only one item. You can't use the loop on it.
Try the following code.
web.php
Route::get('/product/{product}', 'ProductController#show')->name('product.show');
ProductController.php
public function show(Product $product)
{
return view('product.show')->with(compact('product'));
}
home.blade.php
<div class="row">
<div class="col-lg-4 col-md-6 mb-4">
<div class="card h-100">
<img class="card-img-top" src="http://placehold.it/700x400" alt="">
<div class="card-body">
<h4 class="card-title">
{{ $product->name }}
</h4>
<h5>{{ $product->price }}</h5>
<p class="card-text">{{ $product->description }}</p>
<td><a class="btn btn-primary" href="{{ route('product.show', $product->id ) }}">Show</a></td>
</div>
<div class="card-footer">
<small class="text-muted">★ ★ ★ ★ ☆</small>
</div>
</div>
</div>
</div>
you are in wrong blade
you are returning product.show blade in your controller:
return view('product.show')->with(compact('product'));
but you put home.blade code!!!
put the right blade code
show.php: Why not try it $_ Get["id"]

I can't get the route with full slug/post

I am trying to create a blog, when trying to bring the previous record and the next record in sight this returns the "post" but not the full path that should be / single / {slug}
CONTROLLER
public function single($slug)
{
$post = Post::where('slug', $slug)->first();
$previous = Post::where('id', '<', $post->id)->orderBy('id', 'asc')->where('status', 'PUBLISHED')->first();
$next = Post::where('id', '>', $post->id)->orderBy('id')->where('status', 'PUBLISHED')->first();
return view('web.single')->with(compact('post', 'previous', 'next'));
}
view
#if (isset($previous))
<div class="alert alert-success">
<a href="{{ url($previous->slug) }}">
<div class="btn-content">
<div class="btn-content-title"><i class="fa fa-arrow-left"></i> Previous Post</div>
<p class="btn-content-subtitle">{{ $previous->title }}</p>
</div>
</a>
</div>
#endif
</div>
<div class="col-md-6">
#if (isset($next))
<div class="alert alert-success">
<a href="{{ url($next->slug) }}">
<div class="btn-content">
<div class="btn-content-title">Next Post <i class="fa fa-arrow-right"></i></div>
<p class="btn-content-subtitle">{{ $next->title }}</p>
</div>
</a>
</div>
#endif
Route
Route::get('/single/{slug}', 'Web\WorkController#single')->name('single');
When clicking on previous or next, the route shown by the browser is http://127.0.0.1:8000/et-autem-tempora
and should be
http://127.0.0.1:8000/single/et-autem-tempora
You are creating your url doing this:
<a href="{{ url($next->slug) }}">
...
</a>
The url('path') helper returns something like this: http://{base_url}/{path}.
Try to use your named route instead:
<a href="{{ route('single', ['slug' => $next->slug]) }}">
...
</a>
I think this should also work:
<a href="{{ route('single', $next->slug) }}">
...
</a>

Blade and the Negative case

I'm sorry I do not know how to word this question. I'm new to Laravel and I want to either show a photo(s) or if there are no photos I want to show a placeholder. This works but there must be a better way to do it than this.
#foreach ($items as $item)
<?php $totalpics=0; ?>
<div class="col-md-4">
<div class="card mb-4 box-shadow">
#if(! empty($item->photos) )
#foreach ( $item->photos as $photo )
#if ($photo->photo)
<img src="/storage/images/small/{{ $photo->photo }}" class="card-img-top" alt="{{ $item->name }}">
<?php $totalpics++; ?>
#endif
#endforeach
#if(1 > $totalpics)
<img class="card-img-top" data-src="holder.js/100px225?theme=thumb&bg=55595c&fg=eceeef&text=Thumbnail" alt="{{ $item->name }}">
#endif
You want to achieve a for loop and an optional statement for when there is nothing to show in the for loop.
Laravel uses the forelse loop for this (see all blade loops in the documentation).
A basic forelse could be:
#forelse($items as $item)
{{$item}}
#empty
There are no items to display
#endforelse
Above code is pseudo code and would not actually run
Which would render as either all the items or as the text There are no items to display.
In your case you could use:
#forelse($items as $item)
<div class="col-md-4">
<div class="card mb-4 box-shadow">
#forelse ( $item->photos as $photo )
#if ($photo->photo)
<a href="/storage/images/large/{{ $photo->photo }}">
<img src="/storage/images/small/{{ $photo->photo }}" class="card-img-top" alt="{{ $item->name }}">
</a>
#endif
#empty
<a href="/items/{{ $item->id }}">
<img class="card-img-top" data-src="holder.js/100px225?theme=thumb&bg=55595c&fg=eceeef&text=Thumbnail" alt="{{ $item->name }}">
</a>
#endforelse
</div>
</div>
#endforeach
Side note, this will not render any photos if there is a photo model attached to your item but the photo model does not have the photo property set, i.e. the for loop will be used but the if statement will fail.
You can do
#foreach ($items as $item)
<div class="col-md-4">
<div class="card mb-4 box-shadow">
#unless($item->photos)
<img class="card-img-top" data-src="holder.js/100px225?theme=thumb&bg=55595c&fg=eceeef&text=Thumbnail" alt="{{ $item->name }}">
#else
#foreach ( $item->photos as $photo )
#if ($photo->photo)
<img src="/storage/images/small/{{ $photo->photo }}" class="card-img-top" alt="{{ $item->name }}">
#endif
#endforeach
#endunless
There is another way to do that in laravel 5.3+ by using
#forelse($item->photos as $photo)
<img src="/storage/images/small/{{ $photo->photo }}" class="card-img-top" alt="{{ $item->name }}">
#empty
<img class="card-img-top" data-src="holder.js/100px225?theme=thumb&bg=55595c&fg=eceeef&text=Thumbnail" alt="{{ $item->name }}">
#endforelse

How to create dynamic layout in Laravel with Blade?

So I'm building my first blog, and I'd like to dynamically show to posts on my landing page. I want the layout to become like this (might be a little weird):
post-image - post-preview
post-preview - post-image
post-image - post-preview
This is what I have right now to show to blog posts:
#foreach($posts as $post)
<div class="col-sm-4">
<a href="/post/{{ $post->slug }}">
<img src="{{ Voyager::image( $post->image ) }}" class="img-responsive" style="width:100%">
<span>{{ $post->title }}</span>
</a>
</div>
#endforeach
web.php (route):
$posts = App\Post::take(3)->orderBy('created_at')->get();
return view('welcome', compact('posts'));
Now as I'd like to make the layout dynamically. I think I can do this by checking if the ID even or odd. However I have no idea on how to do this even when I've searched 50% of the web already :) .
If there is a better way on doing this just let me know! Greatly appreciated guys!
Yes you can do it by checking if current post or loop iteration is odd or even. (https://laravel.com/docs/5.5/blade#the-loop-variable) For Odd loop iteration, you can write image code first and in even loop iteration you can write preview code first to achieve your desired layout. You can check the following code:
#foreach($posts as $post)
<div class="row">
#if( $loop->iteration % 2 == 0 )
<div class="col-md-4">
<a href="/post/{{ $post->slug }}">
<img src="{{ Voyager::image( $post->image ) }}" class="img-responsive" style="width:100%">
</a>
</div>
<div class="col-md-8">
<span>{{ $post->title }}</span>
</div>
#else
<div class="col-md-8">
<span>{{ $post->title }}</span>
</div>
<div class="col-md-4">
<a href="/post/{{ $post->slug }}">
<img src="{{ Voyager::image( $post->image ) }}" class="img-responsive" style="width:100%">
</a>
</div>
#endif
</div>
#endforeach
Ok I guess I got your question. so there is no direct solution but you can measure inside your for loop by adding extra variable such as:
<?php $inc = 0;?>
#foreach($posts as $post)
<div class="col-sm-4">
<a href="/post/{{ $post->slug }}">
#if($inc%2 == 0)
<img src="{{ Voyager::image( $post->image ) }}" class="img-responsive" style="width:100%">
<span>{{ $post->title }}</span>
#else
<span>{{ $post->title }}</span>
<img src="{{ Voyager::image( $post->image ) }}" class="img-responsive" style="width:100%">
#endif
<?php $inc++;?>
</a>
</div>
#endforeach
Or you can use for loop instead of foreach of loop and inside for loop you can check variable i.e. i is odd or even.

Categories