In controller:
function show($feast_id)
{
$feastMenu = Feast::find($feast_id);
$feastMenu->load('images', 'menu', 'users');
$feastMenu->chef->load('chefMeta');
$feastMenu = $feastMenu->toArray();
return view('feasts.showFeastMenu', compact('feastMenu'));
}
in views
#foreach($feastMenu['menu'] as $k => $menu)
Menu“{{$feastMenu['name']}}”({{count($feastMenu['menu'])}} course meal)
{{$menu['name']}}
#foreach($menu['menu_items'] as $item)
{{$item['name']}}
{{$item['description']}}
#endforeach
#endforeach
How can I set pagination into this please suggest in laravel I am using laravel 5. I have used relation into the controller and pass those toArray
There are a few things i have questions about... but first you should really take a look at the documentation https://laravel.com/docs/5.4/pagination it does a really good job explaining how to do what you want...
Anyways to answer you question i would do it this way... (note how i changed the views due to the returning collection instead of array). Also this will be under the assumption that you are using bootstrap.. if you are not you will need to look over the documentation to see how to add the pagination links
Controller:
function show($feast_id)
{
$feastMenu = Feast::find($feast_id)->simplePaginate(5);
$feastMenu->load('images', 'menu', 'users');
$feastMenu->chef->load('chefMeta');
return view('feasts.showFeastMenu', compact('feastMenu'));
}
View:
#foreach($feastMenu->menu as $k => $menu)
Menu“{{$feastMenu->name}}”({{$feastMenu->menu->count())}} course meal)
{{$menu->name}}
#foreach($menu->menu_items as $item)
{{$item->name}}
{{$item->description}}
#endforeach
#endforeach
{{ $feastMenu->links() }}
Related
I'm working on a forum project using Laravel 8, and in this project, I have made a page for getting all the questions with specific tag. Here is the the method to do that:
public function tag($name)
{
$tag = \App\Models\Tag::findOrFail($name);
return view('tag',[
'single' => $tag
]);
}
And then inside tag.blade.php:
#foreach($single->questions as $one)
...
#endforeach
But now I need to add pagination for this page, so if questions are more than a custom number, they can navigate to other pages.
In fact I had already added pagination to my other page which shows all the entire questions:
public function allQuestions()
{
$all = Question::latest()->paginate(20);
return view('questions.allquestions',[
'all' => $all
]);
}
But I don't know really how to add this feature to tag() method.
So if you know how to add this pagination, please let me know...
I would really appreciate any idea or suggestion from you guys.
Thanks in advance.
Theres 2 choices for this:
First Choice:
public function tag($name)
{
$tag = \App\Models\Tag::findOrFail($name);
$questions = $tag->question()->paginate(10);
return view('tag',[
'single' => $tag, 'questions' => $questions
]);
}
Then, on your view, you can just loop through the questions.
#foreach ($questions as $question)
... fill this
#endforeach
{!! $questions->render() !!}
Second Choice:
public function tag($name)
{
$tag = \App\Models\Tag::findOrFail($name);
$tag->setRelation('questions',$tag->questions()->paginate(10));
return view('tag',[
'single' => $tag
]);
}
Then, on your view, you can just loop through the questions.
#foreach ($single->questions as $question)
... fill this
#endforeach
Just an example:
let's say I have Post model, and the Comment model. Post, of course, have Comments, one-to-many relation.
I have to display list of posts with comments below it.
I'll get my posts in the controller:
$posts = Post::get(), I'll pass it to the blade view and then I'll loop through it
#foreach($posts as $post)
{{ $post->title }}
{{ $post->comments }}
#endforeach
where $post->comments is some relation
public function comments()
{
return $this->hasMany(Comment::class);
}
As we know, that query will be executed many times.
Now my question: how we should optimize it?
Return Cache::remember in the getter?
Get (somehow?) those comments, when getting the posts in one query? Something like join query? I know that I can write that kind of query, but I'm talking about Eloquent's query builder. And then how get the comments within the loop? Wouldn't {{ $post->comments }} call the relation again instead of getting stored data?
Different solution?
You can do $posts = Post::with('comments')->get() to eager load the comments with the post. Read more about it in the documentation: https://laravel.com/docs/5.7/eloquent-relationships#eager-loading
Also, to display the comments you would want to add another foreach loop. It would look something like this:
#foreach($posts as $post)
{{ $post->title }}
#foreach($post->comments as $comment)
{{ $comment->title }}
#endforeach
#endforeach
You’ve probably cached some model data in the controller before, but I am going to show you a Laravel model caching technique that’s a little more granular using Active Record models
Note that we could also use the Cache::rememberForever() method and rely on our caching mechanism’s garbage collection to remove stale keys. I’ve set a timer so that the cache will be hit most of the time, with a fresh cache every fifteen minutes.
The cacheKey() method needs to make the model unique, and invalidate the cache when the model is updated. Here’s my cacheKey implementation:
public function cacheKey()
{
return sprintf(
"%s/%s-%s",
$this->getTable(),
$this->getKey(),
$this->updated_at->timestamp
);
}
public function comments()
{
return $this->hasMany(Comment::class);
}
public function getCachedCommentsCountAttribute()
{
return Cache::remember($this->cacheKey() . ':comments_count', 15, function () {
return $this->comments->count();
});
}
yes u can do like that in controller
$minutes = 60;
$posts = Cache::remember('posts', $minutes, function () {
return Post::with('comments')->get()
});
in blade u can get like that
#foreach($posts as $post)
{{ $post->title }}
#foreach($post->comments as $comment)
{{ $comment->title }}
#endforeach
#endforeach
for more information read this article
I could not think how to write question for this problem.
So this is my problem.
I have two views
store-side-menu.blade.php
×
#foreach($store_categories as $cats)
{{ $cats->category_of_store }}
#endforeach
employ.blade.php
#section('side-menu-section')
#include('fc.static.store-side-menu')
#endsection
In employ.blade.php is only includes the store-side-menu.blade.php. I have designed this structure due to need.
In controller I have
public function employment()
{
$search = "";
$store_categoies = Category::all();
return view('fc.employ.employ', compact('search', 'store_categories'));
}
Now I have included store_categories in compact but store-side-menu.blade.php cannot access it. How do I achieve with its solution.
Try the code below and you should be good to go:
#section('side-menu-section')
#include('fc.static.store-side-menu', ['store_categories' => $store_categories])
#endsection
With laravel's eager loading, I can do something like
$forums = Forum::with('posts', 'threads')->get();
To get the threads as its posts and forum without doing many queries.
However, I have a method that gets the last post of the forum.
This is my method in Forum.php
public function lastThread()
{
$forums = $this->arrayOfIDs(); // get array of all ids, even subforum's subforums.
return Thread::whereIn('forum_id', $forums)->orderBy('updated_at', 'desc')->first();
}
This is my partial view to get the last thread:
#if ($subforum->lastThread())
<a href="{{ viewThread($subforum->lastThread()) }}">
{{ $subforum->lastThread()->title }}
</a>
<br>
<a href="{{ viewPost($subforum->lastThread()->lastPost) }}"> {{ trans('forum/post.last_post') }}
:</a>
{{ $subforum->lastThread()->lastPost->user->info() }}
<br>
{{ $subforum->lastThread()->lastPost->created_at }}
#endif
As you can see, if I am doing $subforum->lastThread() a lot. I can store it in a variable like $lastThread = $subforum->lastThread() and then do something like $lastThread->created_at to reduce the number of queries but I figured it would be much easier if just include it with the original query to get all forums.
Something like:$forums = Forum::with('posts', 'threads', 'lastThread')->get(); perhaps? I have tried doing a hasOne relation for this method but that does not work because the last thread does not necessarily belong to that specific subforum.
Anyway, how can I best fix this N+1 problem?
Thank you.
you have endless options,
if the Cache class is right for you than I will go with this path, you can also do this:
protectd $lastThread;
public function lastThread()
{
if ($this->lastThread) return $this->lastThread;
return $this->fetchLastThread();
}
public function fetchLastThread() {
$forums = $this->arrayOfIDs(); // get array of all ids, even subforum's subforums.
$this->lastThread = Thread::whereIn('forum_id', $forums)->orderBy('updated_at', 'desc')->first();
return $this->lastThread;
}
I'm new to Laravel and I'm getting an error which I think has more to do with logic than anything else but I can't quite seem to grasp how to overcome it.
So, I have a page with a simple form to search for a particular string in my database. But I want to have the result show up on the same page.
Here's what I have so far:
This is my Route.php:
Route::get('/', 'HomeController#index');
Route::post('find', 'HomeController#find');
This is my HomeController:
public function index()
{
return View::make('index');
}
public function search()
{
return View::make('index');
}
public function find()
{
$match = Input::get('find');
if($match) {
$results = Book::where('title', 'like', '%'.$match.'%')
->orWhere('author', 'like', '%'.$match.'%')
->get();
return View::make('index', array('results', $results));
} else {
return Redirect::to('/')->with('flash_error', 'No string added!');
}
}
And my View (index.blade.php):
{{ Form::open(array('url' => 'find', 'method' => 'POST')) }}
{{ Form::text('find', '', array('class' => 'search-query', 'placeholder' => 'Search')) }}
{{ Form::submit('Submit', array('class' => 'btn btn-info')) }}
{{ Form::close() }}
#if (Session::has('flash_error'))
{{ Session::get('flash_error') }}
#endif
#foreach ($results as $result)
{{$result->title}}
#endforeach
(eventually the foreach will be replaced by some ajax loading to display each result)
And the error says "undefined variable: results" and shows the foreach.
I get why that error shows up since on the first pass to this page the results haven't been loaded yet but how can I overcome this? I really want the data to be shown on the same page without having to go to another page to display them.
Like I said, I think this is mostly logic related (although I'm very new to Laravel so it might be that too)
Any help would be greatly appreciated !
you need to pass an associative array as your second param of the make method
return View::make('index', array('results' => $results);
The problem here is that in your use of index.blade.php in multiple controllers, you forgot which controllers provide which variables (and as a result, which variables may be omitted).
When you request / (HomeController#index), index.blade.php is rendered, but since no $results are passed to the view, you see the Undefined Variable warning. This is not a problem in HomeController#find, because you define $results. To combat this, you'll need to do something along the lines of an isset() check on $results before you foreach over it. Like so:
#if(isset($results))
#foreach ($results as $result)
{{$result->title}}
#endforeach
#endif
Your logic may vary based on your page's layout (you might want to add an else and display some alternate placeholder content).
Also, if abstracting the call to View::make() with $results into index_gen() isn't keeping your code DRY, then I'd suggest replacing it in find() with the call to View::make().