Pagination in laravel with conditions - laravel

I having problem with pagination, so far I looked at the docs but I can not find in there. I also looked at other post on stack overflow but they don't have the conditions I have in this case. So how can I paginate the if statement because I get the error
Undefined property: Illuminate\Pagination\LengthAwarePaginator::$threads
because when you paginate you need to get it straight out of the model like this model::paginate() so how can you do it in this case?
the controller
public function index(Request $request)
{
if($request->has('tags')){
$tag = Tag::find($request->tags)->paginate(10);
$threads = $tag->threads;
} else {
$threads = Thread::paginate(10);
}
return view('thread.index', compact('threads'));
}
so how can you properly paginate $tag = Tag::find($request->tags)->paginate(10); this?
the blade that generates a link where the controller get the tag from if that link is clicked
<div class="col-md-3">
<h4>Tags</h4>
<ul class="list-group">
<a href="{{route('thread.index')}}" class="list-group-item">
<span class="badge">14</span>
All Threads
</a>
#foreach($tags as $tag)
<a href="{{route('thread.index',['tags' => $tag->id])}}" class="list-group-item">
<span class="badge">14</span>
{{$tag->name}}
</a>
#endforeach
</ul>
Update
var_dump($request->tags); in the controller drops string(1) "2"

You can use the whereHas() method to add relational conditions (docs).
if ($request->has('tags')){
$threads = Thread::whereHas('tags', function ($query) use ($request) {
$query->whereIn('tags.id', $request->tags);
})->paginate(10);
} else {
$threads = Thread::paginate(10);
}
In this example you need to change the third line with the whereIn method to your correct needs.

Related

I want to displaying comments for each post

hello I just moved from php native and want to try relationships in laravel, so I want to display a post and each comment and the name of user who comments so that when looped the post has a comment that has a relationship with it.
So this is my HomeController.php :
public function index() {
$posts = Post::all();
$comment = Comment::all();
return view('home', [
'posts' => $posts,
'comments' => $comment
]);
}
My Post.php :
public function comments() {
return $this->hasMany(Comment::class);
}
public function user() {
return $this->belongsTo(User::class);
}
My Comments.php :
public function post() {
return $this->belongsTo(Post::class);
}
public function user() {
return $this->belongsTo(User::class);
}
My User.php :
public function post() {
return $this->hasMany(Post::class);
}
My home.blade.php :
#foreach ($posts as $post)
<div class="box-post">
<p>{{ $post->user->name }}</p>
<p>{{ $post->post_content}}</p>
<button>Comment</button>
</div>
#foreach ($comments as $comment)
<div class="box-post">{{ $comment->comment_content }} </div>
#endforeach
#endforeach
the code above runs with the post displayed along with the author but all the comments also appear in all posts, I have searched for references and tried to change the comments value in Controller but the results are still the same so I made the comments appear in each post *$comment = Comment::all();.
what I want is to display posts and comments that relate to each post, like a twitter feature that can reply to people's tweets.
Thx you..
Your relations builded well, so just can simply use $post->comments can get all comments related on each post.
#foreach ($posts as $post)
<div class="box-post">
<p>{{ $post->user->name }}</p>
<p>{{ $post->post_content}}</p>
<button>Comment</button>
</div>
#foreach ($post->comments as $comment) // make changes here
<div class="box-post">{{ $comment->comment_content }} </div>
#endforeach
#endforeach
public function index() {
$posts = Post::with('comments')->get();
return view('home', [
'posts' => $posts,
]);
}
then in blade
#foreach ($posts as $post)
<div class="box-post">
<p>{{ $post->user->name }}</p>
<p>{{ $post->post_content}}</p>
<button>Comment</button>
</div>
#foreach ($post->comments as $comment)
<div class="box-post">{{ $comment->comment_content }} </div>
#endforeach
#endforeach
You have done fine job building models and their relationship.
I recommend you change how you call post query.
public function index(Request $request) {
// add eager loading comments for each post and user
$posts = Post::with('comments', 'user')->get();
// eager loading user is needed, cause in blade you call $post->user->name
// calling comments will no longer needed
// return only $posts
return view('home', compact('posts'));
}
And inside your blade, you can call comments from each post, like this.
#foreach ($posts as $post)
<div class="box-post">
<p>{{ $post->user->name }}</p>
<p>{{ $post->post_content}}</p>
<button>Comment</button>
</div>
#foreach ($post->comments as $comment)
<div class="box-post">{{ $comment->comment_content }} </div>
#endforeach
#endforeach
That's it and if you use barryvdh/laravel-debugbar , you will see there are only 3 queries run, each one from table posts, comments and users.
And for comments query and users query, not all rows will be fetched,
only related to fetched posts from the 1st query.
Have fun using Laravel Framework!
Your PHP native knowledge/expertise will be very useful and speed up your learning/mastering process.

laravel pagination with search wrong links

