Property [articles] does not exist on this collection instance. laravel 5.4 - laravel

help or assist as it does not turn out to make sorting on categories, I can not understand as to solve this problem.
I recently study laravel.
Controller: class ArticlesController
public function showAll ($category_id)
{
$categories = Category::where('name', $category_id)->get();
return view('categories')->with(compact('categories', 'articles'));
}
This view from which I want to go into categories. site.blade.php
#foreach($categories as $category)
<li><a class="nav-link text-white" href={{route('articlesShow', ['id'=>$category->id]) }}">{{ $category->name }}</a></li>
#endforeach
Route:
Route::get('/categories/{category_id}', 'ArticlesController#showAll')->name('articlesShow');
Model: Category
public function articles()
{
return $this->hasMany(Article::class, 'category_id');
}
Representation in which does not get to get: categories.blade.php
#foreach($categories->articles as $article)
<div class="col-6 col-lg-4"> <!--Post -->
<img src="{{ asset('upload/image/1.jpg') }}" width="255" alt="..." class="rounded img_size">
<h4> {{ $article->title }}</h4>
<h6>Category: {{ $article->category->name }}</h6>
<h6>Author: {{ $article->author }}</h6>
<p>{{ $article->text }} </p>
<p><a class="btn btn-secondary" href="{{ route('articleShow', ['id' =>$article->id]) }}"> More »</a></p>
</div><!--EndPost-->
#endforeach

$categories is an array that contains categories, and the articles property belongs to a category, therefore you have to loop the categories before you can access the articles.
try this:
#foreach($categories as $category)
#foreach($category->articles as $article)
<div class="col-6 col-lg-4"> <!--Post -->
<img src="{{ asset('upload/image/1.jpg') }}" width="255" alt="..." class="rounded img_size">
<h4> {{ $article->title }}</h4>
<h6>Category: {{ $article->category->name }}</h6>
<h6>Author: {{ $article->author }}</h6>
<p>{{ $article->text }} </p>
<p><a class="btn btn-secondary" href="{{ route('articleShow', ['id' =>$article->id]) }}"> More »</a></p>
</div><!--EndPost-->
#endforeach
#endforeach

First of all: use eager loading.
Assuming, your ArticlesController#showAll method should display all articles for a given category id, your query should look like this
public function showAll ($category_id)
{
$categoryArticles = Category::with('articles')->where('id', $category_id)->get();
return view('categories')->with('categoryArticles', $categoryArticles);
}
Then to display all articles for the given category (assuming an article has only one category), this could be one way:
#foreach($categoryArticles->articles as $article)
<div class="col-6 col-lg-4"> <!--Post -->
<img src="{{ asset('upload/image/1.jpg') }}" width="255" alt="..." class="rounded img_size">
<h4> {{ $article->title }}</h4>
<h6>Category: {{ $categoryArticles->name }}</h6>
<h6>Author: {{ $article->author }}</h6>
<p>{{ $article->text }} </p>
<p><a class="btn btn-secondary" href="{{ route('articleShow', ['id' =>$article->id]) }}"> More »</a></p>
</div><!--EndPost-->
#endforeach

Related

Laravel search from multi select dropdown

