Get only first image in blade template from foreach loop - laravel

We have two tables room and room images. I am using relation in both tables and want to get the first image from room images table (For thumbnail). Below foreach loop is working fine on single detail page. Now i want to get the thumbnail image for main page.
#foreach ($room->tbl_roomimages as $single_img)
<img src="/storage/cover_images/{{$single_img->room_image}}" alt="">
#endforeach
I am using hasMany relation for Room images in room model.

You can create a function inside your model to get the first image.
Example:
public function getFirstImageAttribute()
{
return $this->hasOne('RoomImageModel');
}
And use that function to get the first image for your room.
<img src="/storage/cover_images/{{ $room->firstImage }}" alt="">

Thanks!
Although i get the first image like this.
#foreach($room->tbl_roomimages as $single_img)
#if($room->tbl_roomimages->first()==$single_img)
{{$single_img->room_image}}
#endif
#endforeach

Related

how to display data based on specific id in laravel?

I am new to laravel. I want to send data as id of existing data. Id comes from products.blade I send via href tag as shown below to gallery page. I have tried to find a way through other sites but it still doesn't work
<a class="btn btn-success" href="/dashboard/galleries/{{ $product->id }}"><i class="ri-image-add-line text-white"></i></a>
then i create a route like this
Route::resource('/dashboard/galleries', DashboardGalleryController::class)->middleware('admin')->shallow();
in the controller gallery, I made like this
public function index($id)
{
$gallery = Gallery::where('products_id', $id)->get();
return view('dashboard.galleries.index', compact('gallery'));
}
then inside the gallery page, I want to display a table to add images based on that id.
dashboard/galleries/index.blade.php
<h1>{{ $gallery->id }}</h1>
should i add data inside foreach or outside?
A restful resource controller sets up some default routes for you and even names them.
and ur case the logic should be inside show() function not index()
check this issue it will help u same issue solved here

How to show multiple images in blade in Laravel from Amazon S3 storage?

I have Book model and there is a field called cover, where I save image link.
I want to get images' links from S3 storage in Collection of Book.
How can I do it?
As you did not provide details on your front-end, I assume you're using blade for it.
To get the images of all the books inside the collection and show them in the front-end, you should do it something like this:
(YourController.php)
public function collection(User $user){
$collection = Collection::where('user_id', $user->id)->first();
$books = $collection->books;
return view('collection', compact('collection', 'books'));
}
In your view, you'd like to foreach each book.
#foreach($books as $book)
<img src="{{Storage::disk('s3')->temporaryUrl('directoryWhereYouStoredYourFiles/' . $book->featured_image, now()->addMinutes(30))}}" alt="cover">
#endforeach

laravel picture gallery optimisation

