I have some struggles with search method in controller. Functions must search in 2 tables, but it will search only in one, the first one. What could be proper approach here?
->when($search, function ($query) use ($search) {
$query->whereHas('info', static function (Builder $query) use ($search) {
$query->where('name', 'LIKE', "%{$search}%")
->orWhere('description', 'LIKE', "%{$search}%")
->orWhere('keywords', 'LIKE', "%{$search}%");
});
$query->whereHas('merchant.translation', static function (Builder $query) use ($search) {
$query->where('name', 'LIKE', "%{$search}%")
->orWhere('description', 'LIKE', "%{$search}%")
->orWhere('keywords', 'LIKE', "%{$search}%");
});
})
I tried with if statement if first one has null or undefined, but no success.Also I tried to separate when function.
Related
I have two table customers, locations, and pivot table customer_location. I want to display Customer with id 3 with location, and then I can search that by location's name, customer's name, domain, number, or by email.
public function getCustomersProperty()
{
$search = $this->search;
return Customer::with('locations')->where('id', '=', '3')
->whereHas('locations', function ($q) use ($search) {
$q->where('name', 'like', '%'.$search.'%');
})
->where(function ($q) {
$q->Where('name', 'like', '%'.$this->search.'%')
->orWhere('domain', 'like', '%'.$this->search.'%')
->orWhere('number', 'like', '%'.$this->search.'%')
->orWhere('email', 'like', '%'.$this->search.'%');
})
->orderBy($this->sortField, $this->sortDirection)
->paginate($this->page_number);
}
Did you mean search by location OR anything else from those fields
public function getCustomersProperty()
{
$search= $this->search;
return Customer::with('locations')->where('id', '=', '3')
->where(function($q) {
$q->Where('name','like', '%'.$this->search.'%')
->orWhere('domain','like', '%'.$this->search.'%')
->orWhere('number','like', '%'.$this->search.'%')
->orWhere('email','like', '%'.$this->search.'%')
->orWhereHas('locations', function($q) use($search) {
$q->where('name', 'like', '%'.$search.'%');
});
})
->orderBy($this->sortField, $this->sortDirection)
->paginate($this->page_number);
}
Or you wanted the eager loaded locations to be relevant to your search.
public function getCustomersProperty()
{
$search= $this->search;
return Customer::with(['locations' => function($q) use($search) {
$q->where('name', 'like', '%'.$search.'%');
}])
->where('id', '=', '3')
->whereHas('locations', function($q) use($search) {
$q->where('name', 'like', '%'.$search.'%');
})
->where(function($q) {
$q->Where('name','like', '%'.$this->search.'%')
->orWhere('domain','like', '%'.$this->search.'%')
->orWhere('number','like', '%'.$this->search.'%')
->orWhere('email','like', '%'.$this->search.'%');
})
->orderBy($this->sortField, $this->sortDirection)
->paginate($this->page_number);
}
Hi I have this code that is to search for records.
Admins are able to see all records, this is the query for admins
$trainings = Training::where('staffName', 'LIKE', "%{$request->search}%")
->orWhere('programTitle', 'LIKE', "%{$request->search}%")
->orWhere('trainer', 'LIKE', "%{$request->search}%")
->paginate();
Whereas Employees should only see their records, so how do I add this condition into the existing query for the search function? This is the query I have for the Employee search currently
$employees = Training::where('staffName',$username)
->orWhere('staffName', 'LIKE', "%{$request->search}%")
->orWhere('programTitle', 'LIKE', "%{$request->search}%")
->orWhere('trainer', 'LIKE', "%{$request->search}%")
->paginate();
I have another version for Managers, which is meant to also refer to their roles from a different table. I am trying it like this but it only is working properly when it comes to the Manager, but when the function fetches anything related to staff under them it fetches all records instead of specific records.
$managers = DB::table('trainings')
->join('users','users.id','=','trainings.staff_id')
->select('trainings.staffName','programTitle','trainer','trainingDate','hours')
->where('trainings.staffName',$username)
->orWhere('reportingTo',$username)
->where(function ($query) use ($request) {
$query->where('trainings.staffName', 'LIKE', "%{$request->search}%")
->orWhere('programTitle', 'LIKE', "%{$request->search}%")
->orWhere('trainer', 'LIKE', "%{$request->search}%");
})
->paginate();
Your usage of orWhere is wrong because orWhere remove all conditions if it's true try this code below
Training::where('staffName', $username)
->where(function ($query) {
$query->where('staffName', 'LIKE', "%{$request->search}%")
->orWhere('programTitle', 'LIKE', "%{$request->search}%")
->orWhere('trainer', 'LIKE', "%{$request->search}%");
})
->paginate();
For the last query
$managers = DB::table('trainings')
->join('users', 'users.id', '=', 'trainings.staff_id')
->select('trainings.staffName', 'programTitle', 'trainer', 'trainingDate', 'hours')
->where(function ($query) use ($username) {
$query->where('trainings.staffName', $username)
->orWhere('reportingTo', $username);
})
->where(function ($query) use ($request) {
$query->where('trainings.staffName', 'LIKE', "%{$request->search}%")
->orWhere('programTitle', 'LIKE', "%{$request->search}%")
->orWhere('trainer', 'LIKE', "%{$request->search}%");
})
->paginate();
here's when query scopes comes to the rescue.
class Training extends Eloquent {
public function scopeFilterByRole($query, $roleId, $searchInput)
{
if ($roleId === 3) {
return $query->where('staffName', 'LIKE', "%{$searchInput}%")
}
return $query;
}
}
Then in your controller
Training::where('programTitle', 'LIKE', "%{$request->search}%")
->orWhere('trainer', 'LIKE', "%{$request->search}%")
->FilterByRole(3, $request->search)
->get();
You can write a global scope for that it will automatically apply in all existing queries:
protected static function boot()
{
parent::boot();
static::addGlobalScope(function (Builder $builder) {
if (auth()->check() and auth()->user()->role == 3) {
$builder->where('staffName', 'LIKE', "%{request()->get('search_name')}%")
}
});
}
I'm having two models Company and Contact search controller, my Contact model look something like:
class Contact extends Model {
public function companies()
{
return $this->belongsToMany('App\Company', 'company_contact', 'contact_id', 'company_id');
}
}
Few of my companies are referred as client for which I have a boolean field under the name of is_client.
I want to search contacts through a param request search which compares contact's first_name and last_name also with company name. If any body wants to have contact list of all the client then they can pass a extra request of client so accordingly I made a controller something like this:
Contact::when($request->client && $request->search, function ($q) use($request) {
$q->whereHas('companies', function ($q) use ($request) {
$q->where('is_client', true)->where(function ($q) use ($request) {
$q->orWhere('name', 'like', '%'. $request->search . '%');
});
})->where(function ($q) use ($request) {
$q->orWhere('first_name', 'like', '%'.$request->search.'%')
->orWhere('last_name', 'like', '%'.$request->search.'%');
});
})->when($request->client == null && $request->search, function ($q) use($request) {
$q->where('first_name', 'like', '%'.$request->search.'%')
->orWhere('last_name', 'like', '%'.$request->search.'%')
->orWhereHas('companies', function ($q) use ($request) {
$q->where('name', 'like', '%' . $request->search . '%');
});
})->when($request->client && $request->search == null, function ($q) use ($request) {
$q->whereHas('companies', function ($q) use ($request) {
$q->where('is_client', true);
});
})
->paginate(30)
It work perfectly fine with non-client contacts and for client contact initial list appears fine but when we type something it behaves not as desired. I may be doing some logic error. Help me out in this or guide me for better approach.
Your conditions when you got client and search are not correctly grouped
Contact::when($request->client && $request->search, function ($q) use($request) {
$q->whereHas('companies', function ($q) use ($request) {
$q->where('is_client', true);
})->where(function ($q) use ($request) {
$q->where('first_name', 'like', '%'.$request->search.'%')
->orWhere('last_name', 'like', '%'.$request->search.'%')
->orWhereHas('companies', function ($q) use ($request) {
$q->where('name', 'like', '%' . $request->search . '%');
});
});
})->when($request->client == null && $request->search, function ($q) use($request) {
$q->where('first_name', 'like', '%'.$request->search.'%')
->orWhere('last_name', 'like', '%'.$request->search.'%')
->orWhereHas('companies', function ($q) use ($request) {
$q->where('name', 'like', '%' . $request->search . '%');
});
})->when($request->client && $request->search == null, function ($q) use ($request) {
$q->whereHas('companies', function ($q) use ($request) {
$q->where('is_client', true);
});
})
->paginate(30)
the condition is_client must be separated from the condition of search
You should have noticed that you can easily shrink the code here
$contactQuery = Contact::query();
if ($request->client) {
$contactQuery->whereHas('companies', function ($q) {
$q->where('is_client', true);
});
}
if ($request->search) {
$contactQuery->where(function ($q) use ($request) {
$q->where('first_name', 'like', '%'.$request->search.'%')
->orWhere('last_name', 'like', '%'.$request->search.'%')
->orWhereHas('companies', function ($q) use ($request) {
$q->where('name', 'like', '%' . $request->search . '%');
});
});
}
$contacts = $contactQuery->paginate(30);
I want to display only the users who are admin and according to a search term which is entered in the searchbox
I store the keyword first
$keyword = $request->get('search');
and then
$users = User::with('admin')->where('role', 'super_admin')
->where(function ($query) use($keyword){
$query->where('id', 'LIKE', "%$keyword%")
->orWhere('name', 'LIKE', "%$keyword%");
})->paginate($perPage);
This works as im searching terms from main table that is user table
But i also want to filter it using admin table columns as
$users = User::with('admin')->where('role', 'super_admin')
->where(function ($query) use($keyword){
$query->where('id', 'LIKE', "%$keyword%")
->orWhere('email', 'LIKE', "%$keyword%")
->orWhere('name', 'LIKE', "%$keyword%")
->orWhere($this->admin->status, 'LIKE', "%$keyword%");
})->paginate($perPage);
This throws an error undefined property admin
Due to this line ->orWhere($this->admin->status, 'LIKE', "%$keyword%");
So how can i use admin column in filtering data
sample eager loading
$users = User::with([
'admin' => function($query) use($keyword) {
$query->where('status', 'LIKE', "%$keyword%")
}
])
->where('role', 'super_admin')
->where(function ($query) use($keyword){
$query->where('id', 'LIKE', "%$keyword%")
->orWhere('email', 'LIKE', "%$keyword%")
->orWhere('name', 'LIKE', "%$keyword%")
})->paginate($perPage);
I'm building a small application in laravel 5.4, where I'm having two models Contact and Companies I've many to many relationship between them, something like this in my Contact Model:
public function company()
{
return $this
->belongsToMany('App\Company', 'company_contact','contact_id', 'company_id')->withTimestamps();
}
Now at someplace I want to have current company i.e. I want to have latest() first(). Or orderBy, created_by desc and get first() row. For this I have to do something like this:
$contacts = Contact::where('name', 'LIKE', '%'. $request->search_input. '%')
->orWhere('email', 'LIKE', '%'. $request->search_input. '%')
->orWhereHas('company', function ($q) use($request) {
$q->where('name', 'LIKE', '%'. $request->search_input. '%');
})
->with('company')
->orderBy('created_at', 'desc')
->paginate(50);
foreach ($contacts as $contact)
{
$contact->company = $contact->company()->withPivot('created_at')->orderBy('pivot_created_at', 'desc')->first();
}
For this to remove foreach I tried using a new relation in my Contact model:
public function currentCompany()
{
return $this
->belongsToMany('App\Company', 'company_contact','contact_id', 'company_id')
->withTimestamps()
->orderBy('created_at', 'desc')
->first();
}
But while fetching in controller:
$contacts = Contact::where('name', 'LIKE', '%'. $request->search_input. '%')
->orWhere('email', 'LIKE', '%'. $request->search_input. '%')
->orWhereHas('currentCompany', function ($q) use($request) {
$q->where('name', 'LIKE', '%'. $request->search_input. '%');
})
->with('CurrentCompany')
->orderBy('created_at', 'desc')
->paginate(50);
But it is throwing me error, is there any eloquent way or Collection way to remove this foreach.
use first() inside closure-
$contacts = Contact::where('name', 'LIKE', '%'. $request->search_input. '%')
->orWhere('email', 'LIKE', '%'. $request->search_input. '%')
->with(['company'=>function ($q) use($request) {
$q->where('name', 'LIKE', '%'. $request->search_input. '%')->first();
}])
->orderBy('created_at', 'desc')
->paginate(50);
Or like this-
$contacts = Contact::where('name', 'LIKE', '%'. $request->search_input. '%')
->orWhere('email', 'LIKE', '%'. $request->search_input. '%')
->orWhereHas('company', function ($q) use($request) {
$q->where('name', 'LIKE', '%'. $request->search_input. '%');
})
->with(['company'=>function($q){
$q->first();
}])
->orderBy('created_at', 'desc')
->paginate(50);
this way you don't need to do any additional foreach loop.
You can't really do what you are trying to do directly. The relationships are query shortcuts. You can ensure you only get the first but that will still be a part of a collection if your relationship is one/many to many.
Consider this:
$contacts = Contact::where('name', 'LIKE', '%'. $request->search_input. '%')
->orWhere('email', 'LIKE', '%'. $request->search_input. '%')
->orWhereHas('company', function ($q) use($request) {
$q->where('name', 'LIKE', '%'. $request->search_input. '%');
})
->with([ 'company' => function ($query) {
return $query->latest(); //Take the latest only
})
->orderBy('created_at', 'desc')
->paginate(50);
However to access the company you need to do something like $contacts[index]->company->first() because it will still produce a collection of related companies even.
The problem is the ORM will perform 2 queries, the first one will retrieve all the Contact models which fulfil the query and the 2nd one will retrieve all related models for all contacts it retrieved. This means if you do things like limiting it to 1 related result you might end up only getting one for all contacts retrieved.