I am trying to create a search filter using dropdown selections. The code only shows results when all dropdowns (make and model) are selected. But it should work even single dropdown (either make or model)is selected. At the moment, if I select a single dropdown, the result page shows "No Matching Data found". this is what I have done -
Controller
class CarFrontController extends Controller
{
public function index_classiccars(Request $request)
{
$filterMakes = DB::table('cars')->select('make')->distinct()->get()->pluck('make');
$filterModels = DB::table('cars')->select('model')->distinct()->get()->pluck('model');
$classiccar = Car::query();
if ($request->has('make')) {
$classiccar->where('make', $request->make);
}
if ($request->has('model')) {
$classiccar->where('model', $request->model);
}
return view(
'layouts.frontend.cars.classiccars_index',
[
'filterMakes' => $filterMakes, 'filterModels' => $filterModels,
'classiccars' => $classiccar->get()
]
);
}
public function store(Request $request)
{
return $request->all();
return view('layouts.frontend.cars.classiccars_index');
}
}
data blade
#forelse ($classiccars as $car)
<div class="row">
<div class="col-lg-5 col-md-5 col-pad">
<div class="car-thumbnail">
<a href="car-details.html" class="car-img">
<div class="price-box">
<span>£{{ $car->price }}</span>
</div>
#php $i=1; #endphp
#foreach ($car->join_caralbum as $image)
#if ($i>0)
<img class="d-block w-100" src="{{asset($image->image_location)}}" alt="car" height="225px" >
#endif
#php $i--; #endphp
#endforeach
</a>
<div class="carbox-overlap-wrapper">
<div class="overlap-box">
<div class="overlap-btns-area">
<a class="overlap-btn" href="{{ url('car_show/'.$car->id) }}">
<i class="fa fa-eye-slash"></i>
</a>
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-7 col-md-7 col-pad align-self-center">
<div class="detail">
<h3 class="title">
{{ $car->make }}
</h3>
<ul class="custom-list">
<li>
{{ $car->model }} /
</li>
......
</ul>
<ul class="facilities-list clearfix">
.....
.....
....
</ul>
</div>
</div>
</div>
</div>
#empty
No matching data found
#endforelse
filter blade
{!! Form::open(['action'=>'CarFrontController#index_classiccars','method'=>'GET']) !!}
<select class="form-control" name="make" id="make">
<option> Make(All)</option>
#foreach ($filterMakes as $make)
<option value="{{ $make }}">{{ $make }}</option>
#endforeach
</select><br>
<select class="form-control" name="model" id="model">
<option> Model(All)</option>
#foreach ($filterModels as $model)
<option value="{{ $model }}">{{ $model }}</option>
#endforeach
</select><br>
{{ Form::submit('Update Search',['class'=>'btn btn-primary']) }}
Your query results empty because even if you don't select any of your options, you actually do. If options don't have a value, the value is the text you give it to the option.
In your case, if you select just a model, actually you are selected 'Make(All)' option too. You can see this simply by putting dd($request->all()) on your index_classiccars method.
For checking selects, you can give empty value to first(default) option and control it with request()->filled('input').

Laravel query return wrong data

QUERY:
$recent_posts = Blog::join("categories",'categories.id', '=', 'blogs.category_id')
->where('categories.status', 1)
->orderBy('blogs.id', 'desc')
->take(3)
->get();
Both tables had a created_at column.
At frontend im using this to retrieve the data:
<div class="row justify-content-center">
#foreach ($recent_posts as $recent_post)
<div class="col-md-6 col-lg-4 latest-blog-resp">
<div class="blog-item">
<div class="blog-img">
<a href="{{ url('blog/'.$recent_post->slug) }}">
#if ($recent_post->blog_image == '')
<img src="{{ asset('fibonacci/adminpanel/assets/img/dummy/no_image.jpg') }}" class="img-fluid round-item" alt="blog image">
#else
<img src="{{ asset('fibonacci/adminpanel/assets/img/blog/thumbnail1/'.$recent_post->blog_image) }}" class="img-fluid round-item" alt="blog image">
#endif
</a>
</div>
<div class="blog-inner">
<div class="blog-meta">
<span class="mr-2">
<i class="mdi mdi-calendar-account-outline"></i>{{ __('frontend.by_admin') }}
</span>
<span>
<i class="mdi mdi-calendar-range"></i>{{Carbon\Carbon::parse($recent_post->created_at)->isoFormat('MMMM')}} {{Carbon\Carbon::parse($recent_post->created_at)->isoFormat('DD')}}
</span>
</div>
<h5 class="blog-title">
{{ $recent_post->title }}
</h5>
<p class="blog-desc">{{ $recent_post->short_description }}</p>
<a href="{{ url('blog/'.$recent_post->slug) }}" class="blog-more-link">
{{ __('frontend.read_more') }} <i class="fa fa-angle-right ml-2"></i>
</a>
</div>
</div>
</div>
#endforeach
#if (count($recent_posts) === 3)
<div class="col-12 text-center margin-top-30">
<div class="btn-group">
<a href="{{ url('blog') }}" class="default-button">
{{ __('frontend.view_all') }}
</a>
</div>
</div>
#endif
</div>
THE PROBLEM:
$recent_post->created_at returns the category table creation (created_at) date but we expect to receive the blog table result as created_as (like a post creation data).
Thanks in advance!
Specify your fields in a select clause.
$recent_posts = Blog::select(
'blogs.slug',
'blogs.blog_image',
'blogs.title',
'blogs.short_description',
'blogs.created_at'
)
->join('categories', 'categories.id', 'blogs.category_id')
->where('categories.status', 1)
->orderByDesc('blogs.id')
->take(3)
->get();

