Laravel 5.7 eloquent query with multiple wheres and a whereNotIn - laravel

I'm attempting to execute a query that gets a data set based on a user id matching two possible columns and a workflow_state not matching two values. My attempt is here:
$usersBugs = Bug::where('assigned_user_id', $user->id)
->orWhere('reported_by', $user->id)
->whereNotIn('workflow_state', ['closed', 'rejected'])
->get();
It is returning a "bug" with a rejected workflow_state. I'm guessing it is executing the whereNotIn as an or? How would I refactor this to execute that the bug cannot be in either of those two states (no matter what) and it can match either the assigned_user_id OR the report_by. I tried leading with the whereNotIn:
$usersBugs = Bug::whereNotIn('workflow_state', ['closed', 'rejected'])
->where('assigned_user_id', $user->id)
->orWhere('reported_by', $user->id)
->get();
Either way it is returning a matched bug based on the assigned_user_id, despite the fact that the workflow_state is rejected.

You may try this:
$model->whereNotIn(...)->where(function($query) use ($user) {
$query->where('assigned_user_id', $user->id)->orWhere('reported_by', $user->id);
})->get();

You should wrap where .. orWhere into additional closure:
$usersBugs = Bug::where(function($q) {
$q->where('assigned_user_id', $user->id)
->orWhere('reported_by', $user->id)
})->whereNotIn('workflow_state', ['closed', 'rejected'])->get();

Related

I get the same row duplicated as the result when I do a simple join using the laravel's DB facade

Code
$result = DB::table('disaster_rescue_data')
->join('users', 'disaster_rescue_data.username', '=', 'users.email')
->get();
Problem
I have this very simple join as mentioned in the above code. However when I render the data on a view or dd the $result, I get the same row duplicated and I can not figure out why. (The rows contain the same data.)
(I am using Laravel 5.4)
Can someone please help me figure out why? (I tried different techniques and none of them worked! Thanks.)
to prevent duplication, you should use distinct() method, this method Returns only unique items from the result.
in order to do that, first you must stricly select what you want:
$result = DB::table('disaster_rescue_data')
->select('disaster_rescue_data.*')
->join('users', 'disaster_rescue_data.username', '=', 'users.email')
->distinct()->get();
You could try using distinct in the query. Distinct removes duplicates in a result set.
For example
$result = DB::table('disaster_rescue_data')
->distinct()
->join('users', 'disaster_rescue_data.username', '=', 'users.email')
->get();
See https://laravel.com/docs/5.4/queries
EDIT:
Ok, I am thinking you can now use groupBy to get the unique results. Although it's not clear what your data structure is so this is a guess to use "users.email". Maybe it could be "disaster_rescue_data.username" to group by. Experiment and see.
$result = DB::table('disaster_rescue_data')
->distinct()
->join('users', 'disaster_rescue_data.username', '=', 'users.email')
->groupBy('users.email')
->get();

How to use AND in laravel database query

$konten = Konten::all()->where('kategori','Announcement' AND 'kategori','Activities')->sortByDesc('id');
It's not work what is the right query for using AND Logic in query sir ? im so sorry i don't have much knowledge to find out the way.. the point is i want $konten contains the row from Konten where the kategori is Announcement and Activities.. how to make it happen ? it just showing konten where the kategori is activities the announcement not passed..
You can chain several where to achieve AND:
$konten = Konten::where('kategori', 'Announcement')
->where('kategori', 'Activities')
->orderBy('id', 'desc')
->get();
Or use whereIn like this:
$konten = Konten::whereIn('kategori', ['Announcement', 'Activities'])
->orderBy('id', 'desc')
->get();
To achieve an AND in Laravel, you simply chain ->where() calls:
$konten = Konten::where('kategori','Announcement')->where('kategori','Activities') ...
As a side note, Konten::all() returns a Collection, and is no longer database logic. You shouldn't call ::all() unless you specifically need every record in the database.
Refactor to the following:
$konten = Konten::where('kategori','Announcement')
->where('kategori','Activities')
->orderBy('id', 'desc')
->get();
This will leverage the database to perform the filtering/ordering, instead of offloading every record into a Collection and allowing PHP to perform the same logic, which can be incredibly inefficient depending on the number of records.
try this:
$konten = Konten::whereIn('kategori', ['Announcement', 'Activities'])->orderBy('id', 'desc')->get();
I have a strong feeling that you probably seek for 'orWhere' clause... If you want ALL records when kategori column equals 'Announcement' and all records when kategori equals 'Activities' you sholud use orWhere clause like so:
$konten = Konten::where('kategori', 'Announcement')
->orWhere('kategori', 'Activities')
->orderBy('id', 'desc')
->get();
Or as mentioned in answers below you can use whereIn statement.

