How in Laravel filter by relationship? - laravel

I have two models which linked with each other:
class Task extends Model{
public function user(){
return $this->belongsTo('App\User', 'user_id');
}
}
class User extends Model{
public function tasks(){
return $this->hasMany('App\Task', 'user_id');
}
}
Now I want to create some search or filter system.
There is a form where the user can choose Task only then the User's parameters (age, sex etc)
How can I do this kind of things? I tried to use newQuery on relation but...
Any help, thanks

I hope i understood you well.
Use nested where and whereHas as such
$tasks = Task::where('condition', $var)
->orWhereHas('user', function($q) use ($var){
$q->where('condition', 'LIKE', '%'. $var.'%');
});

try this. i hope it will work for you.
use join to get data from two tables
function getBuildings($request) {
if (isset($request->keyword) && $request->keyword != '') {
$data = $this->where(function($query) use ($request) {
$query->orWhere('users.column_name', 'LIKE', '%' . $request->keyword . '%');
$query->orWhere('users.column_name', 'LIKE', '%' . $request->keyword . '%');
});
}
$datacount = $this->count();
$dataArray = $this->select('users.*,task.whatever data you want to get from task');
if ($request->length == -1) {
$dataArray = $dataArray->get();
} else {
$dataArray = $dataArray->skip($request->start)->take($request->length)->get();
}
return [$datacount, $dataArray];
}

Related

Laravel eloquent search functionality

