Laravel: How to get last N entries from DB - php

I have table of dogs in my DB and I want to retrieve N latest added dogs.
Only way that I found is something like this:
Dogs:all()->where(time, <=, another_time);
Is there another way how to do it? For example something like this Dogs:latest(5);
Thank you very much for any help :)

You may try something like this:
$dogs = Dogs::orderBy('id', 'desc')->take(5)->get();
Use orderBy with Descending order and take the first n numbers of records.
Update (Since the latest method has been added):
$dogs = Dogs::latest()->take(5)->get();

My solution for cleanliness is:
Dogs::latest()->take(5)->get();
It's the same as other answers, just with using built-in methods to handle common practices.

Dogs::orderBy('created_at','desc')->take(5)->get();

You can pass a negative integer n to take the last n elements.
Dogs::all()->take(-5)
This is good because you don't use orderBy which is bad when you have a big table.

You may also try like this:
$recentPost = Article::orderBy('id', 'desc')->limit(5)->get();
It's working fine for me in Laravel 5.6

I use it this way, as I find it cleaner:
$covidUpdate = COVIDUpdate::latest()->take(25)->get();

Ive come up with a solution that helps me achieve the same result using the array_slice() method. In my code I did array_slice( PickupResults::where('playerID', $this->getPlayerID())->get()->toArray(), -5 ); with -5 I wanted the last 5 results of the query.

The Alpha's solution is very elegant, however sometimes you need to re-sort (ascending order) the results in the database using SQL (to avoid in-memory sorting at the collection level), and an SQL subquery is a good way to achieve this.
It would be nice if Laravel was smart enough to recognise we want to create a subquery if we use the following ideal code...
$dogs = Dogs::orderByDesc('id')->take(5)->orderBy('id')->get();
...but this gets compiled to a single SQL query with conflicting ORDER BY clauses instead of the subquery that is required in this situation.
Creating a subquery in Laravel is unfortunately not simply as easy as the following pseudo-code that would be really nice to use...
$dogs = DB::subQuery(
Dogs::orderByDesc('id')->take(5)
)->orderBy('id');
...but the same result can be achieved using the following code:
$dogs = DB::table('id')->select('*')->fromSub(
Dogs::orderByDesc('id')->take(5)->toBase(),
'sq'
)->orderBy('id');
This generates the required SELECT * FROM (...) AS sq ... sql subquery construct, and the code is reasonably clean in terms of readability.)
Take particular note of the use of the ->toBase() function - which is required because fromSub() doesn't like to work with Eloquent model Eloquent\Builder instances, but seems to require a Query\Builder instance). (See: https://github.com/laravel/framework/issues/35631)
I hope this helps someone else, since I just spent a couple of hours researching how to achieve this myself. (I had a complex SQL query builder expression that needed to be limited to the last few rows in certain situations).

For getting last entry from DB
$variable= Model::orderBy('id', 'DESC')->limit(1)->get();

Imagine a situation where you want to get the latest record of data from the request header that was just inserted into the database:
$noOfFilesUploaded = count( $request->pic );// e.g 4
$model = new Model;
$model->latest()->take($noOfFilesUploaded);
This way your take() helper function gets the number of array data that was just sent via the request.
You can get only ids like so:
$model->latest()->take($noOfFilesUploaded)->puck('id')

use DB;
$dogs = DB::select(DB::raw("SELECT * FROM (SELECT * FROM dogs ORDER BY id DESC LIMIT 10) Var1 ORDER BY id ASC"));

Dogs::latest()->take(1)->first();
this code return the latest record in the collection

Can use this latest():
$dogs = Dogs::latest()->take(5)->get();

Related

Turning 3 SQL queries into 1

I am trying to get a list of calendars - some public some private. Access to the private calendars is managed through a bridging table that lists calendar id (ccalId) and user id (cuserId). I can achieve this but using 3 SQL queries.
Is it possible to achieve this using just one query? I have tried JOINs but it never seems to work.
$calModel->where('calTeam',session()->get('teamId'));
$calModel->where('calType','public');
$calModel->where('calStatus','active');
$data = $calModel->get()->getResultArray();
$calUserModel->select('ccalId');
$calUserModel->where('cuserId', session()->get('id'));
$callist = $calUserModel->get()->getResultArray();
$newarray = implode(", ", $callist);
$calModel->where('calTeam',session()->get('teamId'));
$calModel->whereiI('id', $newarray);
$data2 = $calModel->get()->getResultArray();
$data = array_unique(array_merge($data,$data2), SORT_REGULAR);
Not every time the codeigniter query builder is the best solution. In my opinion for more complex queries it is better to do direct query to the database, instead of using models.
You can easily do a query with 2 joins to get all the results without the useless data. That would work faster and would look cleaner in your code.

Using two columns in where Laravel ORM

I have two columns in my table: max and current. I want to build simple scope
public function scopeNotMax($query)
{
return $query->where('max', '>', 'current');
}
But Laravel gives me that query:
SELECT * FROM table WHERE `max` > 'current'
I don't want this result and I know that I can use in this place whereRaw() or DB::raw(). But I can't find another way to say "hey, this is column, not string!'. Can I do it? Or I must use raws? I want to avoid it.
There is no other way.
where() method in this case add third parameter (value) to bindings and passes it ot PDO library. So it will be escaped.
Alternatively You can pass as third parameter a Closure, but then laravel will form a sub-select for You, which doesn't helps much.
Looks like whereRaw() is made for this kind of sitiuation.
Did you give a try with this ? return $query->where('max > current');
you can use whereRaw():
->whereRaw('table_1.name = table_2.name');
You exmaple code:
->whereRaw('max>current');