I am trying to apply laravel pagination with search functionality.
So far I have tried both live search with laravel pagination and that keeps failing and normal search with pagination where I got better results but still not working.
Here is what I last tried for normal search with pagination:
ProjectController:
public function index()
{
$projects = Project::paginate(6);
return view('dashboard.projects.index',['projects' => $projects]);
}
public function search(Request $request)
{
$q = $request->input('q');
if(!empty($q)){
//dd("search");
$projects = Project::where('name', 'LIKE', '%' . $q . "%")->orderBy('created_at','desc')->paginate(6)->setPath('');
$projects->appends(['q' => $request->input('q')]);
return view ( 'dashboard.projects.index')->with('projects',$projects);
}
return redirect('/dashboard/projects/');
}
dashboard.projects.index
<div class="container-fluid">
<div class="row section-primary">
#foreach($projects as $project)
<div class="col-12 col-md-4 mb-2">
<div class="card project h-100">
<div class="card-header">
<h4>{{$project->name}}</h4>
</div>
<div class="card-body">
<p><strong>Project Manager:</strong> {{$project->manager_name}}</p>
<p class="description">{{ substr($project->description, 0, 110) }}...</p>
<div class="display-flex">
<div>View</div>
<div>Edit</div>
<div>Members</div>
<div>
{!!Form::open(['action' => ['ProjectController#destroy', $project->id], 'method' => 'POST','class' => 'form-link'])!!}
{{Form::hidden('_method', 'DELETE')}}
{{Form::submit('Delete', ['class' => 'button-link'])}}
{!!Form::close()!!}
</div>
</div>
</div>
</div>
</div>
#endforeach
</div>
</div>
<div>
{!! $projects->links()!!}
</div>
The code works fine when I go to dashboard/projects and pagination works.
The search works but pagination fails.
When I press the search button it first goes to dashboard/projects/search
Then when I press page 2 button on pagination it goes to dashboard/projects/search?q=project&page=2, here it is requesting the show function which is unrelated.
PS: Any extra help for live search with pagination would be amazing.
I have managed to fix the problem, for anyone who is facing the same issue, I used in my routes:
Route::resource('/dashboard/projects', 'ProjectController');
Route::any('/dashboard/projects/search', 'ProjectController#search');
For some reasons, /dashboard/projects/search was not a good idea as it was going to the show defined by resource, all I had to do is change:
Route::any('/dashboard/projects/search', 'ProjectController#search');
to
Route::any('/dashboard/project/search', 'ProjectController#search');
so they look like different routes until I find/learn a better solution.
The other solutions is putting the search route first such as:
Route::any('/dashboard/projects/search', 'ProjectController#search');
Route::resource('/dashboard/projects', 'ProjectController');
In larvel => 6 Version:
Input no longer exists In larvel 6,7,8 Version. Use Request instead of Input.
Change $q = $request->input('q'); to $q = $request->q;
Your ProjectController:
use Illuminate\Support\Facades\Request;
..
..
public function search(Request $request)
{
$q = $request->q;
if(!empty($q)){
//dd("search");
$projects = Project::where('name', 'LIKE', '%' . $q . "%")->orderBy('created_at','desc')->paginate(6)->setPath('');
$projects->appends(['q' => $request->input('q')]);
return view ( 'dashboard.projects.index')->with('projects',$projects);
}
return redirect('/dashboard/projects/');
}

Laravel 5.7 | Pagination - eloquent query (relationship table)

