I am working a project and I would want to use a where clause, paginate and then sort in the collection in specific order. I have tried the result below but keeps throwing the errors below Method:
Illuminate\Database\Eloquent\Collection::links does not exist. (View:
/Applications/XAMPP/xamppfiles/htdocs/vermex/resources/views/equipments.blade.php)
The Product model is where I am getting the data and store in a variable called $equipment. If there is a better way of doing this, please help.
public function equipments()
{
$equipments = Product::where('product_category_id', 3)->paginate(2)-
>sortByDesc('id');
return view('equipments', compact('equipments'));
}
Try putting the orderBy before the paginate
$equipments = Product::where('product_category_id', 3)->orderBy('id', 'desc')->paginate(2);
sortByDesc is a collection method.
paginate will need to be last for links to be available in the blade view.
Related
I'm fetching record for multiple section in a view. To show complete data I am simply doing
$data = Data::all();
Then simply getting counts for each section as required.
For example:
{{count($data->where('status', 'HOLD'))}}
For another section on the same view I want to show result with Groupy
For Example:
#foreach($data->paginate()->groupBy('user_id') as $byUser)
#endforeach
Then show the pagination
{{$data->links()}}
I have already tried by separating the result in the controller and Calling the data using different methods.
$data = Data::all();
$userData = Data:paginate(5)->groupBy('user_id');
return view('data.all', compact('data', 'userData'));
This is working well without pagination. After adding pagination I am getting below error.
Method Illuminate\Database\Eloquent\Collection::paginate does not exist. (View: C:\xampp\htdocs\project\resources\views\data\all.blade.php)
Is there any way to work it out? Thanks.
Check this line:
$data = Data::all();
Here you are already executing the query, this means, a Collection instance is returned. That's why you can't use the paginate() method, because that is a QueryBuilder method.
Try this:
$userData = Data::groupBy('user_id')->paginate(5);
return view('data.all', compact('data', 'userData'));
I am trying to paginate an eloquent object but i can't get it to work. The paginate throws a error because $products is not a query builder object but a collection.
// i get this value from a $POST variable
$customOrderIds = [3,2,1,4,6,5,9,8,10,7,11,12,13,14,15,16,17,20,18,19,21,22]; // I want the products ordered in this sequence
$products = Product::get()->sortBy(function($product) use($customOrderIds)
{
return array_search($product->id, $customOrderIds);
});
$products->paginate(5); // Error is thrown here
I want to keep the order of products that is defined in the $customOrderIds
In other questions they suggest to replace get() function with the paginate function but then my custom order will be only applied to the 5 items in the pagination.
I would rather not use anything with raw sql
paginate is an Eloquent method, so it won't work on your collection. However, collections have a forPage method, which you can use:
The forPage method returns a new collection containing the items that would be present on a given page number. The method accepts the page number as its first argument and the number of items to show per page as its second argument
So what you'll need is
$products->forPage(1, 5);
You have to indeed replace the get with the paginate, but you'll have to do the sorting before you paginate. You can try something along the lines of:
Product::orderByRaw(
'FIELD(id,3,2,1,4,6,5,9,8,10,7,11,12,13,14,15,16,17,20,18,19,21,22)'
)->paginate(5);
Sources:
https://laravel.com/docs/5.8/queries#raw-expressions
https://laracasts.com/discuss/channels/eloquent/custom-orderby-in-laravel-query-builder
I'm trying to achieve pagination and it is working absolutely fine until I add sortByDesc() along with my eloquent query.
web.php (route file)
Route::get('/', function(){
$posts = Post::simplePaginate(5)->sortByDesc("post_id");
//sortByDesc("post_id") this causes the problem
}
When I prepare the view for the pagination with {{ $posts->links() }} in the specified view, I get the following error-
Method links does not exist
If I remove the sorting condition from the query, it works perfectly.
What can be the reason behind this behaviour?
Try putting the sort on the query rather than the pagination:
Post::orderBy('post_id', 'desc')->simplePaginate(5);
To extend to what #RossWilson said.
sortBy is a collection function, not an eloquent function, the correct eloquent function is orderBy.
Also, see simplePaginate() as if you were performing a get(), first(), find().
What would you place first the get or the order? ... maybe the get if you want to order a collection (with sortBy), but since simplePaginate does not return the same collection that a get() would return, sortby does not work. And probably messes up the pagination object/collection.
I am trying to make a filter in laravel. This following filter works
$posts= Post::where('category',$request->category)->orderBy('id','desc')->paginate(10);
But when I try to do something like this
public function index(Request $request)
{
$posts= Post::where('category',$request->category)->get();
$posts->latest()->paginate(10);
dd($posts);
It doesn't work. Can someone explain why is this and provide me the code that works. My project have multiple filter.
Error
Because $posts = Post::all(); already execute a query.
Post::where('category',$request->category)->latest()->paginate(10)->get();
would be what you want.
A note:latest requires the created_at column
You should go
$posts = Post::where('category',$request->category)->latest()->paginate(10);
the get request is unnecessary as the paginate will execute the query.
The first one makes the query by pagination i.e fetch 10 records per constructed page
For the second one, based on observation, you most likely have encountered at least 2 errors:
The first, on the line that used the get method because that method requires at least one parameter.
Type error: Too few arguments to function Illuminate\Support\Collection::get()
The other since its a collection, and since there is nothing like paginate or latest method on collection therefore throws other errors. You should check Collection's Available methods to have a glimpse of the methods allowed on collection.
One of the best solutions is to simply order the result when making the query:
Blog::where('category',$request->category)
->orderBy('created_at', 'desc') //you may use also 'updated_at' also depends on your need
->paginate(10);
This way you have the latest coming first int the pagination and also having not worrying about paginating a collection
I'm trying to get a single column value from the first result of a Model's belongsToMany relationship query, as i'm returning the ->first() result of the relationship I was hoping $code->reward->title would work but it doesn't.
I get an Relationship method must return an object of type Illuminate\Database\Eloquent\Relations\Relation error
What I'm trying to do is the get the title of the current reward that is linked to a specific code - the code_reward pivot table has a valid_from and expires_at date as the reward linked to a code will change as time goes by, hence the need to get the currently active reward for that code.
Here's my code:
Model: Code
public function rewards()
{
return $this->belongsToMany('App\Reward')->withPivot('valid_from', 'expires_at')->withTimestamps();
}
public function reward()
{
$now = Carbon::now();
return $this->rewards()
->wherePivot('valid_from', '<', $now)
->wherePivot('expires_at', '>', $now)
->first();
}
Controller: CodeController
public function index()
{
$codes = Code::all();
return view('codes/index')->with('codes', $codes);
}
View: Codes/index
#foreach ($codes as $code)
{{$code->id}}
{{$code->reward->title}}
#endforeach
Any help is really appreciated!
Update
Unfortunately both suggestions below ($code->reward()->title and getRewardAttribute() return an Trying to get property of non-object error.
If I remove ->first() from the Code->reward() method and replace $code->reward->title with $code->reward->first() in the view it echoes out the whole reward model as json, however $code->reward->first()->title still returns the Trying to get property of non-object error
Update 2
If I do {{dd($code->reward->title)}} in the view I get the reward title but if I just do {{$code->reward->title}}, I don't!
AND the $code->reward->title works as expected in a #Show view, so could it be that the collection of codes supplied by the controller's #index method isn't passing the necessary data or not passing it in a necessary format??
SOLVED
The issue was caused by one of the $code->rewards in the foreach loop in the index view returning null! The first one didn't, hence the dd() working but as soon as the loop hit a null it crashed.
Once I wiped and refreshed the db (and made sure my seeds where adding only valid data!) it worked. Doing {{$code->reward ? $code->reward->title : ''}} fixed the issue. Grrr.
Your statement is failing because $code->reward->title tells Laravel that you have defined a relationship on your Code model in a method called reward(). However, your relationship is actually defined in the method rewards(). Instead, reward() is a custom method on the model that you have made up. Calling it as a method and not a relation is the quickest way to get what you want.
{{$code->reward()->title}}
As #andrewtweber points out below, you could also make your custom reward() method into an attribute accessor. To do that, just rename the function to getRewardAttribute() and then you can call it in your view like you originally did.
Alternatively, you could get rid of that reward() method entirely and move all of that logic to the controller, where it probably makes more sense. You'd have to use constrained eager loading to pull that off. So in your controller you'd have something like this:
$codes = App\Code::with(['rewards' => function ($query) {
$query->wherePivot('valid_from', '<', $now)
->wherePivot('expires_at', '>', $now);
])->get();
Of course, this would return all of your filtered codes. This is because you cannot apply a sql limit inside a nested eager relationship as outlined here. So in your view, you would then have to do something like this:
{{$code->rewards->first()->title}}
However, it will be simpler to go with my first solution, so that's entirely up to you.
Try to set this method in Code Model, because query builder treats valid_from and expired_at as string, not date?
public function getDates()
{
return ['valid_from','expired_at'];
}