Eloquent select rows with empty string or null value - php

I have something like $user->albums()->where('col', NULL), it works fine then I tried to extend it to empty strings with $user->albums()->where('col', NULL)->or_where('col', '') and it's not working.
Also I saw on this post that I could use where_null('col') but it's not working and it's not documented. Any simple method to select where empty or NULL col

Try using orWhereNull for the second clause:
$users = DB::table('users')
->where('col', '=', '')
->orWhereNull('col')
->get();
Or if you have multiple conditions in the query, you have to wrap the two in a closure:
$users = DB::table('users')
->where(function(\Illuminate\Database\Eloquent\Builder $query) {
$query->where('col', '')->orWhereNull('col');
})
->where('col2','val2')
->get();

How about this:
$user->albums()->whereRaw("NOT col > ''")
This way you can check both conditions at the same time

Try this query:
$users = DB::table('users')
->whereRaw('col = "" OR col IS NULL')
->get();

I always encourage to create queries with the main Laravel functions that are most used.
That's why you must have 2 things in mind:
algorithm. key1 = value1 AND key2 = value2 OR key3 = value3. Be very carreful about precedence because in the way I exemplified there will be a main OR not an AND with OR inside
using where(), whereIn(), whereNull and closure instead of whereRaw(). whereRaw is using more memory than any others I mentioned.
So, to resume your answer:
OR condition
$users = DB::table('users')
->where('col', '=', '')
->orWhere('col','=','')
->whereNull('col')
->get();
AND and OR condition
$users = DB::table('users')
->where(function($query) { $query->where('col','=','')->orWhere('col','=','')->whereNull('col'); })
->where('col','=','')
->get();

The below solution is tested on LARAVEL 9. Solution is to add to the App\Providers\AppServiceProvider this piece of code:
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
///...
Builder::macro('whereNullOrEmpty', function ($field) {
return $this->where(function ($query) use ($field) {
return $query->where($field, '=', null)->orWhere($field, '=', '');
});
});
Builder::macro('whereNotNullOrEmpty', function ($field) {
return $this->where(function ($query) use ($field) {
return $query->where($field, '<>', null)->where($field, '<>', '');
});
});
}
//...
}
and then call it like this:
if($nullOrEmpty){
$builder->whereNullOrEmpty('col');
}else{
$builder->whereNotNullOrEmpty('col');
}
You must call both commands:
where($field, '<>', null);
where($field, '<>', '');
because the MySql is handling empty strings and nulls different than a PHP
you also need to wrap those two commands with the closure to tell Eloquent to put generated code in parentheses and isolate MySql code:
(where col = null or where col = '')

Not sure, but this might work:
$user->albums()->where_in('col', array(NULL,''));

Related

Laravel Eloquent hardcoded value in whereNotIn

In Laravel eloquent query using multiple columns for whereNotIn clause I need to hardcoded one of the DB::raw column for the value should be coming from a variable (loop variable). What is the best way to implement this?
This is my query and I need to change the hardcoded 1 in DB::raw('(1,user_profile.user_id')
$otherProfiles = Userprofile::where('user_id', '!=', $profile->user_id)
->where(function ($query) use ($userInterests) {
foreach ($userInterests as $interest) {
$query->orWhere('interest', 'like', "%$interest%");
};
})
->whereNotIn(DB::raw('(1, user_profile.user_id)'), function ($query) {
$query->select('sender_id', 'receiver_id')
->from('email_reports');
})
->inRandomOrder()
->get();
Manage to fix it by just simple concatenation
the code added were DB::raw('('. $profile->user_id . ', user_profile.user_id)')
create a variable as $id for your dynamic value..
$otherProfiles = Userprofile::where('user_id', '!=', $profile->user_id)
->where(function ($query) use ($userInterests) {
foreach ($userInterests as $interest) {
$query->orWhere('interest', 'like', "%$interest%");
};
})
->whereNotIn('user_id', $id), function ($query) {
$query->select('sender_id', 'receiver_id')
->from('email_reports');
})
->inRandomOrder()
->get();

Laravel relationships use Where

This relationship is in my Maintenance.php
public function contactedContractor()
{
return $this->hasMany(ContactedContractor::class, 'maintenance_id');
}
I want to use the relationship in a query in my controller
$contractor_maintenances = Maintenance::whereHas('contactedContractor', function ($query) {
return $query->where('contacted_contractors.user_id', '=', 8);
})
->where('contacted_contractors.user_id', $contractor_user_id)
->latest('maintenances.created_at')
->get();
but the where clause is not working giving me this error
Unknown column 'contacted_contractors.user_id' in 'where clause
How do I use the where clause?
You've passed in the query. Maintenance doest not have user_id
->where('contacted_contractors.user_id', $contractor_user_id)
Pass your query as below.
$contractor_maintenances = Maintenance::whereHas('contactedContractor', function ($query) use ($contractor_user_id) {
return $query->where('user_id', $contractor_user_id);
})->latest('maintenances.created_at')->get();

How to fetch users not assigned to a particular role in Laravel [duplicate]