How return all rows for groupBy

I use the query to get the models that the user has, but only 1 model is returned for each user. How to get all? If I set $count=3 I should receive 3 or more models in group, but only first row is returned
$items->where(/*.....*/)
->groupBy('user_id')
->havingRaw("COUNT(*) >= {$count}")->get()
UPDATE
I solved it. I created a separate function for preparing the query and used it 2 times.
I think this may be an incorrect solution, but it works
$items = Items::query();
$this->prepareQuery($request, $items)
$items->whereHas('user', function ($q) use ($count, $request){
$q->whereHas('items', function ($query) use ($request){
$this->prepareQuery($request, $query);
}, '>=', $count);
})
->paginate(4);
This may work.Sometimes take can help.
$items->where(/*.....*/)
->groupBy('user_id')
->take({{$count}});
If you have relationships set up you can quite simply call:
$model->models()
$model being the model you're wanting the list for.
models() being the name of the relationship between the two items.
For example, a post may have many comments. You can call $post->comments() to get a list of the posts comments.
You may also query this from the database directly with some eloquent magic.
Post::with('comments')->where(/*....*/)->get();
EDIT:
You can check to see if a model has X number of related models like so.
Post::has('comments', '>=', 3)->where(/*...*/)->get();

Laravel Sorting Data with Relationship and Pagination

I need sorting the Records data according to Relationship.
I am trying below Query.
$data = Lead::with('bdm', 'status_code', 'bdm.bdm')->get()->sortByDesc('bdm.bdm.name');
It works fine but I need data with pagination which is giving by Laravel 5 by default.
So If I am trying with below query . It is giving error.
$data = Lead::with('bdm', 'status_code', 'bdm.bdm')->pagination(20)->sortByDesc('bdm.bdm.name');
I am trying an other way to do the same task. It works fine but it is not sorting the records.
$data = Lead::with(['bdm','status_code', 'bdm.bdm' => function ($query) {
$query->orderBy('name', 'desc');
}])->paginate(20);
So kindly can anyone give me solution how to adjust this query.
Any Help will be appreciated.
Thanks
You should be using a join statement to do that.
If I were to assume your column names it should look something like this:
$data = Lead::with(['status_code', 'bdm.bdm'])
->join('bdms', 'bdms.id', '=', 'leads.bdm_id')
->orderBy('bdms.name', 'desc')
->paginate(20);
And the first bdm parameter in your query is redundant. It will be handled during bdm.bdm anyway.

Eloquent ORM, how to avoid redundant queries?

Suppose I have the field status in all my database tables. When I want to delete a record, instead of purging it I set the value of field status to 0. This means of course all my queries will always use a where clause such as:
WHERE status = 1
However, this means I have to write and append where('status', '=', 1) to all methods of my eloquent model. It will always be like:
Post::find(1).where('status', '=', 1)
Post::where('status', '=', 1)->get()
Post::find(1).where('status', '=', 1).comments().where('status', '=', 1)->get()
Is there a way to define something as a default scope to have where status = 1 always present in all methods of my model and all the time?
I appreciate any help!
This should do the trick, at least regarding soft delete:
http://four.laravel.com/docs/eloquent#soft-deleting
You could use the scope methods.
public function scopeActive($query)
{
$query->where('status', '=', 1);
}
Then, you use like this:
Post::active()->get();

Resources