Else Statement returned Blank in Laravel

I want to implement a simple search on my Laravel Application
public function search()
{
$search = request()->query('search');
if ($search) {
$books = Book::where('name', 'LIKE', "%{$search}%")->simplepaginate(12);
}
else {
echo "<h2>Book Not Found, please try using another search term</h2>";
$books = Book::orderBy('created_at', 'desc')->simplepaginate(12);
}
return view('search')->with('books', $books);
}
But the else returned a blank screen when the search terms can't be found
UPDATE
Here is my view file
<div class="container">
<div class="row">
<div class="col-sm-12 col-md-10 offset-md-1">
<div class="row">
#foreach($books as $book)
<div class="col-md-3">
<div class="home-catalog-image">
<a href="{{ route('book', $book->id) }}" target="_blank">
<!-- <img src="{{ $book->image }}" alt="trending image" /> -->
<img src="{{ $book->image_url }}" class="img-responsive" alt="{{$book->image_url}}">
</a>
</div>
<p class="author">{{ $book->author->name }}</p>
<h1 class="book-title">{{str_limit($book -> name, 20) }}</h1>
</div>
#endforeach
</div>
<p style="text-align:center;>"> {!! $books->render() !!} </p>
</div>
</div>
</div>
Check how to use the request() helper to get the input.
Also you can use when() method for conditional clauses instead if else.
public function search()
{
$search = request('search', null);
$books = Book::when($search, function ($query, $search) {
return $query->where('name', 'LIKE', "%{$search}%");
})
->orderBy('created_at', 'desc')
->simplePaginate(12);
return view('search')->with('books', $books);
}
Then in Blade you can use #forelse directive to loop the collection, or if it's empty, show the message.
<div class="container">
<div class="row">
<div class="col-sm-12 col-md-10 offset-md-1">
<div class="row">
#forelse ($books as $book)
<div class="col-md-3">
<div class="home-catalog-image">
<a href="{{ route('book', $book->id) }}" target="_blank">
<!-- <img src="{{ $book->image }}" alt="trending image" /> -->
<img src="{{ $book->image_url }}" class="img-responsive" alt="{{$book->image_url}}">
</a>
</div>
<p class="author">{{ $book->author->name }}</p>
<h1 class="book-title">{{str_limit($book -> name, 20) }}</h1>
</div>
#empty
<h2>Book Not Found, please try using another search term</h2>
#endforelse
</div>
<p style="text-align:center;>"> {!! $books->render() !!} </p>
</div>
</div>
</div>
To solve my problem, I use forelse instead of foreach a
#forelse($books as $book)
<div class="col-md-3">
<div class="home-catalog-image">
<a href="{{ route('book', $book->id) }}" target="_blank">
<!-- <img src="{{ $book->image }}" alt="trending image" /> -->
<img src="{{ $book->image_url }}" class="img-responsive" alt="{{$book->image_url}}">
</a>
</div>
<p class="author">{{ $book->author->name }}</p>
<h1 class="book-title">{{str_limit($book -> name, 20) }}</h1>
</div>
#empty
<h2>Book Not Found, please try using another search term</h2>
#endforelse
In my controller, I used
public function search()
{
$search = request('search', null);
$books = Book::when($search, function ($query, $search) {
return $query->where('name', 'LIKE', "%{$search}%");
})
->orderBy('created_at', 'desc')
->simplePaginate(12);
return view('search')->with('books', $books);
}