Laravel 5 eloquent whereIn

Hope anybody can help me, I need to search for items that have category id = x in the database
Example table items
id,cats,name etc...
cats = '1,19' or maybe just '19' or maybe '1,9'
So for this example I need a to search for items that have cats with 9
I tried this but when I search for 9 it also shows 19
$items = Items::where(function($query)use($cat) {
$query->where('cats', 'like', '%,'.$cat->id.'%');
$query->orWhere('cats', 'like', '%'.$cat->id.',%');
$query->orWhere('cats', 'like', '%'.$cat->id.'%');
})->orderBy('updated_at', 'DSC')->get();
I also tried something
$items = Items::whereIn(explode(',', 'cats'), $cat->id)->get();
but it doesn't work
Appreciate any help to find the easiest and shorts way of doing this, regards
It's quite hard to understand what you want to achieve but I'll try. First of all as #particus mentioned the best way is to create pivot table when you don't need to worry about such things.
But the solution if you have list of ids in a columns separated by coma is not storing values like
1,2,3
but always adding , at the beginning and at the end, so it should be in this case:
,1,2,3,
This way, if you have in your table ,19,2,3, and you want to search for value 9, you should use look for ,9, string, for example:
$id = 9;
$items = Items::where('column', LIKE '%,'.$id.',%')->get();
Now for above string no record will be found, but if you have ,9,2,3, or just ,9, the desired record will be found.
Assuming you're using MySQL, you can use the FIND_IN_SET function.
$items = Items::whereRaw("FIND_IN_SET(".$cat->id.", cats)")->orderBy('updated_at', 'DESC')->get();
Please note, this will not use any indexes defined on the cats column. Storing array like data in a field is usually a big red flag. You would benefit by normalizing this out now, rather than trying to work around the current design.

Mysql rand() function in Zend framework 2

In zend framework 1, we had used mysql rand() function like below or using zend_db_expr(). I have tried this in ZF2, but this is not working. Somebody please help me to use this in Zend Framework 2
$select = $this->db()->select()
->from('TABLE')
->order('RAND()');
Thanks,
Looking at the API it appears that the order function accepts a string or array of parameters order(string | array $order). My first thought was to use a key/val array. However, as I look at the actual code of the Db\Sql\Select, the string or array that you are passing gets quoted (see here). Assuming that your Db platform is Mysql, this is the function that quotes the fields (see here). It appears to iterate through each of the fields, and add these quotes, rendering your rand() function a useless string.
Getting to the point, the solution is up to you, but it does not appear that you can do it the way you want with this current version of ZF2.
You will need to extend the Db\Sql\Select class, OR extend the Db\Adapter\Platform\Mysql class, OR change the code in these classes, OR execute your query as a full select statement, OR change up your logic.
By changing up your logic I mean, for example, if your table has an Integer primary key, then first select the MAX(id) from the table. Then, choose your random numbers in PHP prior to executing your query like $ids[] = rand(1, $max) for as many results as you need back. Then your sql logic would look like SELECT * FROM table WHERE id IN(453, 234, 987, 12, 999). Same result, just different logic. Mysql's rand() is very "expensive" anyways.
Hope this helps!
Here you can use \Zend\Db\Sql\Expression. Example function from ModelTable:
public function getRandUsers($limit = 1){
$limit = (int)$limit;
$resultSet = $this->tableGateway->select(function(Select $select) use ($limit){
$select->where(array('role' => array(6,7), 'status' => 1));
$rand = new \Zend\Db\Sql\Expression('RAND()');
$select->order($rand);
$select->limit($limit);
//echo $select->getSqlString();
});
return $resultSet;
}

Kohana orm order asc/desc?

I heed two variables storing the maximum id from a table, and the minimum id from the same table.
the first id is easy to be taken ,using find() and a query like
$first = Model::factory('product')->sale($sale_id)->find();
but how can i retrieve the last id? is there a sorting option in the Kohana 3 ORM?
thanks!
Yes, you can sort resulting rows in ORM with order_by($column, $order). For example, ->order_by('id', 'ASC').
Use QBuilder to get a specific values:
public function get_minmax()
{
return DB::select(array('MAX("id")', 'max_id'),array('MIN("id")', 'min_id'))
->from($this->_table_name)
->execute($this->_db);
}
The problem could actually be that you are setting order_by after find_all. You should put it before. People do tend to put it last.
This way it works.
$smthn = ORM::factory('smthn')
->where('something', '=', something)
->order_by('id', 'desc')
->find_all();
Doing like this, I suppose you'll be :
selecting all lines of your table that correspond to your condition
fetching all those lines from MySQL to PHP
to, finally, only work with one of those lines
Ideally, you should be doing an SQL query that uses the MAX() or the MIN() function -- a bit like this :
select max(your_column) as max_value
from your_table
where ...
Not sure how to do that with Kohana, but this topic on its forum looks interesting.

Categories