Laravel eloquent query join - laravel

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

Related

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

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 - passing array of columns in 'where' clause

I have a search query like this:
$data = User::where('first_name', 'like', '%'.$query.'%')
->orWhere('last_name', 'like', '%'.$query.'%')
->get();
Now, I have many models, each with different column names. Instead of defining a search() function into every controller, I want to do this:
// User
public static function searchableFields()
{
return ['first_name', 'last_name'];
}
// Some other model
public static function searchableFields()
{
return ['name', 'description'];
}
And put the search logic in a shared controller, something like this:
$data = $classname::
where($classname::searchableFields(), 'like', '%'.$query.'%')
->get();
How can I achieve this?
Thanks a lot.
You can loop over the fields and add them to your Eloquent query one by one.
$data = $classname::where(function ($query) use ($classname) {
foreach ($classname::searchableFields() as $field)
$query->orWhere($field, 'like', '%' . $query . '%');
})->get();
I would use scope for that.
You can create base model that all the models should extend (and this model should extend Eloquent model) and in this model you should add such method:
public function scopeMatchingSearch($query, $string)
{
$query->where(function($q) use ($string) {
foreach (static::searchableFields() as $field) {
$q->orWhere($field, 'LIKE', '%'.$string.'%');
}
});
}
Now you can make a search like this:
$data = User::matchingSearch($query)->get();
Just to avoid confusion - $query parameter passed to matchingSearch becomes $string parameter in this method.
You can try something like this.
// Controller
function getIndex(Request $request)
{
$this->data['users'] = User::orderBy('first_name','asc')->get();
if ($request->has('keyword')) {
$results = User::search($request->keyword);
$this->data['users'] = collect([$results])->collapse()->sortBy('first_name');
}
}
// Model
function search($keyword)
{
$results = [];
$search_list = ['first_name','last_name'];
foreach ($search_list as $value)
{
$search_data = User::where($value,'LIKE','%'.$keyword.'%')->get();
foreach ($search_data as $search_value) {
$exist = 0;
if (count($results)) {
foreach ($results as $v) {
if ($search_value->id == $v->id) {
$exist++;
}
}
if ($exist == 0) {
$results[] = $search_value;
}
} else{
$results[] = $search_value;
}
}
}
return $results;
}

Resources