Searching in Laravel - laravel

I created a simple search in Laravel, to find stuff by search term
Controller
public function search()
{
$search = request()->query('search');
$data = array();
$data['books'] = Book::where('name', 'LIKE', "%{$search}%")->simplepaginate(12);
$data['authors'] = Author::where('name', 'LIKE', "%{$search}%")->simplepaginate(12);
return view('search', compact("data"));
}
Blade
#if(is_null(($data['books']) || ($data['authors'])))
<h2>Not Found, please try using another search term</h2><br/><br/>
#endif
#foreach($data['books'] as $book)
<a href="{{ route('book', $book->id) }}" target="_blank">
<img src="{{ secure_asset($book->image_url) }}" class="img-responsive" alt="{{$book->image_url}}">
</a>
<p class="author">{{ $book->author->name }}</p>
<h1 class="book-title">{{str_limit($book -> name, 20) }}</h1>
#endforeach
#forelse($data['authors'] as $author)
<a href="{{ route('author', $author->id) }}" target="_blank">
<img src="{{ secure_asset($author->image_url) }}" class="img-responsive" alt="{{$author->image_url}}">
</a>
<p class="author"></p>
<h1 class="book-title">{{str_limit($author -> name, 20) }}</h1>
#endforeach
What I am trying to is to say
Not Found, please try using another search term
When the search term can't be found. But this is not working for me
#if(is_null(($data['books']) || ($data['authors'])))
<h2>Not Found, please try using another search term</h2><br/><br/>
#endif
It doesn't return the Not found

That's because even with no resuts, the value of $data['books'] or $data['authors'] is not null, instead it's an empty collection. So you should check the count of results:
#if(!$data['books']->count() || !$data['authors']->count())
<h2>Not Found, please try using another search term</h2><br/><br/>
#endif
or use the isEmpty() method:
#if($data['books']->isEmpty() || $data['authors']->isEmpty())
<h2>Not Found, please try using another search term</h2><br/><br/>
#endif
also, it should actually be an AND insted of OR, IMO:
or use the isEmpty() method:
#if($data['books']->isEmpty() && $data['authors']->isEmpty())
<h2>Not Found, please try using another search term</h2><br/><br/>
#endif

Related

Laravel - Element displaying twice while looping inside a condition

This is the example while looping
despite having a condition and relation many too many it seems that the case
#foreach (\App\ClientDocument::where('id_client', $clients->id)->get() as $item)
#if (\App\Document::where('id',$item->id_document)->get())
<a class="img-fluid " href="{{asset('images/'.$item->file)}}" download="{{asset('images/'.$item->file)}}" alt="" name="download" > Telecharger </a>
#endif
#endforeach
in the above snippet
#foreach (\App\ClientDocument::where('id_client', $clients->id)->get() as $item)
#if (\App\Document::where('id',$item->id_document)->get())
<a class="img-fluid " href="{{asset('images/'.$item->file)}}" download="{{asset('images/'.$item->file)}}" alt="" name="download" > Telecharger </a>
#endif
#endforeach
code is absolutely fine, but there might be the possibility, you are running with duplicate data, you can use this also.
\App\ClientDocument::where('id_client', $clients->id)->distinct('id_client')->get()
and instead of using #if (\App\Document::where('id',$item->id_document)->get())
you can use
#if (\App\Document::where('id',$item->id_document)->firstOrFail())
#if (\App\Document::where('id',$item->id_document)->count())
That's it.
first you shouldn't loading data inside blade files
do it inside controller function
then you should create relationship inside ClientDocument model name document
and in your blade you can do that
$item->document
or whatever you want

Laravel - ERROR: Trying to get property 'depthead' of non-object

