real-time data finder - search with multiple models - laravel

i need to make my search engine work with multiple data tables
right now get data from the model "Registro".
public function buscador(){
return view('posts.index');
}
public function search(Request $request){
$results = Registro::where('cliente', 'LIKE', "%{$request->search}%")->get();
return view('posts.results', compact('results'))->with(['search' => $request->search])->render();
}
public function show(Request $request){
$post = Registro::findOrFail($request->id);
return view('posts.post', compact('post'))->render();
}
can search with multiple models?

Multiple ways to do it
1-relation between these tables
and then use conditional with
example
$results = Registro::with(['relation' => function ($query) use ($request->variable) {
$query->where('relation_column', '=', $request->variable);
}])->where('cliente', 'LIKE', "%{$request->search}%")->get();
return view('posts.results', compact('results'))->with(['search' => $request->search])->render();
2- get all results from registro an then map it and for each index do a search in your other table with where inside
$results = Registro::where('cliente', 'LIKE', "%{$request->search}%")->get();
foreach($results as $result){
$res2=OtherTable::where('column',$result->something)->get();
if(sizeof($res2)){
//there is data do something
}
}

Related

output category with child categories and posts and pagination

I want to get category with all children subcategories and posts where id = category_id.
Posts should be paginated.
In category model I have 2 relations.
public function children() {
return $this->hasMany(self::class, 'parent_id');
}
public function posts() {
return $this->hasMany(Post::class, 'category_id');
}
In controller I have this function
public function getCategoryWithPaginatedPosts($slug, $perPage = null)
{
$columns = ['id', 'parent_id', 'title', 'slug', 'description', 'image'];
$postsColumns = ['category_id','title','text'];
$result = Category::whereSlug($slug)
->select($columns)
->with('children')
->with(['items' => function ($q) use ($postColumns) {
$q->wherePublished(true)
->select($postColumns)
->orderBy('id', 'ASC')
->paginate();
}])
->first();
}
Pagination doesn't work.
I just see that number of items is equal to $perPage parameter (and I have more items), but I don't see paginator inside dd($result->items)
It works like that, though I believe it is not the best way to do that.
So I can do it in few steps.
In first step I retrieve all data from DB and convert models to array, because I don't need models on webpage and I suppose it works faster like that. I would use ->toBase() if it could take mutators and relations from the model.
Second step I convert array into stdClass, because it is more comfortable in blade to work with object rather than with array.
Third step is to paginate items with mypaginate function (manual paginator in AppService Provider).
public function getCategoryWithPaginatedPosts($slug, $perPage = null)
{
$columns = ['id', 'parent_id', 'title', 'slug', 'description', 'image'];
$postsColumns = ['category_id','title','text'];
$result = Category::whereSlug($slug)
->select($columns)
->with('children')
->with(['items' => function ($q) use ($postColumns) {
$q->wherePublished(true)
->select($postColumns)
->orderBy('id', 'ASC');
}])
->first()
->toArray();
$result = Arr::arrayToObject($result);
$result->items = collect($result->items)->mypaginate($perPage);
return $result;
}
you should not use ->first() after ->paginate(), change something like this,
$result = Category::whereSlug($slug)
->select($columns)
->with('children')
->with(['items' => function ($q) use ($postColumns) {
$q->wherePublished(true)
->select($postColumns)
->orderBy('id', 'ASC')
}])
->paginate(20);

How to use whereHas method in Laravel scout,

I have been trying to search in both the name column and that's relationship. I have coded as below;
///
$posts = ContentForSearch::with("content_type","content_sub_type")->exclude($exclude)->user($user_id_filter)
->where('name', 'LIKE', "%{$search}%")
->orWhereHas('tags', function ($q) use ($search) {
$q->where('tag', 'LIKE', "%{$search}%");
})
->orderBy($sort, $order)
->paginate($limit);
I have set a searchable Model. I want to change with search method as below;
$posts = ContentForSearch::search($search)->orWhere(function ($query) use ($search) {
$query->whereHas('tags', function ($q) use ($search) {
$q->where('tag', 'LIKE', "%{$search}%");
});
})
->orderBy($sort, $order)
->paginate($limit)->load("content_type","content_sub_type");
Why isnt the code working ? How can i fix it ?
Model is:
class ContentForSearch extends Model{
use Searchable;
protected $table = 'content';
public function searchableAs()
{
return 'contents_index';
}
public function toSearchableArray()
{
$array = $this->toArray();
// Customize array...
return ["name"=> null];
}
public function content_type()
{
return $this->belongsTo(ContentType::class, 'content_type_id');
}
public function tags()
{
return $this->belongsToMany(ContentTag::class, 'content_content_tags', 'content_id', 'content_tags_id')->withTimestamps();
}
// * * *
The way fulltext search works with algolia and elastic, it seems weird that you want to preserve whereHas() relationship method. In my opinion it is an either or case, either you want sql relation search or you want full text, if you want full text, i would map all the tags at index building instead. So something like this would work.
public function toSearchableArray()
{
$customArray = $this->toArray();
$index = 1;
$this->tags->each(function(Tag $tag) use (&$customArray, &index) {
$customArray['tag' . $index++] = $tag->tag;
});
return $customArray;
}
Which will result in an object similar to this being indexed.
{
'name' => 'x',
'tag1' => 'comment',
'tag2' => 'post',
}
Now searching would provide a similar functionality.
ContentForSearch::search($search);

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

laravel 5.2 if else to query database

stuck on a form that allows the user to enter a value into a choice of two fields. I can query the database using one field but want to add more range to database queries. With the following code below when i try to access the page to query it just shows me a white screen.
public function index()
{
$data = $request->all();
if(!empty($data['pstoreNum']))
{
$pstoreNum = $data['pstoreNum'];
$result = DB::table('perfumes')->where('StoreNumber','=',$pstoreNum)
->get();
return view('perfumes',compact('result'));
}
else if(!empty($data['pweekNum']))
{
$pweekNum = $data['pweekNum'];
$result = DB::table('perfumes')->where('WeekNumber','=',$pweekNum)
->get();
return view('perfumes',compact('result'));
}
}
My routes file simple calls the index function. Any help would be appreciated.
You can add query functions within your query like so
public function index(Request $request)
{
$data = $request->all();
$result = \DB::table('perfumes')->where(function($query) use ($data) {
if(!empty($data['pstoreNum'])) {
$query->where('StoreNumber', '=', $data['pstoreNum']);
}
if(!empty($data['pweekNum'])) {
$query->where('WeekNumber', '=', $data['pweekNum']);
}
})->get();
return view('perfumes',compact('result'));
}
You can then use the one query and add multiple wheres on various conditions.
https://laravel.com/docs/5.2/queries#advanced-where-clauses

Resources