Eloquent, multiple where clause with newest record - php

In laravel, I have a simple call that hits the userRecord table with a given email and grabs the first one.
This works but I want to check the created_at column and valid column as well to get the newest one that's valid (newest created_at date where today is before the valid date)
Existing line:
$get= (userRecord::where('email', $request->query->get('email')->where(curdate() < 'valid'))->first());
So rather than just getting the first, I want to add those column conditions. But I can't quite reconcile how to use the multiple where conditions and replace the first() call with just the newest

In laravel you can make multiple wheres like this:
->where([['first_where'],['second_where'],['n_where']])
About the newest:
You can order by the created_at and use desc (bigger to small) like this:
->orderBy('created_at','desc')
And then, you can use the first method

Related

How to get latest record in Laravel 9 [duplicate]

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;

Is it possible to search a table in reverse to get latest data quickly?

I have a table with several million records.
The table has a long string as a key, and searching for records, especially new ones, is very slow.
I have tried to narrow the search to whereDate >= this week, or whereID >= 999999 but this doesn't give a huge performance boost.
We are using Laravel. Is there some kind of feature to search a table from the bottom up or in reverse, instead of searching incrementally from the top down? Something like Model::findBackwards($key) that would start looking at the most recent record and process backwards would be ideal in this situation.
How would you approach this problem?
Edit - here is our current query. It's a job running on horizon
if (DB::table('big_table_with_a_stupid_key')
->whereDate('created_at', '>=', '2019-11-10')
->where('hash', $this->hash)
->increment('counter')
);
else {
DB::table('big_table_with_a_stupid_key')->where(['hash' => $this->hash])->increment('counter');
}
If you want to reverse order of the result, you can use latest() function.
Laravel documentation says: https://laravel.com/docs/6.x/queries
latest / oldest
The latest and oldest methods allow you to easily order results by date. By default, result will be ordered by the created_at column. Or, you may pass the column name that you wish to sort by:
$user = DB::table('users')->latest()->first(); // order by created_at
$user = DB::table('users')->latest('id')->first(); // order by id
You will want to do this by using the ORDER BY clause in your underlying database query. Laravel (of course) exposes this with ->orderBy()
https://www.tutorialsplane.com/laravel-order-by-asc-desc/
The SQL engine will place the result rows in the requested sequence before returning them to you.
Then, to address your performance issues, be sure that any column that you routinely use for searching has an index. This is the secret to maintaining good performance as the number of rows increases.

Laravel. I can't read the data from the column

I have a problem.
Needs to get the first date of creation of data in the table by the currently logged in user.
Working example:
$howMuchIPlay = Game::all('user_id')->where('user_id', '=', Auth::user()->id)->count();
Not working example:
$firstVoteInGame = Game::all('created_at')->first()->where('user_id','=', Auth::user()->id);
When I use count() function I get value 38. This is all the rows for the user, but I want to get only the earliest (first). How can I do this?
Sorry for my english and thank you in advance for help.
$firstVoteInGame = Game::where('user_id', '=', Auth::user()->id)->oldest()->first();
This will get the earliest (oldest) record from the current authenticated user.
You got the order wrong.
You should first limit by user Id.
Then order by created at in descending order so oldest is on top. Or if you want the newest, order by 'desc' instead of 'asc'
Then get the first.
Game::where('user_id','=', Auth::user()->id)->orderBy('created_at','asc')->first();
What you did was:
Get all records from database in a collection.
get first possible record from collection at index 0
limit a model object by a where query(it would fail here since you were in a model object, not a collection or query builder instance);
Your not working example, $firstVoteInGame = Game::all('created_at')->first()->where('user_id','=', Auth::user()->id);, starts off with Game::all('created_at').
What this means is that all Games are returned, but these are limited to the 'created_at' column only (see the documentation here).
Since you're limiting your result to the 'created_at' column, Eloquent will now not be able to compare the 'user_id' columns to the authenticated user id.
In addition, even if you were to select all columns (by performing Game::all()), you are calling ->first() after which you only have the first row remaining.
You say you want to
get the first date of creation of data in the table by the currently logged in user.
This would thus by done by:
$firstVoteInGame = Game::where('user_id', Auth::user()->id)->orderBy('created_at','asc')->first('created_at');
Why you use 'created_at' for ordering as easy/correct way is use primary key, Because you can just do:
$firstVoteInGame = Game::where('user_id','=', Auth::user()->id)->orderBy('id', 'desc')->first();
You can try, if you still want 'created_at':
$firstVoteInGame = Game::where('user_id','=', Auth::user()->id)->orderBy('created_at', 'desc')->first();
TIP
- The Eloquent all method will return all of the results in the model's table so avoid to use it with first method

Mongodb distinct records from last record not from first

In mongodb php, I need to get a distinct list of records based on one field but the search should start from the last record.
db.collection.distinct doesn't sort records and doesnt work with a paginated data set, and it's not given the way it searches for distinct values: any order you see is incidental and could change with implementation or access plan.

Reordering MySQL

I have probably a very simple question.
I have a MySQL database called "alldata", which contains various variables. The first column called LogDateTime contains date and time. Now the thing is that I want the db to be sorted from the oldest to the newest - in other words by column 1.
I know how to do a MySQL query using ORDER BY Logdatetime etc. But what I would like to do is to reorder tha data in the actual database and save it ordered. Right now there are some dates a bit messed up. Then I would not have to use the ORDER BY statement in all my queries because the database would already be sorted.
Could anyone please just give me the SQL command I should use to reorder the entire database?
You cannot setup a relational database table to return results ordered by a specific column of your choosing. You need to use ORDER BY. You could work around this by using views.
The view definition would include an ORDER BY. You could select from the view and it would show results in your desired order.
CREATE OR REPLACE VIEW `mytable_view` AS SELECT * FROM `my_table` ORDER BY `my_date_column`
Then you can select the data:
SELECT * FROM `mytable_view`
Results are shown in desired order.

Categories