I have photo gallery page, which shows all files from given directory.
I have following logic of handling pictures:
original pictures I keep inside storage/app/img
using console command and Intervention\Image library I create thumbs - in public/thumbs_md I keep small thumbs about 300x300 and in public/thumbs_lg I keep the same pictures, but 1024x768.
My idea about gallery page is that I find all files from given directory inside thumbs_md and show them as thumbs with the links to the files with the same names inside thumbs_lg.
And each picture should have description, which I take from $image->exif('ImageDescription') using Intervention\Image library.
And paginate results with 20 pictures on the page.
It works well with less than 200 pictures in the directory, but when it is more nginx gives me 504 Gateway Time-out.
I found that the reason in getting description from exif.
EXIF info stored only in original source pictures inside storage/app/img. During thumbs generating EXIF is deleted. I could't find a way to keep it. Maybe this is main reason why I get Gateway Time-out. I guess that I have 2 problems:
It takes longer time to get EXIF from big source file rather than from thumb, but I don't know how to copy exif data from source image to thumb.
I retrieve exif data from all files in directory at once, but I don't know how to split it into chunks, because I must to give all elements to paginator at once.
At the moment I just comment code where I read EXIF from all files and there is no problems, but I want to get those descriptions and I don't really want to keep image description in database. I like the fact that it is part of image.
Is there a way to optimise my code?
controller
public function item($slug)
{
$files = Storage::disk('storage')->allFiles('thumbs_md/'.$slug);
$links = Storage::disk('storage')->allFiles('thumbs_lg/'.$slug);
if ( empty($files) ){
abort(404);
}
// generate title of the page
try {
$image = Image::make( '/var/www/storage/app/img/categories/'. $slug.'.jpg');
}
catch(NotReadableException $e)
{
// If error
$title = 'Picture not found';
}
// If no error ...
$title = $image->exif('ImageDescription');
// generate description for picture
$ImageDescription = function($value) {
try { $image = Image::make(str_replace('thumbs_md', '/var/www/storage/app/img', $value)); }
catch(NotReadableException $e)
{
// If error
return 'Picture not found';
}
// If no error ...
return $image->exif('ImageDescription');
};
//$imgDesc = array_map($ImageDescription, $files);
for ($i=0; $i < count($files); $i++) {
$items[$i]['thumb'] = $files[$i];
$items[$i]['link'] = $links[$i];
//$items[$i]['description'] = $imgDesc[$i];
}
$items = Arr::arrayToObject($items);
$items = collect($items)->mypaginate($perPage = 20);
$items->title = $title;
$items->slug = $slug;
return view('pages.gallery.item', compact('items'));
}
view
<div class="gallery">
#foreach ($items as $item)
<a href="/storage/{{ $item->link }}" class="lightGallery">
<img {{-- alt="{{ $item->description }}" --}} src="/storage/{{ $item->thumb }}">
{{-- <p>{{ $item->description }}</p> --}}
</a>
#endforeach
</div>
I don't see why you would not put this stuff in a database, when you've clearly shown that retrieving EXIF data from a big file is slow. You don't want to be doing heavy work on each page load.
You are also limited to filtering data easily as long as it is not in a database table.
The code you have currently is badly written and not performant (you are retrieving the page title from an image???) so the way to go is to design a few database tables to handle this :). Once it is done, I bet you can shrink this controller to under 7 lines.
Intensive or time consuming processing should be avoided during request as far as possible for better user experience.
One way to optimise your workflow would be:
Create database table for categories
Create image_categories table with columns
name(string)
slug(string)(unique)
title(string): exif('ImageDescription') or any value
exif(text): whole exif data for the category image if required
Create database table for Images
Create the images table with columns
image_category(string): slug for the image category
src(string): path to the original image
src_thumb_md(string): path to the thumb_md (300 x 300) image
src_thumb_lg(string): path to the thumb_lg (1024 x 768) image
description(string): exif('ImageDescription')
exif(text): whole exif data for the image if required
Store the data when creating thumbnails for image(s)
Extend the console command which you are using to generate the thumbnails, to
store the paths and exif data to the images table for all images
store the title and exif data to the image_categories table when storing the image for category
Define Image and ImageCategory models with relations (optional)
class ImageCategory extends Model
{
public function images()
{
return $this->hasMany(ImageCategory::class, 'image_category');
}
}
class Image extends Model
{
public function imageCategory()
{
return $this->belongsTo(ImageCategory::class, 'image_category', 'slug');
}
}
Controller & View
If Models are defined
public function item($slug)
{
$category = ImageCategory::where('slug', $slug)->first();
$images = $category->images()->paginate(20);
return view('pages.gallery.item', compact('category', 'images'));
}
Or when models are not defined
public function item($slug)
{
$category = DB::tables('image_categories')->where('slug', $slug)->first();
$images = DB::table('images')->where('image_category', $slug)->paginate(20);
return view('pages.gallery.item', compact('category', 'images'));
}
<div class="gallery">
<h1>{{ $category->title }}</h1>
#foreach ($images as $image)
<a href="/storage/{{ $image->src_thumb_lg }}" class="lightGallery">
<img {{-- alt="{{ $image->description }}" --}} src="/storage/{{ $image->src_thumb_md }}">
{{-- <p>{{ $image->description }}</p> --}}
</a>
#endforeach
<!-- Pagination links -->
{{ $images->links() }}
</div>

laravel 5.5 multiple controller inside one view

