How to create dynamic layout in Laravel with Blade? - php

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.

Related

Pictures not showins, seems considered as directories

I would like to show pictures on my website.
Here is the code of the view file :
#foreach($posts as $post)
<div class="w-full md:w-1/3 xl:w-1/4 p-6 flex flex-col">
<img src="{{asset("mvbimg/".$post->image)}}" >
<a href="/news/{{ $post->slug }}">
#if(!empty($post->image))
<img class="hover:grow hover:shadow-lg" src="{{ asset("mvbimg/".$post->image."")}}" alt="{{ $post->title }}">
#else
<img class="hover:grow hover:shadow-lg" src="https://www.example.com/img/nopic.jpg" alt="{{ $post->title }}">
#endif
<p style="text-align: center;">{{ $post->title }}</p></a>
</div>
#endforeach
And this is the frontend :
This is an URL of a picture upload on the server :
http://127.0.0.1:8000/mvbimg/202204171949lbc1.jpg
And this is my directory :

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 check foreach loop for a property. Laravel

I have been trying to figure out how to filter my foreach loop and only display an image if my post has one. So far I have been trying different functions and #ifs but to no avail.
Here is my controller code:
<div class="container">
<div class="row">
<div class="col-sm-6">
#foreach($posts as $post)
<div>
<h1>{{$post->title}}</h1>
<p>{{$post->body}}</p>
<img src="{{url('img', $post->image)}}">
</div>
<hr>
#endforeach
</div>
</div>
</div>
You can use a simple #if:
#if ($post->image)
<img src="{{ url('img/' . $post->image) }}">
#endif
Or #isset:
#isset ($post->image)
<img src="{{ url('img/' . $post->image) }}">
#endisset
https://laravel.com/docs/5.5/blade#control-structures
You can use a simple #if statement to see if the image property of the current $post is set. This could look a little something like this:
#foreach($posts as $post)
<div>
<h1>{{$post->title}}</h1>
<p>{{$post->body}}</p>
#if(!empty($post->image))
<img src="{{url('img', $post->image)}}">
#endif
</div>
<hr>
#endforeach
By including this, the <img> element will only be displayed if the property is not empty.
As also mentioned in another answer, you can replace the #if(!empty(...)) by #isset(...) to achieve the same result.

How to skip first item in a foreach loop in Laravel?

I am trying to fill my webpage with content based on content stored in a database. However, I would like to skip the first item; I want to start looping from the second item.
How can I achieve this?
#foreach($aboutcontent as $about)
<div class="col-md-4 text-center">
<div class="thumbnail">
<img id="" class="img-responsive" src="images/{{ $about->aboutimg }}" alt="">
<div class="caption">
<h3>{{ $about->aboutname }}</h3>
<p>{{ $about->aboutinfo }}</p>
</div>
</div>
</div>
#endforeach
As of Laravel 5.4, whenever you use foreach or for within blade files you will now have access to a $loop variable. The $loop variable provides many useful properties and methods, one of them being useful here, for skipping the first iteration. See the example below, which is a much cleaner way of achieving the same result as the other older answers here:
#foreach ($rows as $row)
#if ($loop->first) #continue #endif
{{ $row->name }}<br/>
#endforeach
Try This :
#foreach($aboutcontent as $key => $about)
#if($key > 0){
<div class="col-md-4 text-center">
<div class="thumbnail">
<img id="" class="img-responsive" src="images/{{ $about->aboutimg }}" alt="">
<div class="caption">
<h3>{{ $about->aboutname }}</h3>
<p>{{ $about->aboutinfo }}</p>
</div>
</div>
</div>
#endif;
#endforeach
Assuming that the $aboutcontents is numeric array just use the good old fashioned for loop instead of your new fangled foreach
// Notice you start at 1 and your first
// elem is 0 so... ta da... skipped
#for ($i = 1; $i < count($aboutcontents); $i++){
$about = $aboutcontents[$i]; //This is the object
//now use $about as you would
}
Note: I have not used Larvel or blades but based on the docs this should be doable
There is two way to do this:
1- if your $key is numeric you can use:
#foreach($aboutcontent as $key => $about)
#if($key == 0)
#continue
#endif
code
#endforeach
2- if a $key is not numeric
use #loop->first as a condition
You need some kind of a counter if you want to do that in blade:
<?php $count = 0;?>
#foreach
#if($count>1)
<div class="col-md-4 text-center">
<div class="thumbnail">
<img id="" class="img-responsive" src="images/{{ $about->aboutimg }}" alt="">
<div class="caption">
<h3>{{ $about->aboutname }}</h3>
<p>{{ $about->aboutinfo }}</p>
</div>
</div>
</div>
#endif
$count++
#endforeach
EDIT:
I like the answer provided by Mark Baker in the comment better
#foreach(array_slice($aboutcontent, 1) as $about)
<div class="col-md-4 text-center">
<div class="thumbnail">
<img id="" class="img-responsive" src="images/{{ $about->aboutimg }}" alt="">
<div class="caption">
<h3>{{ $about->aboutname }}</h3>
<p>{{ $about->aboutinfo }}</p>
</div>
</div>
</div>
#endforeach
Alternatively, you can just remove the first element from the array before iterating:
#php
array_shift($aboutcontent);
#endphp
#foreach($aboutcontent as $about)
<div class="col-md-4 text-center">
<div class="thumbnail">
<img id="" class="img-responsive" src="images/{{ $about->aboutimg }}" alt="">
<div class="caption">
<h3>{{ $about->aboutname }}</h3>
<p>{{ $about->aboutinfo }}</p>
</div>
</div>
</div>
#endforeach
The advantage is that you do not need any conditions to verify you are not the in the first iteration. The disadvantage is that you might need the first element within the same view, but that we don't know from your example.
Note It might make more sense to remove the first element from the array before you pass on the data to the view.
For reference, see:
http://php.net/manual/en/function.array-shift.php
https://laravel.com/docs/5.4/blade#php
Try this
#foreach($aboutcontent->slice(1) as $about)
<div class="col-md-4 text-center">
<div class="thumbnail">
<img id="" class="img-responsive" src="images/{{ $about->aboutimg }}" alt="">
<div class="caption">
<h3>{{ $about->aboutname }}</h3>
<p>{{ $about->aboutinfo }}</p>
</div>
</div>
</div>
#endforeach

