I'm adding some custom functionality to OsTicket (1.10) but I can't figure out how to filter tickets of multiple departments.
What I'm doing is:
$departments = [1, 4, 9]; //these are department IDs
$query = Ticket::objects();
$query->filter(['dept_id' => $departments]);
...
The filter() function in VerySimpleModel (class.orm.php) says in a comment:
// Multiple arrays passes means OR
But I guess this means that I can filter with a OR on different columns, not on a single one, which is what I need. I tried navigating the code but I can't find a solution.
Found it, I simply needed to query like this:
$query->filter(['dept_id__in' => $departments]);
I need a Laravel query that returns the most recently created row of various site_id rows please. At the moment, I have this query:
Score::whereIn('site_id', $sites)->where('type', 2)->select('score')->get();
But it's returning all of the scores for the sites, where type = 2.
At the moment, the $sites array only contains 1,2, so it will exclude the site_ids that are 3 and 4.
Database structure:
My intended result that the query returns would be the following rows:
ID: 1, 2. - As in, they are the most recently created rows of the IDs within the array.
Update:
If I use:
Score::whereIn('site_id', $sites)->where('type', 2)
->select('score')
->groupBy('site_id')
->get();
a groupBy method, it returns the two scores that I want, but I'm not sure why it would return them? I thought it would just group all of the site's scores by site_id?
Thank you for your help.
Here's what you need: https://softonsofa.com/tweaking-eloquent-relations-how-to-get-latest-related-model/
With that you can easily do this:
$sites = Site::with('latestScore')->find($siteIds); // Collection
// now for each site:
$site->latestScore // what you wanted
however, if you want a collection of scores instead of accessing them via site, then use collection methods:
$sites = Site::with('latestScore')->find($siteIds); // Collection
$scores = $sites->pluck('latestScore') // get nested elements from collection
->filter() // filter out null items
I sounds to me like you just need an orderBy("created_at") chained to the end of your eloquent query.
I am trying to create a eloquent query to get the user results of an array of user id's. Is there a clean way to accomplish this using elequent instead of chaining wheres like this:
$users = User::where('id', '=', '1')->orWhere('id','=','2')
My array of ids comes from an API call and can contain as many id's as the call passes.
Cheers!
You want to use whereIn. This lets you pass in an array of IDs.
$userIds = [1, 2];
$users = User::whereIn('id', $userIds)->get();
I have 3 columns id, msg and created_at in my Model table. created_at is a timestamp and id is primary key.
I also have 5 datas, world => time4, hello => time2,haha => time1,hihio => time5 and dunno => time3 and these datas are arranged in ascending order (as arranged here) based on their id.
In laravel 4, I want to fetch these data, arrange them in ascending order and take the last n(in this case, 3) number of records. So, I want to get dunno,world and hihio rows displayed like this in a div :
dunno,time3
world,time4
hihio,time5
What I have tried
Model::orderBy('created_at','asc')->take(3);
undesired result :
haha,time1
hello,time2
dunno,time3
Also tried
Model::orderBy('created_at','desc')->take(3);
undesired result :
hihio,time5
world,time4
dunno,time3
I have also tried the reverse with no luck
Model::take(3)->orderBy('created_at','asc');
This problem seems fairly simple but I just can't seem to get my logic right. I'm still fairly new in Laravel 4 so I would give bonus points to better solutions than using orderBy() and take() if there is. Thank you very much!
You are very close.
It sounds like you want to first order the array by descending order
Model::orderBy('created_at','desc')->take(3);
but then reverse the array. You can do this one of two ways, either the traditional PHP (using array_reverse).
$_dates = Model::orderBy('created_at','desc')->take(3);
$dates = array_reverse($_dates);
Or the laravel way, using the reverse function in Laravel's Collection class.
$_dates = Model::orderBy('created_at','desc')->take(3)->reverse();
Check out Laravel's Collection documentation at their API site at http://laravel.com/api/class-Illuminate.Support.Collection.html
Now $dates will contain the output you desire.
dunno,time3
world,time4
hihio,time5
You're pretty close with your second attempt. After retrieving the rows from the database, you just need to reverse the array. Assuming you have an instance of Illuminate\Support\Collection, you just need to the following:
$expectedResult = $collection->reverse();
To get last three rows in ascending order:
$_dates = Model::orderBy('created_at','desc')->take(3)->reverse();
Now, the json output of $_dates will give you a object of objects.
To get array of objects use:
$_dates = Model::orderBy('created_at','desc')->take(3)->reverse()->values();
$reverse = Model::orderBy('created_at','desc')->take(3);
$show = $reverse->reverse();
How can I select a random row using Eloquent or Fluent in Laravel framework?
I know that by using SQL, you can do order by RAND(). However, I would like to get the random row without doing a count on the number of records prior to the initial query.
Any ideas?
Laravel >= 5.2:
User::inRandomOrder()->get();
or to get the specific number of records
// 5 indicates the number of records
User::inRandomOrder()->limit(5)->get();
// get one random record
User::inRandomOrder()->first();
or using the random method for collections:
User::all()->random();
User::all()->random(10); // The amount of items you wish to receive
Laravel 4.2.7 - 5.1:
User::orderByRaw("RAND()")->get();
Laravel 4.0 - 4.2.6:
User::orderBy(DB::raw('RAND()'))->get();
Laravel 3:
User::order_by(DB::raw('RAND()'))->get();
Check this article on MySQL random rows. Laravel 5.2 supports this, for older version, there is no better solution then using RAW Queries.
edit 1: As mentioned by Double Gras, orderBy() doesn't allow anything else then ASC or DESC since this change. I updated my answer accordingly.
edit 2: Laravel 5.2 finally implements a wrapper function for this. It's called inRandomOrder().
This works just fine,
$model=Model::all()->random(1)->first();
you can also change argument in random function to get more than one record.
Note: not recommended if you have huge data as this will fetch all rows first and then returns random value.
tl;dr: It's nowadays implemented into Laravel, see "edit 3" below.
Sadly, as of today there are some caveats with the ->orderBy(DB::raw('RAND()')) proposed solution:
It isn't DB-agnostic. e.g. SQLite and PostgreSQL use RANDOM()
Even worse, this solution isn't applicable anymore since this change:
$direction = strtolower($direction) == 'asc' ? 'asc' : 'desc';
edit: Now you can use the orderByRaw() method: ->orderByRaw('RAND()'). However this is still not DB-agnostic.
FWIW, CodeIgniter implements a special RANDOM sorting direction, which is replaced with the correct grammar when building query. Also it seems to be fairly easy to implement. Looks like we have a candidate for improving Laravel :)
update: here is the issue about this on GitHub, and my pending pull request.
edit 2: Let's cut the chase. Since Laravel 5.1.18 you can add macros to the query builder:
use Illuminate\Database\Query\Builder;
Builder::macro('orderByRandom', function () {
$randomFunctions = [
'mysql' => 'RAND()',
'pgsql' => 'RANDOM()',
'sqlite' => 'RANDOM()',
'sqlsrv' => 'NEWID()',
];
$driver = $this->getConnection()->getDriverName();
return $this->orderByRaw($randomFunctions[$driver]);
});
Usage:
User::where('active', 1)->orderByRandom()->limit(10)->get();
DB::table('users')->where('active', 1)->orderByRandom()->limit(10)->get();
edit 3: Finally! Since Laravel 5.2.33 (changelog, PR #13642) you can use the native method inRandomOrder():
User::where('active', 1)->inRandomOrder()->limit(10)->get();
DB::table('users')->where('active', 1)->inRandomOrder()->limit(10)->get();
You can use:
ModelName::inRandomOrder()->first();
it's very simple just check your laravel version
Laravel >= 5.2:
User::inRandomOrder()->get();
//or to get the specific number of records
// 5 indicates the number of records
User::inRandomOrder()->limit(5)->get();
// get one random record
User::inRandomOrder()->first();
or using the random method for collections:
User::all()->random();
User::all()->random(10); // The amount of items you wish to receive
Laravel 4.2.7 - 5.1:
User::orderByRaw("RAND()")->get();
Laravel 4.0 - 4.2.6:
User::orderBy(DB::raw('RAND()'))->get();
Laravel 3:
User::order_by(DB::raw('RAND()'))->get();
In Laravel 4 and 5 the order_by is replaced by orderBy
So, it should be:
User::orderBy(DB::raw('RAND()'))->get();
For Laravel 5.2 >=
use the Eloquent method:
inRandomOrder()
The inRandomOrder method may be used to sort the query results randomly. For example, you may use this method to fetch a random user:
$randomUser = DB::table('users')
->inRandomOrder()
->first();
from docs: https://laravel.com/docs/5.2/queries#ordering-grouping-limit-and-offset
You can also use order_by method with fluent and eloquent like as:
Posts::where_status(1)->order_by(DB::raw(''),DB::raw('RAND()'));
This is a little bit weird usage, but works.
Edit: As #Alex said, this usage is cleaner and also works:
Posts::where_status(1)->order_by(DB::raw('RAND()'));
Use Laravel function
ModelName::inRandomOrder()->first();
You can easily Use this command:
// Question : name of Model
// take 10 rows from DB In shuffle records...
$questions = Question::orderByRaw('RAND()')->take(10)->get();
There is also whereRaw('RAND()') which does the same, you can then chain ->get() or ->first() or even go crazy and add ->paginate(int).
I prefer to specify first or fail:
$collection = YourModelName::inRandomOrder()
->firstOrFail();
Laravel has a built-in method to shuffle the order of the results.
Here is a quote from the documentation:
shuffle()
The shuffle method randomly shuffles the items in the collection:
$collection = collect([1, 2, 3, 4, 5]);
$shuffled = $collection->shuffle();
$shuffled->all();
// [3, 2, 5, 1, 4] - (generated randomly)
You can see the documentation here.
At your model add this:
public function scopeRandomize($query, $limit = 3, $exclude = [])
{
$query = $query->whereRaw('RAND()<(SELECT ((?/COUNT(*))*10) FROM `products`)', [$limit])->orderByRaw('RAND()')->limit($limit);
if (!empty($exclude)) {
$query = $query->whereNotIn('id', $exclude);
}
return $query;
}
then at route/controller
$data = YourModel::randomize(8)->get();
I have table with thousands of records, so I need something fast. This is my code for pseudo random row:
// count all rows with flag active = 1
$count = MyModel::where('active', '=', '1')->count();
// get random id
$random_id = rand(1, $count - 1);
// get first record after random id
$data = MyModel::where('active', '=', '1')->where('id', '>', $random_id)->take(1)->first();
Here's how I get random results in eloquent in one of my projects:
$products = Product::inRandomOrder()->limit(10);
10 - The number of random records to pull.
Try this code! It Works:
User::orderBy(DB::raw('RAND()'))->get();