I would like to retrieve the last file inserted into my table. I know that the method first() exists and provides you with the first file in the table but I don't know how to get the last insert.
You'll need to order by the same field you're ordering by now, but descending.
As an example, if you have a time stamp when the upload was done called upload_time, you'd do something like this;
For Pre-Laravel 4
return DB::table('files')->order_by('upload_time', 'desc')->first();
For Laravel 4 and onwards
return DB::table('files')->orderBy('upload_time', 'desc')->first();
For Laravel 5.7 and onwards
return DB::table('files')->latest('upload_time')->first();
This will order the rows in the files table by upload time, descending order, and take the first one. This will be the latest uploaded file.
Use the latest scope provided by Laravel out of the box.
Model::latest()->first();
That way you're not retrieving all the records. A nicer shortcut to orderBy.
You never mentioned whether you are using Eloquent, Laravel's default ORM or not. In case you are, let's say you want to get the latest entry of a User table, by created_at, you probably could do as follow:
User::orderBy('created_at', 'desc')->first();
First it orders users by created_at field, descendingly, and then it takes the first record of the result.
That will return you an instance of the User object, not a collection. Of course, to make use of this alternative, you got to have a User model, extending Eloquent class. This may sound a bit confusing, but it's really easy to get started and ORM can be really helpful.
For more information, check out the official documentation which is pretty rich and well detailed.
To get last record details
Model::all()->last(); or
Model::orderBy('id', 'desc')->first();
To get last record id
Model::all()->last()->id; or
Model::orderBy('id', 'desc')->first()->id;
Many answers and some where I don't quite agree. So I will summarise again with my comments.
In case you have just created a new object.
By default, when you create a new object, Laravel returns the new object.
$lastCreatedModel = $model->create($dataArray);
dd($lastCreatedModel); // will output the new output
echo $lastCreatedModel->key; // will output the value from the last created Object
Then there is the approach to combine the methods all() with (last()and first()) without a condition.
Very bad! Don't do that!
Model::get()->last();` // the most recent entry
Model::all()->last();` // the most recent entry
Model::get()->first();` // the oldest entry
Model::all()->first();` // the oldest entry
Which is basically the wrong approach! You get() all() the records, and in some cases that can be 200,000 or more, and then pick out just one row. Not good! Imagine your site is getting traffic from Facebook and then a query like that. In one month that would probably mean the CO² emissions of a city like Paris in a year. Because the servers have to work unnecessarily hard. So forget this approach and if you find it in your code, replace it/rewrite it. Maybe you don't notice it with 100 data sets but with 1000 and more it can be noticeable.
Very good would be:
Model::orderBy('id', 'desc')->last(); // the most recent record
Model::latest('id')->first(); // the most recent record
Model::latest('id')->limit(1)->get(); // the most recent record
Model::orderBy('id', 'desc')->limit(1)->get(); // the most recent entry
Model::orderBy('id', 'desc')->first(); // the most recent entry
Model::orderBy('id', 'asc')->first(); // the oldest entry
Model::orderBy('id', 'asc')->limit(1)->get(); // the oldest entry
Model::orderBy('id', 'asc')->first(); // the oldest entry
If orderBy is used in this context, the primarykey should always be used as a basis and not create_at.
Laravel collections has method last
Model::all() -> last(); // last element
Model::all() -> last() -> pluck('name'); // extract value from name field.
This is the best way to do it.
You can use the latest scope provided by Laravel with the field you would like to filter, let's say it'll be ordered by ID, then:
Model::latest('id')->first();
So in this way, you can avoid ordering by created_at field by default at Laravel.
Try this :
Model::latest()->get();
Don't use Model::latest()->first(); because if your collection has multiple rows created at the same timestamp (this will happen when you use database transaction DB::beginTransaction(); and DB::commit()) then the first row of the collection will be returned and obviously this will not be the last row.
Suppose row with id 11, 12, 13 are created using transaction then all of them will have the same timestamp so what you will get by Model::latest()->first(); is the row with id: 11.
To get the last record details, use the code below:
Model::where('field', 'value')->get()->last()
Another fancy way to do it in Laravel 6.x (Unsure but must work for 5.x aswell) :
DB::table('your_table')->get()->last();
You can access fields too :
DB::table('your_table')->get()->last()->id;
Honestly this was SO frustrating I almost had to go through the entire collection of answers here to find out that most of them weren't doing what I wanted. In fact I only wanted to display to the browser the following:
The last row ever created on my table
Just 1 resource
I wasn't looking to ordering a set of resources and order that list through in a descending fashion, the below line of code was what worked for me on a Laravel 8 project.
Model::latest()->limit(1)->get();
Use Model::where('user_id', $user_id)->latest()->get()->first();
it will return only one record, if not find, it will return null.
Hope this will help.
Model($where)->get()->last()->id
For laravel 8:
Model::orderBy('id', 'desc')->withTrashed()->take(1)->first()->id
The resulting sql query:
Model::orderBy('id', 'desc')->withTrashed()->take(1)->toSql()
select * from "timetables" order by "id" desc limit 1
If you are looking for the actual row that you just inserted with Laravel 3 and 4 when you perform a save or create action on a new model like:
$user->save();
-or-
$user = User::create(array('email' => 'example#gmail.com'));
then the inserted model instance will be returned and can be used for further action such as redirecting to the profile page of the user just created.
Looking for the last inserted record works on low volume system will work almost all of the time but if you ever have to inserts go in at the same time you can end up querying to find the wrong record. This can really become a problem in a transactional system where multiple tables need updated.
Somehow all the above doesn't seem to work for me in laravel 5.3,
so i solved my own problem using:
Model::where('user_id', '=', $user_id)->orderBy('created_at', 'desc')->get();
hope am able to bail someone out.
be aware that last(), latest() are not deterministic if you are looking for a sequential or event/ordered record. The last/recent records can have the exact same created_at timestamp, and which you get back is not deterministic. So do orderBy(id|foo)->first(). Other ideas/suggestions on how to be deterministic are welcome.
You just need to retrive data and reverse them you will get your desire record let i explain code for laravel 9
return DB::table('files')->orderBy('upload_time', 'desc')->first();
and if you want no. of x last result
return DB::table('files')->orderBy('upload_time', 'desc')->limit(x)->get();
If the table has date field, this(User::orderBy('created_at', 'desc')->first();) is the best solution, I think.
But there is no date field, Model ::orderBy('id', 'desc')->first()->id; is the best solution, I am sure.
you can use this functions using eloquent :
Model::latest()->take(1)->get();
With pdo we can get the last inserted id in the docs
PDO lastInserted
Process
use Illuminate\Support\Facades\DB;
// ...
$pdo = DB::getPdo();
$id = $pdo->lastInsertId();
echo $id;
I have been working with a laravel 5.3 version and in a table i have a json column where i have saved average rating of a category table.
so, A product category table has a column "detail" as a json data type which saves avgRating.
I want to run a query inside that json column. And i want to filter that category with a average rating. So, from the frontend side rating comes in a parameter with a comma seperated so that category can be filtered with multiple ratings.
$productCategory = ProductCategory::query();
$ratings = explode(',',$params['ratings']);
$productCategory = $productCategory->whereIn('detail->avgRating',$ratings)->get();
I want to achieve something like this.
I am using Postgres
It turns out that there was too much uncertainty at the time when the question was asked. Once the asker separated the problems and figured out that the raw query of
DB::select(DB::raw("SELECT * FROM product_categories where detail->>'avgRating' in ('2.0','4.0')"));
works in Postgres, the asker from that point onwards had a much easier time figuring out the actual solution in the where clause. I presuppose that it was
detail->>avgRating
instead of
detail->avgRating
but from the comment section that was not yet confirmed. But the moral of the story is that whenever one has an eloquent problem that might be related to the RDBMS, then it makes a lot of sense to first sort out the raw query and then, having solid knowledge about what should be generated, at that point one can switch to the Eloquent code and apply the solution there.
You should use whereJsonContains or whereRaw:
$productCategory->whereJsonContains('detail->>avgRating',$ratings)->get();
OR
$productCategory->whereRaw('JSON_CONTAINS(detail->>avgRating, ?)', $ratings)->get();
I'm currently working on a Symfony project, using Doctrine to manage entities.
I have a table named User, containing a few columns, and then another table named Tag, containing a foreign key to that User table with a ManyToOne relation based on the user id, and a single other column named value.
In my app, I need to find a list of users, depending on one of the Tag row, AND the value of one of the User's column. Let's resume :
Select all users where user.value equals somevalue AND Tag.value equals anothervalue.
As I never used Symfony nor Doctrine before this project, I searched into Doctrine documentation and found about the Query Builder. So, I did this :
EDIT : The way I was doing it was kinda weird, so I modified it and here is the result :
public function findByTagAndApp($tag, $app)
{
$em = $this->getEntityManager();
$qb = $em
->getRepository('APIBundle:User')
->createQueryBuilder('u')
->leftJoin('APIBundle\Entity\Tag', 't')
->where('u.application = :app')
->andWhere('t.tag = :tag')
->setParameter('tag', $tag)
->setParameter('app', $app)
;
$users = $qb->getQuery()->getResult();
return $users;
}
And it seems like it works, but in a strange way. Instead of returning an array of User items, which is what I want, it returns an array of array of User items. The first array is always containing two entries, and these two entries are always identical : they are the array I need, without a single difference.
I tried to do return $users[0] instead of just users, and then I can manipulate my User entities the intended way. I could keep it this way as it is working, but I'd really like to know why it returns an unneeded array of array instead of just the array I want. It might be my query, but I'm not sure how to modify it to get only the Users I want.
Any clues on why it behave like this would be really appreciated, as I'm still learning about Doctrine. Thanks !
EDIT² : Nevermind, this query seems completely incorrect too, as I got all users according to the $app value, but it seems like it never check if there is a row in the Tag table with a value of somevalue associated to a foreign key of the User table..
I don't know exactly why it is but..
I think you have to mention from() like ->from('User', 'u')
for extra you can find here
After a few hours of tweaking, I figured it out using SQL statement on PhpMyAdmin, so I could notice that there was a LOT of things that I was doing wrong :
First, the join was not correct. My goal was to collect users that had a certain value in their own table, AND a value from the Tag table. Using a left join, I was collecting users with their own value OR a the value from the Tag table.
Second : The $app value I was passing was an object of type Application (the Application field in my User table is a foreign key), and the query builder didn't know what to do with it. Passing the app_id instead of the app object solved the problem.
Third : The way I collected result was wrong. Obviously, this query returns an array of User objects. And as I execute this query multiple times in a row, I had an array on which I used array_push to fill it with the data, thinking that pushing array1 with array2 would put array2 values into array1, but it was just putting array2 into array1, resulting to that array of arrays that was the initial problem. Using array_merge instead of array_push, I am now able to collect all the results from the queries into a single array. A little array_unique on that to avoid redundancy, and everything is working as expected.
Thanks to everyone who replied !
I have to call the $model->groupBy(?allcols?) function with all columns as a param.
How should I do this?
Edit: I have all Columns as an Array, so i can't pass them like 'col1','col2',...
I'm asking this because i have this poblem (github) and i found out, that there the prob is on Line 119.
I tried it manually like col1,col2 which worked, but it should by dynamically for all models.
I found this snippet, to get all cols from the current table as an array, but i can only pass a String.
Ok, if I'm understanding your edit correctly, you've got an array of column names you wish to group by. If $model is the name of your query, I'd recommend just using a foreach loop and appending each field:
foreach($allcols as $col){
$model->groupBy($col);
}
$model->get();
There is no such function for grouping all columns but you may use groupBy(col1, col2, ...), for example, if you have a posts table then you may use:
DB::table('posts')->groupBy('col1', 'col2')->get();
Or using Eloquent Model, for example a Post model:
Post::groupBy('col1', 'col2')->get();
If all you're trying to do is get rid of duplicate records (which is all that groupBy(all) would do as far as I can envision), you could also just use $model->distinct() instead. However, unless you add a select() to exclude the id field, you're going to wind up with the full recordset with no grouping, as by definition the id is unique to each record and thus won't collapse across records by either manner.
For example I have the following tables in my database:
People
Groups
And in the People table I have the following columns:
Name
Birthdate
Group
In the Groups table I have the following columns:
Name
Colour
Now I want to fetch results from my database to make a list of all the People.
So I would use this:
$this->set('people', $this->Person->find("all"));
And obviously in my view I would loop through the returned array and display it. Now I also want to find out for each person in the list what Colour and Group name they are (retrieved from the groups table).
How would I go about this in CakePHP.
First make sure your model relationships are defined. Second, you might want to consider using "id" fields for your related tables (I assume you did and maybe just did not include them in your original questions table definitions).
And yes, run debug($this->Person->find("all")) as Elwhis noted to see what your array is dumping out.
And if this is a mission critical application, be sure to use containable instead of recursive to prevent taxing queries to your db.
You have to set the recursive attribute. But I guess it should work with the default value. Put this line in your controller debug($this->Person->find("all")) and check whether the data doesn't already contain you desired group information.
If not, try setting $this->Person->recursive = 1; before calling the find() function
For more information about recursive: http://book.cakephp.org/view/1063/recursive