In my Laravel-5.8 blade that has this code:
#foreach($employees as $key => $employee)
<li class="list-group-item">
<b>Line Manager:</b>
#if(!$employee->linemanager)
<a class="float-right">N/A</a>
#else
<a class="float-right">{{ $employee->linemanager->fullName() ?? 'None' }}</a>
#endif
</li>
<li class="list-group-item">
<b>HOD:</b>
#if(!$employee->department->depthead)
<a class="float-right">N/A</a>
#else
<a class="float-right">{{isset($employee->department->depthead) ? $employee->department->depthead->first_name. ' ' .$employee->department->depthead->last_name : 'None'}}</a>
#endif
</li>
#endforeach
and its pointing to this line:
#if(!$employee->department->depthead)
How do I resolve it?
Thanks
The root cause of your issue is that $employee->department is either null or not an Object (Instance of Department, assuming you have Model and Relationships setup properly). You've got a check in place, but it's in the wrong spot. Check for $employee->department and $employee->department->depthead:
#if($employee->department)
#if($employee->department->depthead)
{{ $employee->department->depthead->first_name. ' ' .$employee->department->depthead->last_name }}
#else
None
#endif
#else
N/A
#endif
The defaults returned from a properly formed relationship will remove the need for string checks, meaning that #if($employee->department) and #if($employee->department->depthead) will be "truthy" or "falsey" enough to handle your use case.
Sidenote, this complexity is best moved to a Model function. In your Employee model, add this function:
public function getDepartmentHeadAttribute(){
if ($this->department) {
if ($this->department->depthead) {
return "{$this->department->depthead->first_name} {$this->department->depthead->last_name}";
} else {
return 'None';
}
} else {
return 'N/A';
}
}
Then, in your .blade.php file, you can simply do:
#foreach($employees as $employee)
{{ $employee->department_head }}
#endforeach
And it will perform the required if checks inside your Model and output First/Last, None or N/A as requird.
#if(!$employee->department->depthead)
look like the employee->department is not null, but it is not an object too ...
may be it is a string or number ....
#if(!$employee->department->depthead)
you could use 'is_object' method to determine that ...
#if( is_object($employee->department))
#if(!$employee->department->depthead)
....
#endIf
#endIf
but i don't think that the problem ...
the problem maybe you miss loading the relation,
if the property 'department' is a field of type 'json'
don't forget to cast it in model to 'array'

How to display default image if no filename exists in Laravel database

I want to display an image for each entry in a list of posts. The name of the images are unique file names. They are all saved in a database (MySQL) table. There is more than one image for each post. The code works right. Except, when there is a post without an image filename. This is a possible scenario but i can't get the code to work. In the event there's no existing filename for a post, i want to display a default filename.
Here's my code:
Images logic:
/**
* Get a vehicle's top or main image data from the image table
*/
public function topImage($id)
{
$image = Vehiclefulldataimage::where('vehiclefulldatas_id', $id)
->orderBy('id', 'ASC')->first();
return $image;
}
Here's the blade view, Posts:
#if (count($posts) > 0)
#foreach($posts as $post)
<?php $imageFilename = (new \App\Models\Logic\Images)->topImage($post->id); ?>
<!--Item-->
<li>
<div class="preview">
#if ($imageFilename = 0)
<img src="{{ asset('images') . '/' . 'defaultImage.jpg' }}" alt="No photo">
#else
<img src="{{ asset('images') . '/' . $imageFilename->disk_image_filename }}" alt="{{ ucfirst($imageFilename->caption) . ' | ' . $post->title }}">
#endif
</div>
<div class="desc">
<h3>{{ str_limit($post->title, 100, '...') }}</h3>
</div>
</li>
<!--/Item-->
#endforeach
#endif
This is the error message i get:
"Trying to get property of Non Object"
Try the following code:
You are using an assignment operator instead of comparison operator
//#if (count($posts) > 0)
#if (!$posts->isEmpty())
#foreach($posts as $post)
<?php $imageFilename = (new \App\Models\Logic\Images)->topImage($post->id); ?>
<!--Item-->
<li>
<div class="preview">
//#if ($imageFilename = 0) this is an assignment operator not comparison operator
#if ($imageFilename->isEmpty())
<img src="{{ asset('images') . '/' . 'defaultImage.jpg' }}" alt="No photo">
#else
<img src="{{ asset('images') . '/' . $imageFilename->disk_image_filename }}" alt="{{ ucfirst($imageFilename->caption) . ' | ' . $post->title }}">
#endif
</div>
<div class="desc">
<h3>{{ str_limit($post->title, 100, '...') }}</h3>
</div>
</li>
<!--/Item-->
#endforeach
#endif
Check your if statement....what you're doing there is an assignment and not a condition test...you can include a column..with a string pointing to the path of your default image..and set it to default...then load it...as default image
All of the answers above fix your problem. However, I recommend you to fix this problem by using Laravel features, Mutators.
https://laravel.com/docs/5.8/eloquent-mutators
Laravel mutators allow you to format or modify your Model attribute.
Just in your Vehiclefulldataimage model write the code below:
public function getImageAttribute($value)
{
//can write more logic here.
return $value ?: 'path/to/your/default/image';
}
Then you don't care more if condition blade template. If your image is empty the mutator returns the default image. So, everywhere when your retrieve Vehiclefulldataimage instance the mutator works properly
Thanks everyone.
After looking at all the answers, i did a simple alteration to my code. I altered:
#if ($imageFilename = 0)
to:
#if ($imageFilename == null)
Thus, my code now looks:
#if (count($posts) > 0)
#foreach($posts as $post)
<?php $imageFilename = (new \App\Models\Logic\Images)->topImage($post->id); ?>
<!--Item-->
<li>
<div class="preview">
#if ($imageFilename == null)
<img src="{{ asset('images') . '/' . 'defaultImage.jpg' }}" alt="No photo">
#else
<img src="{{ asset('images') . '/' . $imageFilename->disk_image_filename }}" alt="{{ ucfirst($imageFilename->caption) . ' | ' . $post->title }}">
#endif
</div>
<div class="desc">
<h3>{{ str_limit($post->title, 100, '...') }}</h3>
</div>
</li>
<!--/Item-->
#endforeach
#endif