How to show TeamController#index and ProductController#index both show list of team and product inside one view main.blade.php
Looks like you want to show two datasets on one page. Basically, it means you have to execute two controller methods but it's not necessary to follow each and everything that official documentation says.
For example, if Products belong to a team, you can execute only TeamController#index and show products as given below.
#foreach($teams as $team)
#foreach($team->products as $product)
{{ $product->name }}
#endforeach
#endforeach
If no teams and products are two different entities and does not have any relation, you can just pass teams and products like this:
TeamController.php
public function index()
{
$teams = Team::all();
$products = Product::all(); // Don't forget to include 'use App\Product'
return view('index',compact(['teams','products']);
}
and then you can show teams and products like this:
index.blade.php
#foreach($teams as $team)
{{ $team->name }}
#endforeach
#foreach($products as $product)
{{ $product->name }}
#endforeach
Getting information from two different models does not mean you have to execute two different controller functions.
Still, if you want to get data from two different controllers, you can setup index.blade.php and create two ajax requests that will get data from two different URLs (two different controller methods).
Let me know if you have any more questions.
You can't show results from two controllers like that. Create a view that includes both the view that TeamController#index and ProductController#index return. be aware that both might be extending a layout which will probably try to load your page twice, so keep in mind to split the views into smaller components and include only those.
More info here
https://laravel.com/docs/5.6/views#creating-views

Joomla Component - Site Model Issue

I've been developing a Real Estate component for several of my clients. I have most everything working, except getting images from a separate table.
One example of a site model is City. Within the city model, the primary get (query) is a list of properties, based on the city. Example, if from either the cities view, or menu item, a city such as Dallas is selected, then in the single city view only property listings where property city = Dallas will show.
That part is working great, as it is supposed to. The problem is that every listing has multiple images, stored in an images table. On the property list view, only a single image (out of potentially many) needs to be pulled an displayed.
Adding as a "linked" sub-query within the main properties query doesn't work, as it will create multiple duplicate property listings for each image. So, I created as a custom method, get image.
The compiler that I am using to aid in the building doesn't support a signature method (method that takes values), so I needed to add as a class value. In the getItems function for properties, I created the class value of:
$this->a_property_id = $item->id;
Then, in the getImage custom function I added
$query->where('a.propid = ' . $db->quote($this->a_property_id));
as part of the query. In theory, this should pull a single item where a.propid equals the property id, such as property id=3, then pull an item from images where propid=3.
Lastly, I added the image code in the site view default.php as part of the foreach:
<?php foreach ($this->items as $item): ?>
<li>
<div class="uk-grid uk-panel uk-panel-box">
<div class="uk-width-medium-1-3">
<?php if(empty($this->image->path)){ ?>
<div> <img class="uk-thumbnail uk-thumbnail-medium" src="<?php echo JURI::root().'media/com_mostwantedrealestate/images/No_image_available.png'; ?>"> </div>
<?php } else { ?>
<div> <img class="uk-thumbnail uk-thumbnail-medium" src="<?php echo JURI::root() . $this->image->path . $this->image->filename; ?>"></div>
<?php } ?>
</div>
<div class="uk-width-medium-1-3 uk-float-left">
<a href="<?php echo 'index.php?option=com_mostwantedrealestate&view=property&id='.$item->id;?>" title="<?php echo $item->name;?>" rel="" >
<h3><?php echo $item->name; ?></h3>
</a>
</div>
This is kind of working, but not completely, so I'm unsure what I may be missing. With the way I have this coded, it's displaying an image. If there is only a single property listing, then it shows the proper image, however if there a, lets say, two properties: id=1 and id=3, then it shows propid=3 from the image table for both listings, rather than showing propid=1 for id=1 and propid=3 for id=3.
Any thoughts on what I might be missing?
You're looping over the $this->items but you use the same $this->image object for all of them. So you see the same image over and over again.
You can fix this by adding the image information to the item. Since you want to show just one image you can easily do this with single query joining your item table and your image table.
Another way is to combine the necessary data from different queries in your model so you can use something like $item->image->path.

Resources