laravel/blade cycle in template

I need your help. Here is my template file. How can I make to work that template? Main problem is that I don't know how to change div class values. Now I can make working only <div class="thumb-left"> but I also need <div class="thumb-middle"> and <div class="thumb-right">.
Thank you.
#extends('_layouts.main')
#section('content')
<div id="content-section">
#foreach ($uploads as $upload)
<div class="thumb-left">
<img alt="{{ $upload->image_title }}" title="{{ $upload->image_title }}" src="/files/images/{{ $upload->imagefile }}" height="250" width="300">
<div class="thumb-info">
{{ $upload->image_title }}
<a class="cat" href="#">PHOTOS</a>
</div>
</div>
#endforeach
<div class="thumb-middle">
<img alt="sunset" title="Sunset HDR" src="img/thumb.jpg" height="250" width="300">
<div class="thumb-info">
{{ $upload->image_title }}
<a class="cat" href="#">PHOTOS</a>
</div>
</div>
<div class="thumb-right">
<img alt="sunset" title="Sunset HDR" src="img/thumb.jpg">
<div class="thumb-info">
City Sunset HDR
<a class="cat" href="#">PHOTOS</a>
</div>
</div>
</div>
#stop
You could do:
#foreach ($uploads as $upload)
<div class="thumb-{{ array('left', 'middle', 'right')[($loop->iteration-1)%3] }}">
<img alt="{{ $upload->image_title }}" title="{{ $upload->image_title }}" src="/files/images/{{ $upload->imagefile }}" height="250" width="300">
<div class="thumb-info">
{{ $upload->image_title }}
<a class="cat" href="#">PHOTOS</a>
</div>
</div>
#endforeach
The $loop variable is a build in blades variable - check the docs:
When looping, a $loop variable will be available inside of your loop.
This variable provides access to some useful bits of information such
as the current loop index and whether this is the first or last
iteration through the loop. For instance: $loop->iteration - the current loop
iteration (it starts at 1).
You probably want to change your foreach to also use a key, so you can know at which index in your array you are:
<div id="content-section">
#foreach ($uploads as $index => $upload)
<div class="thumb-left">
<img alt="{{ $upload->image_title }}" title="{{ $upload->image_title }}" src="/files/images/{{ $upload->imagefile }}" height="250" width="300">
<div class="thumb-info">
{{ $upload->image_title }}
<a class="cat" href="#">PHOTOS</a>
</div>
</div>
#endforeach
</div>
Now, if I understand properly, what you're looking for is to switch from thumb-left, to thumb-middle and then finally thumb-right, and then loop again. You could use modulo to assign your class name based on the current index. This is untested code but you could probably use something along the lines of:
<div id="content-section">
{{ $classnames = array("thumb-left", "thumb-middle", "thumb-right"); }}
#foreach ($uploads as $index => $upload)
<div class="{{ $classnames[$index % count($classnames)] }}">
<img alt="{{ $upload->image_title }}" title="{{ $upload->image_title }}" src="/files/images/{{ $upload->imagefile }}" height="250" width="300">
<div class="thumb-info">
{{ $upload->image_title }}
<a class="cat" href="#">PHOTOS</a>
</div>
</div>
#endforeach
</div>

Categories