How to make button visible once to admin-type user in Laravel?

I want to make ADD button only visible to admin-type user. My code looks like this:
#foreach($users as $user)
#if(Auth::user()->type=='admin')
<a href="{{ route('User.create', ['id'=>$user->id ]) }}" class="btn btn-default</i> ADD</a>
#endif
#endforeach
But, it returns lot of ADD button according to number of all users because of foreach loop. If I remove foreach loop, it will show error:
Undefined variable: user
How can I solve this problem?
It's because of you are removing the foreach , but using the variable $user again inside the routes .
Please remove the $user->id and instead, use Auth::user()->id .
#if(Auth::user()->type=='admin')
<a href="{{ route('User.create', ['id'=>Auth::user()->id ]) }}" class="btn btn-default</i> ADD</a>
#endif
You do not need to use foreach loop to check authenticated user having type admin
You need to remove passing id into the user.create route
#if(Auth::user()->type == 'admin')
<a href="{{ route('User.create') }}" class="btn btn-default</i> ADD</a>
#endif

Recursive display of data with blade, laravel

My Controller:
class Comments extends Controller {
public function GenerateComments($id){
$theme = DB::table('New_Themes')
->where('id', $id)
->get();
$Comments = NewTheme_Comment::where('id_theme', $id)->get();
return view('comments', ['Themes'=>$theme, 'Comments'=>$Comments]);
}
My Table(NewTheme_Comment):
id
parent_id
id_theme
user
text
upVotes
downVotes
My view(contains the recursive display of the tree of comments like the same in reddit), ......(data) contains the bootstrap media object, and the </div>'s things are used to round up (visually) the tree of comments as it should be:
<?php
tree($Comments, 0, 0);
$var = -1;
function tree($Comments, $parent_id = 0, $level=0, $c=0) {
global $var;
foreach($Comments as $Comment) {
if($Comment['parent_id'] == $parent_id) {
If ($level > $var) $var++; else {
for ($i = $var-$level+1; $i>0; $i--) { if ($c < 0) echo '</div> </div>'; else $c--; };
$var=$level;
};
echo '........(data)';
tree($Comments, $Comment['id'], $level+1,$c);
};
};
};
?>
The problem is that .........(data) should contain this stuff:
<div class="media">
<div class="media-left">
<img class="media-object" style="height:40px; width:40px;" src="{{ URL::asset("images/upVote.svg") }}" >
<div>{{$Comment->upVotes-$Comment->downVotes}}</div>
<img class="media-object" style="height:40px; width:40px;" src="{{ URL::asset("images/downVote.svg") }}" >
</div>
<div class="media-body">
<p class="media-heading">{{ $Comment->text }}</p>
<p class="media-heading">{{ $Comment->user }} / {{ $Comment->created_at }} </p>
And I am using the blade above this line | , which I can't integrate into that echo in view, replacing the ..........(data).
I have the intuition that the function I should integrate into the controller but I am broken(I spent to much time on recursive method of displaying comments) and I don't know how to take the data and print out it as whole unit recursively.
Any help is GREATLY appreciated to find a way out of this mess, thank you very much
Edit 1:
This is an example if i am filling with bootstrap media object in ........(data):
<div class="media">
<a class="media-left" href="#">
<img class="media-object" src="..." alt="...">
</a>
<div class="media-body">
<h4 class="media-heading">Media heading</h4>
Without 2 x </div>
You are approaching the views in a wrong way, as blade templates are not meant to use functions, it's better to follow the below recommendations.
The best way for that is to place the function code inside a blade file, for example recursive.blade.php:
recursive.blade.php
#foreach($comments as $comment)
//place your code here
#endforeach
Then in your main blade you can call it several times:
main.blade.php
<div>
#include('recursive', ['comments' => $comments])
</div>
The below example works for me and is the most widely used approach. remember the default value for parent_id is -1.
Model
public function children(){
return $this->hasMany(self::class,'parent_id','id')->with('children');
}
Controller
$comments = Comments::where('parent_id','=',-1)->get();
return view('comments',['comments'=> $comments]);
Blade (comments.blade.php)
<div class="tree">
#include('comment-list-widget',['comments' => $comment])
</div>
Blade (comment-list-widget.blade.php)
<ul>
#foreach($comments as $comment)
<li>
<a>{{$comment->text}}</a>
#if(!empty($comment->children) && $comment->children->count())
#include('comment-list-widget',['comments' => $comment->children])
#endif
</li>
#endforeach
</ul>

Resources