I'm currently creating a search functionality on my index blade file.
I have different users that have different stores per area.
my User model:
function area() {
return $this->hasOne('App\Area');
}
function role() {
return $this->belongsTo('App\Role');
}
function reports() {
return $this->hasMany('App\Report');
}
function stores() {
return $this->hasManyThrough('App\Store', 'App\Area');
}
}
Area model:
function reports() {
return $this->hasMany('App\Report');
}
function stores() {
return $this->hasMany('App\Store');
}
function user() {
return $this->belongsTo('App\User');
}
Store model:
function district() {
return $this->belongsTo('App\District');
}
function cluster() {
return $this->belongsTo('App\Cluster');
}
function city() {
return $this->belongsTo('App\City');
}
function area() {
return $this->belongsTo('App\Area');
}
I have managed to make the functionality work on admin account (where in you can see all stores) by:
function index(Request $request) {
if($request->has('search')) {
$stores = Store::whereHas('city', function($query) use($request) {
$query->where('name', 'like', '%' . $request->search . '%');
})->orWhereHas('cluster', function($query) use($request) {
$query->where('name', 'like', '%' .$request->search. '%');
})->orWhere('name', 'like', '%' .$request->search. '%')
->orWhere('store_no', 'like', '%' .$request->search. '%')->paginate(10);
} else {
$stores = Store::orderBy('created_at', 'desc')->paginate(10);
}
return view('/stores.store_list', compact('stores'));
what I want to do on user accounts is:
function index(Request $request) {
if($request->has('search')) {
$id = Auth::user()->id;
$query = $request->search;
$user = User::find($id)->stores()->where('name', 'like', '%' . $query . '%')->paginate(10);
} else {
$id = Auth::user()->id;
$user = User::find($id)->stores()->orderBy('created_at', 'desc')->paginate(10);
}
return view('/stores.store_list', compact('user'));
}
I'm having an error when searching:
SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'name' in where clause is ambiguous (SQL: select count(*) as aggregate from stores inner join areas on areas.id = stores.area_id where areas.user_id = 6 and name like %houston% and stores.deleted_at is null)
can anyone point me on the right direction and let me know what i'm missing here? Thank you!
When you have error such is
Column 'some_column_name_here' in where clause is ambiguous...
it means that there is complex query associated with more tables of which at least two those have same table name in their structure and that table name is used in complex query (in some ON, WHERE...) in this case WHERE as error states.
You always can use table_name.column_name {table name dot column name} syntax to point syntax at exact table meant (ambiguous).

How to search into hasMany relationship in laravel

I have a model of Company and Dispensary
<?php
// Company.php
public function dispensary()
{
return $this->hasMany(Dispensary::class);
}
// Dispensary.php
public function company()
{
return $this->belongsTo(Company::class);
}
What I want is first get the dispensary of the company which the user belongs.
$auth = \Auth::user();
$userCompany = $auth->company()->get();
$dispensaries = Company::find($userCompany->first()->id)->dispensary;
How should I construct a query where the user can search for the dispensary list where the user belongs.
I have tried using whereHas but it's searching from the Company instead of the Dispensary
Company::find($userCompany->first()->id)
->whereHas('dispensary', function ($query) use ($name) {
$query->where('name', 'like', "%{$name}%");
})->get();
Okay I finally made it to work just by using where clause
$company = Company::find($id)->dispensary()
->where('name', 'like', "%{$name}%")
->where('contact_email', 'like', "%{$email}%")
->get();

tojson() does not return all related models

I am working on laravel 5.5 project
i have four tables as following:-
1- Subject model (has following relations)
public function types()
{
return $this->belongsToMany('App\Types');
}
public function areas()
{
return $this->belongsToMany('App\Area');
}
public function articles()
{
return $this->hasMany('App\Article');
}
2- Area and Types has many to many relation with Subject model
public function subjects()
{
return $this->belongsToMany('App\Subjects');
}
3- Article has 1 to many relation with Subject
public function subjects()
{
return $this->belongsTo('App\Subjects');
}
The below controller will search for subject by keyword, select type or area and return value as json using toJson() and return results to view:-
public function search(Request $request)
{
//start search//
$get_Subjects = new Subject();
$get_Subjects = $get_Subjects ->newQuery();
if($request->term != '')
{
$get_Subjects->with('articles')->whereHas('articles', function ($query) use ($request){
$query->where('title', 'LIKE', '% '.$request->term.' %')
->orwhere('abstract', 'LIKE', '% '.$request->term.' %')
->orwhere('fullCitation', 'LIKE', '% '.$request->term.' %');
})
->where(function($query) use ($request){
$query->where('name', 'LIKE', '%'.$request->term.'%');
});
}if($request->area != '28')
{
// search for the selected area
$get_Subjects->with('areas')->whereHas('areas', function($query) use ($request){
$query->where('area_id', $request->area);
});
}
if($request->type!= '36')
{
// search for the selected types
$get_Subjects->with('types')->whereHas('types', function($query) use ($request){
$query->where('type_id', $request->type);
});
}
$subjects = $get_Subjects->tojson();
return View::make('public.search', compact('subjects'));
}
the issue is when i search by keyword the returned json only include related articles, and if i search by area i only get related areas()
while if i did not use json and access variable from blade i can access all related models even though it is the same query
i tried to use load() but it did not work
any help will be valuable
============Update===========
i tried using load() as follow
$subjects= $get_subjects->get();
$subjects= $subjects->load('articles', 'areas', 'types')->tojson();
when search by keyword, the json does have related relations
but they are empty
when search by area or type, the json does have related relation
which mean if i search in the subject table only which is the 1st case i wont get related model with it
please need your help
Have you tried adding the ->get() method before the ->toJson() method?
$subjects = $get_Subjects->get()->toJson();
get() will run the query and return models. toJson() should then work as you expect.
Update
I would write your code like this to start with. (I haven't tested this).
It seems like you are using the whereHas the wrong way. The subject table should have the area_id and type_id fields, so whereHas isn't needed... this might not be the case, but it seems like it should be based on the info you provided.
public function search(Request $request)
{
$get_Subjects = new Subject();
$get_Subjects = $get_Subjects ->newQuery();
$with = [];
if($request->term != '') {
$with[] = 'articles';
$subjects = $get_Subjects->whereHas('articles', function ($query) use ($request){
$query->where('title', 'LIKE', '% '.$request->term.' %')
->orwhere('abstract', 'LIKE', '% '.$request->term.' %')
->orwhere('fullCitation', 'LIKE', '% '.$request->term.' %');
})
->where('name', 'LIKE', '%'.$request->term.'%');
}
if($request->area != '28') {
$with[] = 'areas';
$get_Subjects->where('area_id', $request->area);
}
if($request->type!= '36') {
$with[] = 'types';
$get_Subjects->where('type_id', $request->type);
}
$subjects = $get_Subjects->with($with)->get()->toJson();
return View::make('public.search', compact('subjects'));
}

where clause inside a relationships - laravel

I have 3 models like this:
WarehousePivotCategory:
id - warehouse_id - warehouse_category_id
Warehouse:
title
WarehouseCategory:
title_en
I've created 2 hasOne relationships inside WarehousePivotCategory and they work fine:
public function Warehouse()
{
return $this->hasOne('App\Models\Warehouse','id','warehouse_id');
}
public function WarehouseCategory()
{
return $this->hasOne('App\Models\WarehouseCategory','id','warehouse_category_id');
}
in the database I have two records in warehouses table :
id title
1 AA
2 BB
I want to search title in warehouses :
$title = 'AA';
$warehouses = WarehousePivotCategory::with(['warehouse' => function($q) use ($title) {
$q->where('title', 'like', '%' . $title . '%');
},'WarehouseCategory'])->get();
foreach ($warehouses as $w)
{
echo $w->warehouse->title; // no thing
}
but it doesn't return any of title of warehouses.
my relationships is correct because below code works fine :
WarehousePivotCategory::with('warehouse','WarehouseCategory')->paginate(10);
I think you're missing get method in your closure. Try it like this:
$warehouses = WarehousePivotCategory::with(['warehouse' => function($q) use ($title) {
$q->where('title', 'like', '%' . $title . '%')->get(); },'WarehouseCategory'])->get();
You can also send array of fields you want to fetch to get method, like this:
$warehouses = WarehousePivotCategory::with(['warehouse' => function($q) use ($title) {
$q->where('title', 'like', '%' . $title . '%')->get(['id', 'title']); },'WarehouseCategory'])->get();
That is wrong. You don't need to use hasone while you have created pivot.You need to use BelongsToMany
class warehouse extends Model{
public function ware_cat(){
return $this->BelongsToMany('App\Models\WarehouseCategory');
}
public function getWarehouse(){
$this->with('ware_cat')->get();
}
}
Pivot table will fetch it so in warehouse model you will get its category and in category model you will get the warehouse same way visa-versa.

Laravel eloquent query join

<?php
namespace App\Http\Controllers;
use App\Clients;
use Illuminate\Http\Request;
use App\Http\Requests;
class AuditsController extends Controller {
public function index() {
$clients = Clients::distinct()->select('tag')->where('tag', '!=', 'NA')->get();
return view('clients', compact('clients'));
}
public function show($client) {
$machines = Clients::with('machines', 'bios')->where('TAG', $client)->get();
$server = $machines->where('OSNAME', 'LIKE', '%server%')->get();
return view('audit', compact('client'))->with('server', $server);
}
}
$machines creates a list of machines the client has, i need to have this list only show the machines with the word server in the field OSNAME, ive tried doing it as follows but it also did not work
$machines = Clients::with('machines', 'bios')->where('TAG', $client)->where('OSNAME', 'LIKE', '%server%')->get();
I'm not sure on what is the correct laravel method for doing this, should i create a new model?
Clients/machines reference 2 different tables in DB.
Use Eager-loading Filters:
Before:
public function show($client) {
$machines = Clients::with('machines', 'bios')->where('TAG', $client)->get();
$server = $machines->where('OSNAME', 'LIKE', '%server%')->get();
return view('audit', compact('client'))->with('server', $server);
}
After:
public function show($client) {
$machines = Clients::with(['machines' => function($query) {
//Filter eager loaded relation
return $query->where('OSNAME', 'LIKE', '%server%');
}, 'bios'])->where('TAG', $client)->get();
return view('audit', compact('client'))->with('machines', $machines);
}
See: https://laravel.com/docs/5.1/eloquent-relationships#constraining-eager-loads
The Right Way (Avoids unnecessary queries):
public function show($client) {
//Proper way to do it
$server = Machine::whereHas('client',function($query) use ($client){
return $query->where('TAG', $client)
})->where('OSNAME', 'LIKE', '%server%')->get();
return view('audit', compact('client'))->with('server', $server);
}

Resources