how can I use pagination, where my eloquent query looks:
PageController - method show:
$page = Page::where('slug', $slug)->with(['subpages'=>function($q) {
$q->where('visible', 1)->orderBy('order', 'asc')->paginate(9);
}])->first();
I would like to paginate subpages on page's View blade (Page - one to many - Subpage relationship)
Here is part of my show.blade.php view:
{{ $page->subpages->links() }}
Error:
Method Illuminate\Database\Eloquent\Collection::links does not exist.
EDIT:
FULL FUNCTION SHOW:
public function show(PageRepository $pageRepo, $slug){
$page = Page::where('slug', $slug)->with(['subpages'=>function($q) {
$q->where('visible', 1)->orderBy('order', 'asc');
}])->first();
$subpages = $page->subpages()->paginate(2);
$sidebar = Navbar::where('type','sidebar')->orderBy('order')->with(['pages'])->get();
return view('pages.page.show', [
"page" => $page,
"subpages" => $subpages,
"sidebar" => $sidebar,
]);
}
VIEW:
<div class="row display-flex">
#foreach($page->subpages as $subpage)
<div class="col-sm-4">
<div class="card mb20">
<div class="card-block">
<h4 class="card-title font400">{{ $subpage->title }}</h4>
</div>
</div>
</div>
#endforeach
</div>
{{ $subpages->links() }}
If your goal is to paginate the relation from what I see, but you're querying the parent model. That's what's wrong. You have to completely change your logic since the subquery doesn't map the relation inside the Laravel Model. It's just used as a condition to retrieve that model.
You query should look like this:
$page = Page::where('slug', $slug)->with(['subpages'=>function($q) {
$q->where('visible', 1)->orderBy('order', 'asc') // ->paginate(9); This is not necessary
}])->first();
Now that you have the parent model, you can execute a new query for the relation, and there you have to call the paginate method:
I don't think that would be a good practice to do something like this in your blade view:
{{ $page->subpages()->paginate(9)->links() }}
But it's better to implement a new variable:
// Previous code that retrieves the page
$subpages = $page->subpages()->paginate(9);
return response()->view('your.blade.view', compact('page', 'subpages');
now you can use the subpages variable, that contains the paginated results, in your view

Foreach doesnt work in my View in laravel 5.6

public function getValues(Request $request){
$typ=$request->get('typ');
$stellentyp=$request->get('stellentyp');
$bereich=$request->get('bereich');
$abschluss=$request->get('abschluss');
$user = DB::table('users')->get();
$angebots = DB::table('angebots') ->orderBy('stellenname', 'asc');
if(!empty($request->get('stellentyp'))){
$angebots->where('stellentyp', $stellentyp);
}
$angebots->get();
$row = $angebots->count();
return view('user/angebots', compact('typ', 'stellentyp', 'bereich', 'abschluss', 'row', 'angebots', 'user'));
}
this is my controller
{{$row}} Angebote insgesamt
<div class="row">
#foreach ($angebots as $angebot)
<div class="col-12 col-md-6 col-lg-4 pt-4">
<div class="card offer-card">
<div class="card-image">
<img class="img-fluid" src="{{ asset('uploads/avatars/' . $user[$angebot->firma -1]->avatar) }}">
</div>
<div class="card-body">
<h4 class="text-j4y-dark praktikumstitel">{{ $angebot->stellenname }}</h4>
Jetzt mehr anzeigen ยป
</div>
</div>
</div>
#endforeach
</div>
and this is my view
but i got this error message:
Undefined property: Illuminate\Database\MySqlConnection::$firma (View: C:\wamp\sites\j4ylara\resources\views\user\angebots.blade.php)
if I put the get behind my first statement so like this
$angebots = DB::table('angebots') ->orderBy('stellenname', 'asc')->get();
but then the filter doesn't work
I don't know how I can view my results
I only know this way
{{$angebot[1]->stellenname}}
but I want all my results so I use a foreach but it doesn't work
does anyone know why?
In the following snippet
$angebots = DB::table('angebots') ->orderBy('stellenname', 'asc');
if(!empty($request->get('stellentyp'))){
$angebots->where('stellentyp', $stellentyp);
}
$angebots->get();
You're doing $angebots->get() which returns the results of your query. You need to assign the results of your query to a variable and pass that into your view. You could do something like this:
$angebots = $angebots->get();
Which would assign the result of the query to $angebots and then you could use it in your view.
Personally, I would consider renaming $angebots to $angebotsQuery or something similar and then do this:
$angebotsQuery = DB::table('angebots') ->orderBy('stellenname', 'asc');
if(! empty($request->get('stellentyp'))){
$angebotsQuery->where('stellentyp', $stellentyp);
}
$angebots = $angebotsQuery->get();
You are sending the Builder in $angebot. Try putting the results in a variable.
public function getValues(Request $request){
$typ=$request->get('typ');
$stellentyp=$request->get('stellentyp');
$bereich=$request->get('bereich');
$abschluss=$request->get('abschluss');
$user = DB::table('users')->get();
$angebots = DB::table('angebots') ->orderBy('stellenname', 'asc');
if(!empty($request->get('stellentyp'))){
$angebots->where('stellentyp', $stellentyp);
}
$angebots = $angebots->get();
$row = $angebots->count(); //this will not cause an issue since the Collection has a count method
return view('user/angebots', compact('typ', 'stellentyp', 'bereich', 'abschluss', 'row', 'angebots', 'user'));
}

Can't use pagination on hasMany relationship

Here's my category model:
public function products() {
return $this->hasMany('Product');
}
Then i am printing all products that each category has:
#foreach($category->products as $product)
{{ $product->title }}
#endforeach
However it prints every related product to this category. How can i use pagination in that case? I've tried to print pagination links at the bottom:
<div class="pager">
{{ $category->products()->paginate(12)->links() }}
</div>
It does print pagination links correctly, but when i change the page - content is not changing.
Before sending data to view first paginate the result like this.
$products = $category->products()->paginate(12);
now pass this value to the view and just iterate it.
#foreach($products as $product)
{{$product->title}}
#endforeach
To display links just call links method on the products in the view.
{{$products->links()}}
You want to call paginate your products first:
public function products() {
return $this->hasMany('Product');
}
public function recentProducts() {
return $this->products()->paginate(12);
}
Then in your view you loop through
#foreach($category->recentProducts() as $product)
{{ $product->title }}
#endforeach
Then your links
<div class="pager">
{{ $category->recentProducts()->links() }}
</div>
Pass paginated collection to the view:
// controller
$products = $category->products()->paginate(12);
// view
#foreach ($products as $product)
// do what you need
#endforeach
// links:
$products->links();

Resources