Creating nested comments in laravel

I have the following blog control
public function show($slug)
{
$post = Blog::where('slugs', '=', $slug)->first();
$vars['pageTitle'] = Config::get('site.pageTitle') . $post['title'];
// The breadcrumbs... needs to be repopulated every page
$vars['breadCrumbs'] = [[
'url' => action('SimpleController#index'),
'title' => 'CovertDEV'
],[
'url' => action('BlogController#index'),
'title' => 'Blog'
],[
'url' => route('blog_post', ['slug' => $slug]),
'title' => $post['title']
]];
$vars['blog'] = $post;
$vars['comments'] = $post->Blog_comments->groupBy('comment_id');
return view('blog', $vars);
}
And the following scary view for the comments
#php
function display_comments($main, $depth = "\t")
{
foreach($main[0] as $mcomment)
{
#endphp
<div class="media">
<img class="m-3 avatar-sm rounded-1 border border-thick-1 shadow" src="../public/css/images/avatar-placeholder.png" alt="<?=$mcomment->firstname;?> <?=$mcomment->lastname;?>'s Avatar">
<div class="media-body">
<h6 class="mt-0 p-1 lead m-0 border-bottom"><?=$mcomment->firstname;?> <?=$mcomment->lastname;?></h6>
<div class="p-2">
<p><?=$mcomment->comment;?></p>
</div>
#php
if(isset($main[$mcomment->id]))
{
display_child($main, $main[$mcomment->id], $depth);
}
#endphp
</div>
</div>
#php
}
}
function display_child($main, $comment, $depth)
{
foreach($comment as $ccomment)
{
#endphp
<div class="media">
<img class="m-3 avatar-sm rounded-1 border border-thick-1 shadow" src="../public/css/images/avatar-placeholder.png" alt="<?=$ccomment->firstname;?> <?=$ccomment->lastname;?>'s Avatar">
<div class="media-body">
<h6 class="mt-0 p-1 lead m-0 border-bottom"><?=$ccomment->firstname;?> <?=$ccomment->lastname;?></h6>
<div class="p-2">
<p><?=$ccomment->comment;?></p>
</div>
#php
if(isset($main[$ccomment->id]))
{
display_child($main, $main[$ccomment->id], $depth."\t");
}
#endphp
</div>
</div>
#php
}
}
display_comments($comments);
#endphp
That is as ugly as it gets. It generates how I want it, but that is ugly, terribly ugly.
This is an image of the created nested comments
What is the best way to make this work elegantly in the blade template? I tried extending the blade template thing according to the docs, but that didn't prove fruitful for me. I simply couldn't figure out how to do it.
With this, I can't call asset, or anything like that... those are already out of scope.
I finally found my solution I'm satisfied with. If anyone has a better solution, do feel free to suggest.
My Blog controller is the same, only thing that changed is my view. In my blog view (where I see those comments as a user):
blog.blade.php
#foreach($comments[0] as $comment)
<div class="media comment">
#if(!is_null($comment->users['avatar']))
<img class="m-3 avatar-sm rounded-1 border border-thick-1 shadow" src="{{ asset( Config::get('site.asset_folder') . 'users/images/' . $comment->users['avatar']) }}" alt="{{ $comment->users['firstname'] }} {{ $comment->users['lastname'] }}'s Avatar">
#else
<img class="m-3 avatar-sm rounded-1 border border-thick-1 shadow" src="{{ asset( Config::get('site.asset_folder') . 'css/images/avatar-placeholder.png') }}" alt="{{ $comment->users['firstname'] }} {{ $comment->users['lastname'] }}'s Avatar">
#endif
<div class="media-body">
<h6 class="mt-0 p-1 lead m-0 border-bottom">{{ $comment->users['firstname'] }} {{ $comment->users['lastname'] }}</h6>
<div class="p-2">
<p>{{ $comment->comment }}</p>
</div>
#if(isset($comments[$comment->id]))
#include('block.comments', ['comments' => $comments, 'parent_id' => $comment->id, 'depth' => 0])
#endif
</div>
</div>
#endforeach
And then, my block/comments.blade.php
#foreach($comments[$parent_id] as $comment)
#if($depth >= Config::get('site.max_nested'))
</div>
</div>
#endif
<div class="media comment">
#if(!is_null($comment->users['avatar']))
<img class="m-3 avatar-sm rounded-1 border border-thick-1 shadow" src="{{ asset( Config::get('site.asset_folder') . 'users/images/' . $comment->users['avatar']) }}" alt="{{ $comment->users['firstname'] }} {{ $comment->users['lastname'] }}'s Avatar">
#else
<img class="m-3 avatar-sm rounded-1 border border-thick-1 shadow" src="{{ asset( Config::get('site.asset_folder') . 'css/images/avatar-placeholder.png') }}" alt="{{ $comment->users['firstname'] }} {{ $comment->users['lastname'] }}'s Avatar">
#endif
<div class="media-body">
<h6 class="mt-0 p-1 lead m-0 border-bottom">{{ $comment->users['firstname'] }} {{ $comment->users['lastname'] }}</h6>
<div class="p-2">
<p>{{ $comment->comment }}</p>
</div>
#if(isset($comments[$comment->id]))
#include('block.comments', ['comments' => $comments, 'parent_id' => $comment->id, 'depth' => $depth + 1])
#endif
#if($depth < Config::get('site.max_nested'))
</div>
</div>
#endif
#endforeach
And then I have a config file site in the config folder with the following contents
return [
// We define the max depth for the nested comments
// You could obviously define this value in database and be retrieving it from there
'max_nested' => 3,
];
The way my $comments array is set-up, the parent comments are always going to be in $comments[0] while the child comments would be in $comments[$parent_id]
I think that's fairly simple yet effectively functional!

