Kohana orm order asc/desc? - php

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.

Related

Comparing two columns in Laravel 5

I am using Laravel
Let's say, I have two date fields in my table. If I want to compare them, i can do whereRaw clause.
$query->whereRaw('date1 > date2')->get()
Is there a way to make a modification to date2 inside this query, so it is actually date2-1day?
Something like:
$query->whereRaw('date1 > (date2-1day)')->get()
You are free to call any SQL code in the "raw" part of your query, so you could do sth like below:
$query->whereRaw('date1 > DATE_SUB(date2, INTERVAL 1 DAY)')->get();
Keep in mind that executing SQL code this way will make your queries work only in databases that support such functions.
Another way would be using whereColumn like
$users = DB::table('users')
->whereColumn('updated_at', '>', 'created_at')
->get();
OR
UserTable::whereRaw('column1 != column2')->get();

Laravel Eloquent return count of each group with groupBy()

I want to groupBy() task using Laravel Eloquent. I have searched Internet and didn't find anything with eloquent.
some people used groupBy() query with Query Builder like this link
But I want to create query like this style:
Task::select('id')->groupBy('category_id')->count();
This code just return only count of first category_id. But I want count of all the category_id.
Native Collection alternative (grouped by php, not mysql). It's a nice option when you have the Collection as variable already assigned. Of course is less optimal than mysql grouping in most cases.
$tasks->groupBy('category_id')->map->count();
You should add the count to the select function and use the get function to execute the query.
Task::select('id', \DB::raw("count(id)"))->groupBy('category_id')->get();
The \DB::raw() function makes sure the string is inserted in the query without Laravel modifying its value.
More simple:
Task::select('id')->groupBy('category_id')**->get()**->count();
You can do something like this:
return DB::table('offers')->select('*', DB::raw('count('.$field.') as total_count'))->groupBy($field)->get();
I overrode the count() method in my model. Could be something like:
public function count($string = '*'){
$tempmodel = new YourModel();
return $tempmodel ->where('id',$this->id)->where('category_id',$this->category_id)->count($string);
}
This gave me exactly the behavior of count() I was looking for.
Worked for me as
we need to select one column like 'category_id' or 'user_id' and then
count the selected column on get()
Task::select('category_id')
->where('user_id',Auth::user()->id)
->groupBy(['category_id'])
->get()
->count();
This works for me.
output:
return $email_trackers = EmailTracker::get()->groupBy('campaign_id')->map->count();
{
"6": 2
}

Laravel: How to get last N entries from DB

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();

Codeigniter, join of two tables with a WHERE clause

I've this code:
public function getAllAccess(){
$this->db->select('accesscode');
$this->db->where(array('chain_code' => '123');
$this->db->order_by('dateandtime', 'desc');
$this->db->limit($this->config->item('access_limit'));
return $this->db->get('accesstable')->result();
}
I need to join it with another table (codenamed table), I've to tell it this. Not really a literal query but what I want to achieve:
SELECT * accesscode, dateandtime FROM access table WHERE chain_code = '123' AND codenames.accselect_lista != 0
So basically accesstable has a column code which is a number, let us say 33, this number is also present in the codenames table; in this last table there is a field accselect_lista.
So I have to select only the accselect_lista != 0 and from there get the corrisponding accesstable rows where codenames are the ones selected in the codenames.
Looking for this?
SELECT *
FROM access_table a INNER JOIN codenames c ON
a.chain_code = c.chain_code
WHERE a.chain_code = '123' AND
c.accselect_lista != 0
It will bring up all columns from both tables for the specified criteria. The table and column names need to be exact, obviously.
Good start! But I think you might be getting a few techniques mixed up here.
Firstly, there are two main ways to run multiple where queries. You can use an associative array (like you've started to do there).
$this->db->where(array('accesstable.chain_code' => '123', 'codenames.accselect_lista !=' => 0));
Note that I've appended the table name to each column. Also notice that you can add alternative operators if you include them in the same block as the column name.
Alternatively you can give each their own line. I prefer this method because I think its a bit easier to read. Both will accomplish the same thing.
$this->db->where('accesstable.chain_code', '123');
$this->db->where('codenames.accselect_lista !=', 0);
Active record will format the query with 'and' etc on its own.
The easiest way to add the join is to use from with join.
$this->db->from('accesstable');
$this->db->join('codenames', 'codenames.accselect_lista = accesstable.code');
When using from, you don't need to include the table name in get, so to run the query you can now just use something like:
$query = $this->db->get();
return $query->result();
Check out Codeigniter's Active Record documentation if you haven't already, it goes into a lot more detail with lots of examples.

Doctrine: How can I have a where clause included only when necessary in a query?

I want to use a single query to retrieve:
items of any categories (no filter applied);
only items of a single category (limited to a particular category);
For that purpose I should be able to write a Doctrine query which would include a where clause only when certain condition is met (eg. part of URL existing), otherwise, where clause is not included in the query.
Of course, i tried with using the If statement, but since doctrine query is chained, the error is thrown.
So i guess the solution might be some (to me unknown) way of writing doctrine queries in an unchained form (by not having each row started with "->" and also having each row of a query ending with semicolon ";")
That way the usage of IF statement would be possible i guess.
Or, maybe there's already some extremely simple solution to this matter?
Thanks for your reply!
I am unfamiliar with Codeigniter but can't you write something like this?
$q = Doctrine_Query::create()
->from('items');
if ($cat)
$q->where('category = ?', $cat);
In your model pass the condition for where as a parameter in a function.
In below example i am assuming the function name to be filter_query() and passing where condition as a parameter.
function filter_query($condition=''){
$this->db->select('*');
$this->db->from('TABLE NAME');
if($condition != ''){
$this->db->where('condition',$condition);
}
}
In above example i have used Codeigniter's Active Record Class.

Categories