In Laravel we can setup relationships like so:
class User {
public function items()
{
return $this->belongsToMany('Item');
}
}
Allowing us to to get all items in a pivot table for a user:
Auth::user()->items();
However what if I want to get the opposite of that. And get all items the user DOES NOT have yet. So NOT in the pivot table.
Is there a simple way to do this?
Looking at the source code of the class Illuminate\Database\Eloquent\Builder, we have two methods in Laravel that does this: whereDoesntHave (opposite of whereHas) and doesntHave (opposite of has)
// SELECT * FROM users WHERE ((SELECT count(*) FROM roles WHERE user.role_id = roles.id AND id = 1) < 1) AND ...
User::whereDoesntHave('Role', function ($query) use($id) {
$query->whereId($id);
})
->get();
this works correctly for me!
For simple "Where not exists relationship", use this:
User::doesntHave('Role')->get();
Sorry, do not understand English. I used the google translator.
For simplicity and symmetry you could create a new method in the User model:
// User model
public function availableItems()
{
$ids = \DB::table('item_user')->where('user_id', '=', $this->id)->lists('user_id');
return \Item::whereNotIn('id', $ids)->get();
}
To use call:
Auth::user()->availableItems();
It's not that simple but usually the most efficient way is to use a subquery.
$items = Item::whereNotIn('id', function ($query) use ($user_id)
{
$query->select('item_id')
->table('item_user')
->where('user_id', '=', $user_id);
})
->get();
If this was something I did often I would add it as a scope method to the Item model.
class Item extends Eloquent {
public function scopeWhereNotRelatedToUser($query, $user_id)
{
$query->whereNotIn('id', function ($query) use ($user_id)
{
$query->select('item_id')
->table('item_user')
->where('user_id', '=', $user_id);
});
}
}
Then use that later like this.
$items = Item::whereNotRelatedToUser($user_id)->get();
How about left join?
Assuming the tables are users, items and item_user find all items not associated with the user 123:
DB::table('items')->leftJoin(
'item_user', function ($join) {
$join->on('items.id', '=', 'item_user.item_id')
->where('item_user.user_id', '=', 123);
})
->whereNull('item_user.item_id')
->get();
this should work for you
$someuser = Auth::user();
$someusers_items = $someuser->related()->lists('item_id');
$all_items = Item::all()->lists('id');
$someuser_doesnt_have_items = array_diff($all_items, $someusers_items);
Ended up writing a scope for this like so:
public function scopeAvail($query)
{
return $query->join('item_user', 'items.id', '<>', 'item_user.item_id')->where('item_user.user_id', Auth::user()->id);
}
And then call:
Items::avail()->get();
Works for now, but a bit messy. Would like to see something with a keyword like not:
Auth::user()->itemsNot();
Basically Eloquent is running the above query anyway, except with a = instead of a <>.
Maybe you can use:
DB::table('users')
->whereExists(function($query)
{
$query->select(DB::raw(1))
->from('orders')
->whereRaw('orders.user_id = users.id');
})
->get();
Source: http://laravel.com/docs/4.2/queries#advanced-wheres
This code brings the items that have no relationship with the user.
$items = $this->item->whereDoesntHave('users')->get();

cant get the data I want from two different tables using Laravel

I have a table called instructor_class: user_id, class_id and I have another table classes: id, time, active.
I would like to show classes for a single user but only those classes that active is 0 or 1.
My current code looks like this:
return InstructorClass::with('classes.session')->where('user_id', '=', $userId)->get();
This code is displaying me everything, then I tried the following code:
$active = 1;
return InstructorClass::with(['classes' => function ($q) use ($active) {
$q->where('active', '=', $active); // '=' is optional
}])
->where('user_id', '=', $userId)
->get();
This again returns me same records, but of course the class property is null for each record, which at some point looks correct, but my point is if the 'active' field does not corresponds at the classes table do not show the record, seems like the where() stm within with() is optional..
I am kinda stuck here...
Would appreciate your help, opinions!
You can use ::has('classes') to only return the models that have related classes
return InstructorClass::has('classes')->with(['classes' => function ($q) use ($active) {
$q->where('active', $active);
}])
->where('user_id', '=', $userId)
->get();
Never thought it could be this simple:
return InstructorClass::with('classes.session')
->join('classes', 'classes.id', '=', 'instructor_class.class_id')
->where('classes.active', '=', 1)
->where('user_id', '=', $userId)
->get();

Conditional join in Laravel Fluent

In Laravel PHP framework you can use a condition inside a where clause, like this (Fluent):
...
->where(function($query) use ($var) {
if(isset($var)) {
$query->where('something', '=', $var);
}
})
->...
So if you do not have a $var variable, the where clause will not be added to the query.
I would like to do the same thing, but with a join clause, so for example join with another table only if $var is set, but this does not work, the query collapses:
...
->join('tableB', function($query) use ($var) {
if(isset($var)) {
$query->on('tableA.id', '=', 'tableB.id');
}
})
->...
Any suggestion?
You don't need to chain all methods on a single cast.
For instance:
// Instantiates a Query object.
$query = Db::table('posts')->where('published', '=', '1');
// Adds conditional join and where
if (Input::has('category')) {
$query->join('categories', 'categories.id', '=', 'post.category_id')
->where('categories.permalink', '=', Input::get('category'));
}
// Adds another clause
$query->order_by('created_at');
// Fecthes results
$results = $query->get()

Categories