Before I was simply doing a query that selects some field and some conditions. This line of code is giving me the correct result.
public function index()
{
// Get links
$links = Link::select('id', 'url', 'short_url', 'counter', 'expired_on')
->orderBy('id', 'desc')
->where('delete_flg', 0)
->get();
// Return data
return view('dashboard')->with(
array(
'links' => json_decode($links),
'current_datetime' => Carbon::now()
)
);
}
Now I want to implement pagination to the above line.
$links = Link::select('id', 'url', 'short_url', 'counter', 'expired_on')
->orderBy('id', 'desc')
->where('delete_flg', 0)
->get()->paginate(2);
When I try using paginate(2) at the end I get error:
Method Illuminate\Database\Eloquent\Collection::paginate does not exist.
So from some other tutorial I tried without ->get() and then paginate
Then I get such error.
count(): Parameter must be an array or an object that implements Countable
I am confused on how to implement paginate.
Can anybody please help me?
You can simply do following:
$links = Link::select('id', 'url', 'short_url', 'counter', 'expired_on')
->orderBy('id', 'desc')
->where('delete_flg', 0)
->paginate(2);
paginate already acts like a ->get()
And this is how you return the data / collection to your view:
// return data
return view('dashboard', compact('links'));
Alternative to compact:
return view('dashboard')->with([
'links' => $links
]);
Then in your view you can do whatever you wish to do with the data:
#foreach($links as $link)
<p>{{ link }}</p>
#endforeach
This is a documented change in PHP 7.2. You need to either update Laravel to 5.6+ or downgrade PHP to version 7.1.
Furthermore you have to use paginate() without ->get(), you should also take a look at the pagination documentation.
Related
I have some search with multiple arguments and I want to query if the input is not null then make query argument.
I tried many ways but I cannot get query results.
Here is my sample code
$products = Product::where('game_id',$tg->id);
if($keyword !=null){
$products->where("name","like",$keyword);
}
if($price_start !=null){
$products->where("price",">",$price_start);
}
if($price_end !=null){
$products->where("price","<",$price_end);
}
if($avalibility !=null){
$products->where("status","=",$avalibility);
}
$products->orderBy("created_at","DESC");
$products->get();
Try this
$products = Product::select('*')
->where(function ($query) use($request){
if($keyword !=null){
$query->where('name','like','%'.$keyword.'%');
}
if($price_start !=null){
$query->where("price",">",$price_start);
}
if($price_end !=null){
$query->where("price","<",$price_end);
}
if($avalibility !=null){
$query->where("status","=",$avalibility);
}
})
->where('game_id',$tg->id)
->orderBy('created_at', 'DESC')
->get();
In your code assign the result of query to the variable products as follows:
$products = $products->get();
now the $products will contain the result
Try adding ->get() to the query builder.
$products = Product::where('game_id',$tg->id)->orderBy->('created_at', 'desc')->get().
Use the explicit ->get() on the query builder to get a collection. And then use laravels collection
methods (https://laravel.com/docs/5.8/collections#available-methods) to add further where clauses and sort the results (see sortBy method) or add the orderBy clause to the intial query (as above). You can leave out the final ->get() since it's called on the query builder.
Using the 'where' collection method inside the if statement:
if(isset($keyword)) {
$products = $products->where('name','like', '%' . $keyword . '%');
}
First you need to validate your data as follow
$request->validate([
'id' => 'required',
'keyword' => 'required',
'price_start' => 'required',
'availability' => 'required'
]);
Now you can perform your data query with these validate Data. If you have multiple data for where method you might be put all of them in array ,after that to fetch the data-you should use get() method; like as bellow
$products = Product::where([
['id', '=', $request->id],
['keyword', 'like', $request->keyword]
])
->orderBy("created_at","DESC")
->get();
I've followed the instructions on the Laravel documentation for pagination with appends([]) however I'm having a little trouble with the persistence of these parameters.
Say for example, I pass home?category=Cars&make=Tesla to my view. What is the best way to paginate with them Get requests?
Right now I've passed the category as a parameter to the view as (where category is the model i've grabbed findOrFail with the request('category');)
$category_name = $category_model->name;
And then in my view it's like so:
{{ $vehicles->appends(['category' => $category_name])->links() }}
But when I go between pages in the pagination, this $category_name value doesn't seem to persist. Whats the recommended way to achieve what I want?
Thanks.
You can append the query string in your controller when you paginate the result. I'm not sure if that was your only question or even regarding applying the query string as a condition. So here is a sample showing you how to do both. This should give you an idea of how to do it. I just assumed the column names in this example.
$category = request('category');
$make = request('make');
$vehicles = Vehicle::when($category, function ($query) use ($category) {
return $query->where('category', $category);
})
->when($make, function ($query) use ($make) {
return $query->where('make', $make);
})
->paginate(10);
$vehicles->appends(request()->query());
return view('someview', compact('vehicles'));
Every time I try to setup my pagination:
Missing argument 1 for Illuminate\Support\Collection::get()
My controller:
public function index()
{
$products = DB::table('products')
->where('product_group_id', '=', 1)
->paginate(15)
->get();
return view('product.index', [
'products' => $products,
]);
}
My view:
{{ $products->links() }}
What goes wrong here?
You don't need ->get() here. ->paginate() gets your records from the database and returns a collection of those 15 items.
When you're running ->get() here you're attempting to run it on the collection that is returned which expects a $key and is used to get a specific item out of a collection.
You should do this:
$products = DB::table('products')
->where('product_group_id', '=', 1)
->paginate(15);
return view('product.index', [
'products' => $products,
]);
or with Eloquent
$product = Product::where('product_group_id', '=', 1)
->paginate(15);
return view('product.index', [
'products' => $products,
]);
Note: I have put the filters before the paginate() call to ensure that the where clause is part of the database query rather than trying to filter the resulting collection/paginator
When you call the paginate() method on a Illuminate\Database\Query\Builder object, You will get an instance of \Illuminate\Pagination\LengthAwarePaginator. That itself does not have a get()-Method, but the Illuminate\Pagination\AbstractPaginator it extends has a magic __call() function which forwards the call to the underlying Collection.
Now, Illuminate\Support\Collection does have a get() method, but it takes the key of the element you want to get out of the Collection as an argument, hence the error you get.
Now, I suppose what you actually want to achieve standard pagination with links for page numbers and "forward" and "back" buttons. If so, you should just stick to the documentation: Get the data just the way you did, just leave out the get(), then display it in a view the way its shown here.
EDIT: Just read about the Method links does not exist error you get. That is indeed strange. Builder::paginate() definitely returns an Instance of LengthAwarePaginator which itself definitely has a links() method.
Is there perhaps some more code that is relevant to this problem which you havent shown us yet? Maybe in your view?
I have a table called List which i planned to be displayed into view with this command : $lists= List::with('user', 'product.photodb', 'tagCloud.tagDetail')->get();. But, i want the data displayed is only those that has TagID equal to the one user inputted. Those data can be retrieved from TagCloud table.
What i am currently doing is :
$clouds = TagCloud::select('contentID')
->where('tagDetailID', '=', $tagID)
->get();
$lists = List::with('user', 'product.photodb', 'tagCloud.tagDetail')
->where('id', '=', $clouds->contentID)
->get();
But when i tried to run it, it only return a null value, even though when i am doing return $clouds, it does returned the desired ID.
Where did i do wrong ? Any help is appreciated !
A couple of gotchas with your current solution.
Using get() returns an Illuminate\Database\Eloquent\Collection object. Hence you can't use $clouds->contentID directly since $clouds is a collection (or array if you prefer). See Collection Documentation.
where(...) expects the third parameter to be a string or integer, aka single value. Instead, you are passing a collection, which won't work.
The correct way is to use whereHas() which allows you to filter through an eager loaded relationship.
Final Code:
$lists = List::with('user', 'product.photodb', 'tagCloud.tagDetail')
->whereHas('tagCloud',function($query) use ($tagID) {
return $query->where('contentID','=',$tagID);
})
->get();
See WhereHas Documentation.
What you want is whereHas()
$list = List::with(...)
->whereHas('relation', function($q) use($id) {
return $q->where('id', $id);
})->get();
Apply Where condition in you tagCloud model method tagDetail
public function tagDetail(){
return $q->where('id', $id);
}
I have News model, and News has many comments, so I did this in News model:
public function comments(){
$this->hasMany('Comment', 'news_id');
}
But I also have field trashed in comments table, and I only want to select comments that are not trashed. So trashed <> 1. So I wonder is there a way to do something like this:
$news = News::find(123);
$news->comments->where('trashed', '<>', 1); //some sort of pseudo-code
Is there a way to use above method or should I just write something like this:
$comments = Comment::where('trashed', '<>', 1)
->where('news_id', '=', $news->id)
->get();
Any of these should work for you, pick the one you like the most:
Eager-loading.
$comments = News::find(123)->with(['comments' => function ($query) {
$query->where('trashed', '<>', 1);
}])->get();
You can inject the parameter to query function by use($param) method, that allows you to use dynemic query value at runtime.
Lazy-loading
$news = News::find(123);
$comments = $news->comments()->where('trashed', '<>', 1)->get();
I couldn't help but notice, though, that what you're probably trying to do is handle soft deleting, and that Laravel has built-in functionality to help you with that: http://laravel.com/docs/eloquent#soft-deleting
You can do simply in your eloquent model file.
do like this :
public function comments_with_deleted()
{
return $this->belongsTo('Comments', 'id')->where('deleted', 1);
}
public function comments()
{
return $this->belongsTo('Comments', 'id');
}
call like this :
// for show comments with deleted
$comments = News::find(123)->with('comments_with_deleted');
// for show comments without deleted
$comments = News::find(123)->with('comments');
rmobis's answer was what I needed, but it throws an error in current Laravel 5. You have to use it as an associatve array now:
$comments = News::find(123)->with(
['comments' => function ($query) {$query->where('trashed', '<>', 1);}]
);
Took me some time to figure it out, hope this will help others.
Read more in Laravel's Docs (5.6): https://laravel.com/docs/5.6/eloquent-relationships#querying-relations