Laravel eloquent search functionality - laravel

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).

Related

How to search from relationship data ? In laravel

public function scopeSearch($query, $value)
{
$searchValues = explode(' ', $value);
if (!$value) return $query;
return $query->where(function ($q) use ($searchValues) {
foreach ($searchValues as $token) {
$q->orWhere('name', 'like', "%{$token}%");
$q->orWhere('street', 'like', "%{$token}%");
}
});
}
I want to search the data. This model also has
public function brands()
{
return $this->belongsToMany(Brand::class, 'dealer_brands');
}
public function province()
{
return $this->belongsTo(Province::class);
}
How can I get data from the relastionship. Like Dealer(model) has data Nmae = josh , brand_id = 1 {brand.name = samsung} , province_id = 2 (province.name = "aligora"). When I search Josh Samsung Alogora, I want to ge the data. When I only search aligora, I want to get the data of model having province aligora. hOW CAN I MODIFY CODE?
looking at your model relationships. This may work for you
public function scopeSearch($query, $value)
{
if (!$value) return $query;
$searchValues = explode(' ', $value);
return $query->where(function ($q) use ($searchValues) {
foreach ($searchValues as $token) {
$q->where('name', 'like', "%{$token}%")
->orWhere('street', 'like', "%{$token}%")
->orWhereHas('brands', function ($sub_q) use ($searchValues) {
$sub_q->where('name', 'like', "%{$token}%")
->orWhere('street', 'like', "%{$token}%");
})
->orWhereHas('province', function ($sub_q) use ($searchValues) {
$sub_q->where('name', 'like', "%{$token}%")
->orWhere('street', 'like', "%{$token}%");
});
}
});
}
I have no idea about column names in related tables so repeating name and street. you can change as per requirement

How in Laravel filter by relationship?

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];
}

laravel 5- get related products by search in Many To Many

Table 1: products: id,title
Table 2: features: id,name,values
Table 3:feature_product:id,product_id,values
I want get all related products when I search in values in feature_product table.
I do these:
in product model:
public function features()
{
return $this->belongsToMany(Feature::class)->withPivot('values');
}
public function feature()
{
// ???
}
and query for search:
$q = 'yellow';
$query->where(function($query) use ($q)
{
$query->WhereHas('feature' , function ($query) use
($q){$query->where('values' , 'LIKE' , '%' . $q . '%' );});
}
how can I search in related features of products? (and get those products)
I think I must do something in this function in product model:
public function feature()
{
// ???
}
in product model:
public function features()
{
return $this->belongsToMany(Feature::class)->withPivot('values');
}
public function feature()
{
// ??
}
in Feature Model:
public function products(){
return $this->belongsToMany('App\Product')->withPivot('values');
}
and query search
$query->WhereHas('features' , function ($query) use ($q) {
$query->where('feature_product.values' , 'LIKE' , '%' . $q . '%' );
});

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'));
}

Laravel: get data from variouos tables based on optional conditions

I want to write a query based on optional condition that will fetch data from different tables. My schema looks like
myboxes Table
id,
type_id --> foreign key to box_type table
postal_code
po_box
created_at
updated_at
mybox_access table
id
mybox_id -> foreign key to myboxes table
email
box_type table
id
type_name
And here are my models
MyBox.php
class MyBox extends Model {
public function type() {
return this->hasOne(BoxType::class, 'id', 'type_id');
}
public function access() id
return this->hasOne(MyBoxAccess::class, 'mybox_id', 'type_id');
}
}
MyBoxType.php has following relation ship
public function mybox() {
return this->hasOne(MyBox::class, 'id', 'type_id');
}
And MyBoxAccess.php has following relationship
public function vbox() {
return $this->belongsTo(MyBox::class, 'id', 'mybox_id');
}
Now I want to get based on following condition
I have email as required param and postal_code and po_box as optional params (but one of them will be must and both can also be present).
So I want to get data of all my_boxes that have type_id 3 OR all myboxes whoes id matches to email in mybox_access table AND postal_code or po_box matches to params in myboxes table
For simple match of params postal code and po_box I can write some thing like
$result = new MyBox();
if(!empty($request['postal_code'])) {
$result->where('postal_code', like, '%'.$request['postal_code']);
}
if(!empty($request['po_box'])) {
$result->where('po_box', like, '%'.$request['po_box']);
}
$result = $result->get();
But I don't know how to get data for above mentioned condition. When I try to do using with() like
MyBox::with(['access' => function(Builder $query) use ($request){
$query->where('mybox_id',$request['id']);
}])->get();
I get
`Argument 1 Passed to {closure} () must be an instance of Illuminat\Database\Query\Builder, instance of Illuminate\Databaase\Eloquent\Relation\HasOne given`
Can any body please let me know how can I get data based on above mentioned condition
$query is a relationship, not a builder instance.
So this should not throw any Exception.
MyBox::with(['access' => function ($query) {
$query->where('mybox_id', $request['id']);
}])->get();
But I don't think it'd resole your issue because your Box <=> Access relationship is not right. It should be HasMany.
// MyBox.php
public function type()
{
return $this->hasOne(BoxType::class, 'id', 'type_id');
}
public function access()
{
return $this->hasMany(MyBoxAccess::class, 'mybox_id', 'id');
}
Then in your Controller you could do this.
// $results where type_id is 3
$results = MyBox::where('type_id', 3)->get();
// List of boxes accessible by email
$results = MyBox::whereHas('access', function ($query) {
$query->where('email', request()->input('email'));
})->get();
// Results where postal_code and po_box matches the request
$results = MyBox::with('access')->where(function ($query) {
if (request()->has('postal_code')) {
$query->where('postal_code', 'like', '%' . request()->input('postal_code'));
}
if (request()->has('po_box')) {
$query->where('po_box', 'like', '%' . request()->input('po_box'));
}
})->get();
And if you want to merge all conditions:
$results = MyBox::where(function ($query) {
if (request()->has('type_id')) {
$query->where('type_id', request()->input('type_id'));
}
if (request()->has('email')) {
$query->whereHas('access', function ($query) {
$query->where('email', request()->input('email'));
});
}
if (request()->has('postal_code')) {
$query->where('postal_code', 'like', '%' . request()->input('postal_code'));
}
if (request()->has('po_box')) {
$query->where('po_box', 'like', '%' . request()->input('po_box'));
}
})->get();
I always use the request() facade when using in closures, it feels cleaner to me.
Try this query:
MyBox::with('access')->get();

Resources