Accessing collection from a relationship

So I have 2 tables.
DirtyEvent model and Event model.
I am retrieving DirtyEvent with Event which works fine
In blade I have:
#if (\Request::is('profile/event'))
#foreach ($events as $event)
#if (empty( $event->image ))
<div class="card-header">
<span class="card-title"> {{($event->title) }}</span>
</div>
#else
<div class="card-image">
<img class="img-responsive" src="{{ $event->image }}"></img>
<span class="card-title"> {{($event->title) }}</span>
</div>
#endif
<div class="card-content">
<p><strong>Starts: </strong>#php echo ($startdate) #endphp - {{$event->startime }}</p>
<br>
#if ($startdate != $enddate)
<p><strong>Ends: </strong>#php echo ($enddate) #endphp - {{$event->endtime }}</p>
<br>
#endif
<p><strong>Description:</strong></p>
<br>
<p>{{$event->description }}</p>
</div>
<div class="card-action">
<i class="fa fa-pencil-square-o fa-2x" aria-hidden="true"></i>
<form method="POST" action={{ url('events/delete/' . $event->id) }}>
{{ method_field('PATCH') }}
{{ csrf_field() }}
<button type="submit" class="delete" style="border:none;"><i class="fa fa-trash-o fa-2x" aria-hidden="true"></i></button>
</form>
</div>
#foreach ($events->publicevents as $eventss)
{{dd($events)}}
#endforeach
#endforeach
However dd($events) gives me:
DirtyEvent Collection -> relations -> publicevents -> Event collection
But, It is saying that publicevents do not exist in current collection.
Controller
public function index()
{
$id = Auth::id();
$events = DirtyEvent::where('user_id', $id)
->with('publicevents')
->get();
return view('events.viewEvent', compact('events'));
}
Model
public function publicevents()
{
return $this->hasMany('App\Event', 'event_id');
}
I guess not all dirty event objects have events. So check this first with empty() or isEmpty() or count():
#if (!empty($event->publicevents))
#foreach ($event->publicevents as $eventss)
{{ $eventss->id }}
#endforeach
#endif
Update
It should be $event->publicevents, not $events->publicevetns.

Resources