Ad

How To Get The Last Record Using Eloquent Scope?

- 1 answer

I have a Posts table structured like this:

enter image description here

Now I'm trying to get the latest post which is obviously the record with id = 2.

I have this in my theme page posts.htm:

[builderList postLatest]
modelClass = "Me\Articles\Models\Posts"
scope = "scopeLatest"
scopeValue = "{{ :scope }}"
displayColumn = "title"
noRecordsMessage = "No records found"
detailsPage = "-"
detailsUrlParameter = "slug"
pageNumber = "{{ :page }}"

in my model Posts I have:

public function scopeLatest($query)
{
  return $query->orderBy('created_at','desc')->first();
}

But this one is returning both records. I also tried using latest()

return $query->latest();

And this one gives me the error:

Maximum function nesting level of '1000' reached, aborting!

Even tried passing parameter like latest('created_at') but got the same error.

Tried dumping dd($query->orderBy('created_at','desc')->first()->toSql()) and got select * from posts where posts.deleted_at is null

  1. Why first() is not limiting to 1 record?
  2. Why latest() is throwing me Maximum error? Is this version specific bug? It seems I cant find documentation related to it. I have Laravel 5.5.48.

I'm not sure now what can I use. Maybe I'm doing something wrong here. I just need to get the latest post.

Ad

Answer

The solution to your problem is using the ->take(1)method. There are more methods applicable to queries but here is the list of available methods you can run on a collection instance. I believe Builder expects scopes to return a query {[a collection of models]}. I took some time to do testing and in my opinion this might just be a flaw in the Builder Plugin construction.

Now before you look at my research below. I would say you should learn to build your own components like Hardik suggests in a comment. Hope this all helps.

So here is a scope I have for a plugin:

public function scopeFilterTypes($query) {
    return $query->whereNotIn('slug', [
        'range', 
        'close',
        'all', 
        'single',
        'three',
        'five',
        'self'
        ])->first();
}

Here is a picture of my backend form which correctly only sees one item in the relationship (this is why I am using a scope):

enter image description here

Now look at this image of my builder component You can see that it even ignores my ->whereNotIn([]) method on the query:

enter image description here

To prove my finding on this flaw in the builder component I do a find($id) method which would return a model instance not a collection of models. Using the find($id) method also gives me the correct result in the backend form but in the Builder list shows me all the records which is incorrect.

However when I change the scope to ->take(1):

public function scopeFilterTypes($query) {
    return $query->whereNotIn('slug', [
        'range', 
        'close',
        'all', 
        'single',
        'three',
        'five',
        'self'
        ])->orderBy('created_at','desc')->take(1);
}

I get this in the backend form; working correctly: enter image description here

And I get this from the builder list:

enter image description here

Ad
source: stackoverflow.com
Ad