How can I get images under a blog for a user - laravel

What I actually want is, for a specific user, I'm trying to show every image under a single blog. What I'm getting is a single blog post images for every blog.
Controller
$user_id = Session::get('id');
$user = Users::find($user_id);
$blogs = Blog::where('user_id', $user_id)->paginate(10);
$blogImage = BlogImage::where('blog_id', $blogs->pluck('id'))->get();
return view('Users.userlayout', compact('user', 'blogCat', 'blogs', 'username', 'blogImage'));
View Page
#foreach($blogs as $blog)
<div class="post">
#foreach($blogImage as $img)
<img src="{{asset('storage/blog_img/'.$img->blog_img)}}" alt="Image"
class="img-responsive">
#endforeach
<p>
<?php $str = $blog->blog_desc; ?>
{{str_limit($str, 250, "...")}}
</p>
<a href="{{URL::to('/blog-details/'.$blog->id)}}" target="_blank" class="btn_1">
Read more
</a>
</div>
<hr>
#endforeach

This is because you're using where instead of whereIn.
If you try and pass an array or a collection to where it will only use the first value.
$blogImage = BlogImage::whereIn('blog_id', $blogs->pluck('id'))->get();
Since this will return all of the BlogImage's associated with the Blog's the in the paginated list I would imagine you'll need to do a check to make sure you're only displaying the images that are associated with the specific Blog. One way you can do this is by using `#continue():
#foreach($blogImage as $img)
#continue($blogImage->blog_id !== $blog->id)
<img src="{{asset('storage/blog_img/'.$img->blog_img)}}" alt="Image" class="img-responsive">
#endforeach
All of that being said I would recommend using a one-to-many relationship between Blog and BlogImage:
Blog
public function images()
{
return $this->hasMany(BlogImage::class);
}
BlogImage
public function blog()
{
return $this->belongTo(Blog::class);
}
Then in your controller you can Eager load the images and have something like:
$blogs = Blog::with('images')->where('user_id', $user_id)->paginate(10);
And your blade file would have:
#foreach($blog->images as $image)
<img src="{{asset('storage/blog_img/'.$image->blog_img)}}" alt="Image" class="img-responsive">
#endforeach
You could then apply the same one-to-many relationship logic between User and Blog as well.

Related

Laravel Mega Menu Loop

I am learning laravel and was trying to create a Megamenu. But I can call parent menu, I stacked at 1st child and 2nd child.
Same children coming under every parent.
<div class="navbar-mega">
<div class="dropdown-mega">
#php
$categories = App\Models\Category::where('parent_id', 0)->orderBy('order_level','ASC')->get();
#endphp
#foreach ($categories as $item)
<button class="dropbtn-mega"> {{$item->id}}</button>
#endforeach
<div class="dropdown-content-mega">
<div class="row-mega">
#php
$subcategories = App\Models\Category::where('parent_id',
$item->id)->orderBy('name','ASC')->get();
#endphp
#foreach ($subcategories as $subcategory)
<div class="column-mega">
<h3>{{$subcategories}}</h3>
</div>
#endforeach
</div>
</div>
</div>
</div>
Database Fields
Subcategory Query Output
This code :
$subcategories = App\Models\Category::where('parent_id',$item->id)->orderBy('name','ASC')->get();
is not within the loop through the $categories as $item. So when it is executed it will also return the same set of categories (as $item will always be the same value at that point in your code.
Put it within the loop :
#foreach ($categories as $item)
<button class="dropbtn-mega"> {{$item->id}}</button>
<div class="dropdown-content-mega">
<div class="row-mega">
#php
$subcategories = App\Models\Category::where('parent_id',
$item->id)->orderBy('name','ASC')->get();
#endphp
#foreach ($subcategories as $subcategory)
<div class="column-mega">
<h3>{{$subcategories}}</h3>
</div>
#endforeach
</div>
</div>
#endforeach
and it should work fine.
You can use append for fetch sub categories, in your category model use this,
protected $appends = [
'sub_categories'
];
public function getSubCategoriesAttribute()
{
return Category::where('parent_id', $this->id)->orderBy('name','ASC')->get();
}
<div class="navbar-mega">
<div class="dropdown-mega">
#php
$categories = App\Models\Category::where('parent_id', 0)->orderBy('order_level','ASC')->get();
#endphp
#foreach ($categories as $category)
<button class="dropbtn-mega"> {{ $category->id }}</button>
#endforeach
<div class="dropdown-content-mega">
<div class="row-mega">
#foreach ($category->sub_categories as $subCategory)
<div class="column-mega">
<h3>{{ $subCategory->name }}</h3>
</div>
#endforeach
</div>
</div>
</div>
</div>
The better way to use below code in controller. And create the relations in model.
$categories = App\Models\Category::where('parent_id', 0)->orderBy('order_level','ASC')->get();
Use child parent relation in your model:
public function children()
{
return $this->hasMany(Category:Class,'parent_id');
}
And use with to get as parent-child tree
$categories = App\Models\Category::with('children)->where('parent_id', 0)->orderBy('order_level','ASC')->get();
You can check it using
dd($categories);
and use loop on it easily.
I think your table structure is not appropriate. Maybe you are trying to create an infinity category, subcategory, and other staff. In that case, you may go through this.
Table columns name should be like
id parent_id level name .....
Brief :
id as primary key, parent_id will be foreign key of your db table primary id, and other columns will be as your expectation.
How to read all the staff?
You may follow the below steps.
$categories = Category::query()->where('parent_id',0)->get() // You may put order by something.
Note: What you will get from this query?
The answer is, you will get all the parent's categories.
Now read every single parents category and their childrens.
How to read parents' category and their children?
At First Read Parent category
foreach($categories as $key=>$category){
echo $category->name; // Your Parent Category is here.
}
Secondly, Read the Parent-Child category
foreach($categories as $key=>$category){
echo $category->name; // Your Parent Category is here.
// Must check is child category found or not. Otherwise your error can be arrise.
if($categories->subCategories->count()){
foreach($categories->subCategories as $k=>$subCategory){
echo $subCategory->name;
}
}
}
A question can be here $categories->subCategories->count() && foreach($categories->subCategories as $k=>$subCategory) ?
If you have a question like this.
The answer is below :
Note: You must add a relationship method inside Category Model like A Parent Category can be More Child SubCategory
add this method to your Category Model.
public function subCategories(){
return $this->hasMany(Category::class,'parent_id');
}
Now you will get smooth output.
Have fun.

property does not refresh in the internal components of Livewire

Take a look at the following examples:
showPost.blade.php:
<div>
<livewire:content-box :content="$post"/>
<button wire:click="nextPost" >Next Post >></button>
</div>
and
content-box.blade.php :
<div>
<h1>{{ $content->title }}</h1>
<p>{{ $content->content }}</p>
</div>
So far, it is completely clear what is going to happen ...: First, the information of the content to be viewed is received through showPost and passed to the contentBox, and everything is OK ..
Well now I want to get the information of the next content via the account through the button I put and calling the nextPost method:
class ShowPost extends Component
{
public Post $post;
public function render()
{
return view('livewire.show-post');
}
public function nextPost()
{
$id = $this->post->id;
$nextPost = Post::where('id', '>', $id)->first();
$this->post = $nextPost;
}
...
But nothing happens and the contentBox component has no reaction .... Has anyone had this problem ???!
I'm not sure livewire works well with nested components. could use the pagination instead. The livewire docs suggest you should not use them for little snippets or use blade components for that kind of nesting.
You can achieve what you're doing at the moment with some simple pagination.
<?php
namespace App\Http\Livewire;
use App\Models\User;
use Livewire\Component;
use Livewire\WithPagination;
class SomeContent extends Component
{
use WithPagination;
public function render()
{
// Using simplePaginate(1) instead of paginate(1).
// simplePaginate only shows "<- Previous" and "Next ->" links
// paginate shows those 2 buttons but also page numbers which you don't seem to want.
return view('livewire.some-content', [
'users' => User::simplePaginate(1),
]);
}
}
<div>
{{-- This might look wrong, but essentially it's looping through an array of length 1 because we're paginating --}}
#foreach ($users as $user)
<h1>{{ $user->name }}</h1>
<h2>{{ $user->email }}</h2>
#endforeach
{!! $users->links() !!}
</div>
EDIT
I can confirm blade components work.
Here, nextUser is the same implementation you gave.
public function nextUser()
{
$id = $this->user->id;
$nextUser = User::where('id', '>', $id)->first();
$this->user = $nextUser;
}
<div class="container">
<div class="content">
{{-- These two have the exact same template --}}
<livewire:child :user="$user" />{{-- Doesn't update when clicking Next --}}
<x-blade-child :user="$user" />{{-- Updates when clicking Next --}}
</div>
<div>
<button wire:click="nextUser">Next</button>
</div>
</div>
When clicking nextUser, the blade component updates but the livewire one doesn't.
Livewire doesn't like nested components. In your case, we can use basic blade component:
<div>
<x-content-box :content="$post"/>
<button wire:click="nextPost" >Next Post >></button>
</div>
And then:
Move content-box.blade.php to resources/views/components/
Remove component_name.php file in app/Http/Livewire
Most of the time, we can change 2 nested livewire components to livewire(parent) + basic blade component(child),

laravel rendering section no passing parameters data

i have a problem passing variable during the rendering of only a section
All works good but array of data passed to the section('sidebar') view create an error ($data doesn't exist)
My blade files are
Default.blade.php
..other html code before..
<body>
#include('includes.header')
<div class="container-fluid">
<div class="row">
#yield('sidebar')
<!-- main content -->
#include('includes.main')
</div>
<footer class="row">
#include('includes.footer')
</footer>
</div>
</body>
..other code after..
home.blade.php
#extends('layouts.default')
#section('sidebar')
#include('includes.sidebar')
#stop
sidebar.blade.php
..other html code before..
<h2>The current UNIX timestamp is {{ time() }}.</h2>
<ul>
#isset($data)
#foreach ($data as $item)
<li class="nav-item"> {{$item->polizza}}</li>
#endforeach
#endisset
</ul>
..other html code after..
Controller Method search
public function search(Request $request){
if ($request->ajax()) {
$data = Customers::select('id','contr_nom','email','targa','cliente')
->where('polizza',request('polizza'))
->get();
return view('pages.home',$data)->renderSections()['sidebar'];
}
//return json_encode($data);
}
I know that array $data is good because i try return just JSON and i know that just sidebar refresh because timestamp change.
But $data is not passed to sidebar section refreshed!!
Why?
Thks a lot
You have the right idea, you just need to send the variable in a form that will be recognized. I'll break it out to an extreme, to help understand the parts, but you can easily recombine for shorter code.
$view = view('pages.home', compact('data')); // Compact with the text name ('data') sends the variable through
$sections = $view->renderSections(); // returns an associative array of 'content', 'pageHeading' etc
return $sections['sidebar']; // this will only return whats in the sidebar section of the view
Using compact() should get your where you need, and is the key.

How to display data value according to dropdown in laravel?

I have a table in my database which has a field lis_type and the field has 2 values: sale and rent, and I am calling data on my view page. Let's suppose I click on the Sale page, there only sale similar listing should be displayed. If I click on Rent then similar listing should be shown for rent. However, right now both listings are coming together, Please let me guide where I am making a mistake.
Controller
public function listingshownow(Request $r, $slug)
{
$listview = Listing::where('slug', $slug)->first();
$products = Listing::where('propId', $listview->propId)
->where(function ($query) {
$query->where('lis_type', '=', 'sale')->orWhere('lis_type', '=', 'rent');
})->get();
return view('listings-view', compact('products'));
}
View for Similar Listings...
#foreach($products as $prod)
#if($prod->lis_type === 'sale')
<div class="row featured portfolio-items">
<div class="col-lg-7 col-md-12 homes-content pb-0 mb-44">
<ul class="homes-list clearfix">
<li>
<i class="fa fa-bed" aria-hidden="true"></i>
<span>{{$prod->ls_fs}}</span>
</li>
<li>
<i class="fa fa-bath" aria-hidden="true"></i>
<span>{{$prod->bathroom}} Bathroom</span>
</li>
</ul>
</div>
</div>
#endif
#endforeach
You need to pass a variable to your controller to indicate what kind of page you are viewing, so you can use that in your query/filter.
For example, let's say your sales page URL looks like http://example.com/listings/sales. Then you could set up a route like:
Route::get('listings/{type}', 'ListingsController#show');
Now your ListingsController could have a method like:
// The $type parameter will be what was matched in the route
public function show($type) {
$listings = Listings::where('lis_type', $type)->get();
return view('listings-view', ['listings' => $listings]);
}
You might want to check that $type only matches the values you expect. You could either do that in the controller, eg:
// At the top of show()
if ($type !== 'sales' && $type !== 'rent') {
abort(404);
}
Or you could restrict it in your route, by specifying that the {type} there has to match some pattern:
Route::get('listings/{type}', 'ListingsController#show')->where('type', 'sales|rent');
All of this is covered in the Laravel routing docs, I suggest reading them, and better yet, take some minutes and browse all the docs! 30min skimming will give you a broad idea of how things work, and the knowledge of where to look and read more when you need a question answered.

How do I display images in a footer?

I have stored logos in the database and want to display them in the footer which is included #include('layouts.footer'). I am fetching images from the database using this code
public function show(){
$logo = DB::table('logos')->get();
return view('layouts.footer',['logo'=>$logo]);
}
I want to display these images in the footer using
<div class="footer">
#foreach($logo as $l)
{{ $l->company_name}}
{{ $l->company_logo}}
#endforeach
<p class="footer-text">© Copyright <?php echo date("Y"); ?> Hotel Store Partners</p>
</div>
but returns an error "undefined variable logo".
What is the correct way to display the images in the footer?
Try Using View Composer
In you AppserviceProvider boot method you can gather these name and pass to all Views at once.
Reference
Two ways you can achieve this:
1. Put this code in footer.
#php
$logo = DB::table('logos')->get();
#endphp
<div class="footer">
#if(count($logo))
#foreach($logo as $l)
{{ $l->company_name}}
{{ $l->company_logo}}
#endforeach
#endif
<p class="footer-text">© Copyright <?php echo date("Y"); ?> Hotel Store Partners</p>
</div>
But this method is a bad practice
Create FooterComposer
public function compose(View $view)
{
$logo = DB::table('logos')->get();
$view->with(['logo'=>$logo]);
}
Now $logo will be accessible in footer.
I have used View Composer.
In AppServiceProvider boot method, I added this code:
public function boot()
{
View::composer('layouts.app', function($view){
$view->with('logo', Logo::all());
});
}
In the Controller, I used this code:
return view('layouts.footer');
In the footer, I used this code:
<footer>
#foreach($logo as $l)
<p>{{ $l->company_name }}</p>
<img src="https://partners.hotelstore.co.ke/public{{ $l->company_logo }}" style="width:100px; height:75px;">
#endforeach
<p class="footer-text">© Copyright <?php echo date("Y"); ?> Hotel Store Partners</p>
</footer>
This is what finally displayed the images on the footer.

Resources