Laravel Eloquent - Conditional Data Fetching - php

I've a customer and customer group table. I want to search the customers based on term/filter text.
Say, there is two customer_group_id, 7 and 8. When 8, I'll need to find mobile fields in orWhere clause, otherwise not.
What I've tried is
$contacts = Contact::where(function ($query) use ($term) {
$query->where('contacts.name', 'like', '%' . $term .'%')
});
// For customer_group_id=8
$contacts->when('customer_group_id=8', function($q) use ($term){
return $q->orWhere('mobile', 'like', '%' . $term .'%');
});
The when() is not working. It showing all the results. I know that I've to pass any boolean value in the when() functions first parameter.
Is there any solution for this problem? Or what is the other way I can get the data's.

The when() method doesn't add an if statement to your query, it is just a way to save you from writing an if statement in your code.
To achieve what you're after you can use nested orWhere() clause:
$contacts = Contact::where('name', 'like', '%' . $term . '%')
->orWhere(function ($query) use($term) {
$query->where('customer_group_id', 8)->where('name', 'like', '%' . $term . '%');
})
->get();
If there is more to your query than what you've put in your question then you can simply wrap the above in another where clause:
$contacts = Contact::where(function ($query) use ($term) {
$query->where('name', 'like', '%' . $term . '%')
->orWhere(function ($query) use ($term) {
$query->where('customer_group_id', 8)->where('name', 'like', '%' . $term . '%');
});
})
->where('some column', 'some value')
->get();

Related

How to Fetch data from multiple tables using relationships in laravel on certain conditions?

I am fetching data from multiple tables by joining them and the relationship is one to many and one to one
Everything works fine as I am using joins with raw method (directly writing queries) but I want to use Laravel sophistication which means I am looking to use with() has() or whereHas() to get same results.
My Query that works fine in controller
$licenses = DB::table('licenses')
->join('users as u', 'u.id', '=', 'licenses.user_id')
->join('users as sp', 'sp.id', '=', 'licenses.sales_person_id')
->join('license_types', 'license_types.id', '=', 'licenses.license_type_id')
->select('licenses.*', 'license_types.*', 'u.first_name', 'u.last_name', 'u.email', 'sp.first_name as fname', 'sp.last_name as lname')
->where('u.first_name', 'LIKE', '%' . $query . '%')
->orWhere('u.last_name', 'LIKE', '%' . $query . '%')
->orWhere('u.email', 'LIKE', '%' . $query . '%')
->orWhere('sp.first_name', 'LIKE', '%' . $query . '%')
->orWhere('sp.last_name', 'LIKE', '%' . $query . '%')
->get();
My License Model
public function user()
{
return $this->hasOne('App\User','id','user_id');
}
public function license_type()
{
return $this->hasOne('App\LicenseType','id','license_type_id');
}
The Response I get when the above mentioned query is executed
#items: array:1 [
0 => {#444
+"id": 1
+"user_id": 2
+"sales_person_id": 3
+"license_type_id": 1
+"license": "CCVTGS7S0R4M8P7R7S3R"
+"license_duration": 23
+"license_expiry": null
+"allowed_test": "fef"
+"no_of_devices_allowed": 1
+"is_deleted": 0
+"trial_activated_at": "2021-03-10 10:18:04"
+"license_activated_at": null
+"user_device_unique_id": "a9dc00sssd6daf79"
+"is_active": 1
+"created_at": null
+"updated_at": null
+"title": "monthly"
+"price": "232"
+"type": 2
+"first_name": "Mohammad"
+"last_name": "Fahad"
+"email": "apexlegendsisracistt#gmail.com"
+"fname": "Mohammad"
+"lname": "Fahad"
}
]
I want to get the same results with the Laravel eloquent but when I use with I dont know how to specify where conditions and to get same output.
you can try something like this
$licenses = License::with(['license_type', 'user', 'salesPerson'])
->whereHas('user', function ($q) use ($query) {
$q->where('first_name', 'LIKE', '%' . $query . '%')
->orWhere('last_name', 'LIKE', '%' . $query . '%')
->orWhere('u.email', 'LIKE', '%' . $query . '%');
})
->whereHas('salesPerson', function ($q) use ($query) {
$q->where('first_name', 'LIKE', '%' . $query . '%')
->orWhere('last_name', 'LIKE', '%' . $query . '%')
->orWhere('u.email', 'LIKE', '%' . $query . '%');
})->get();
in model you need to create another relationship
public function salesPerson()
{
return $this->hasOne('App\User', 'id', 'sales_person_id');
}
NOTE this is not exact solution but you can modify as per your need
ref link https://laravel.com/docs/8.x/eloquent-relationships#querying-relationship-existence

Joining two models in Laravel Eloquent

I have a model stored in a variable like:
$user = User::where('name', 'like', $test)
->orderBy('name');
I would like to build another query where I can join $user. Can't find the right syntax to do it.
What am trying to achieve:
$numbers= Number::join($user, $users.id, '=', 'number.user_id')
->where('name', 'like', "%" . $validated['text'] . "%")])
->get();
Assuming you have typical hasMany/belongsTo relationships set up between User and Number models, this should work:
User::where("name", "like", $test)
->whereHas("numbers", function($q) {
$q->where("name", "like", "%$validated[text]%");
})
->with("numbers", function($q) {
$q->where("name", "like", "%$validated[text]%");
})
->get();
The where() method, of course, matches users with the desired name. The whereHas() method further restricts based on the relationship, looking only for users having numbers with a matching name. Assuming you want to retrieve those matching numbers, you have to do the same filter again on the eager load.
Try this,
$numbers= Number::whereHas('<Your Eloquent Model>',function($query)use($validated){
$query->where('name', 'like', "%" . $validated['text'] . "%")]);
}
->get();
Join can be written in this way
$records = User::select('users.*')
->where('users.name', 'like', $test)
->join('numbers', function($join) {
$join->on('users.id', '=', 'numbers.id')
->where('numbers.name', 'like', "%" . $validated['text'] . "%");
})
->get();

How can i find only deleted rows in Laravel?

I'm using SoftDeletesin my projects, which is recognized as deleted_at in database table, I want to search and find only deleted rows.
Here is my controller code
public function trashedJobSearch(Request $request)
{
$search = $request->get('search');
$jobs = Jobs::select('id', 'company_name', 'position_name', 'job_description','deleted_at', 'created_at', 'expire_date', 'status')
->where(DB::raw('lower(company_name)'), 'like', '%' . mb_strtolower($search) . '%')
->orWhere(DB::raw('lower(position_name)'), 'like', '%' . mb_strtolower($search) . '%')
->where('deleted_at', '!=', null)
->paginate(10);
return view('/trashed', compact('jobs'));
}
I tried to use onlyTrashed() but it's not working either.
As you have orWhere you need to use a grouping and also onlyTrashed
Jobs::select('id', 'company_name', 'position_name', 'job_description','deleted_at', 'created_at', 'expire_date', 'status')
->where(function ($query) use ($search) {
$query->where(DB::raw('lower(company_name)'), 'like', '%' . mb_strtolower($search) . '%')
->orWhere(DB::raw('lower(position_name)'), 'like', '%' . mb_strtolower($search) . '%');
})->onlyTrashed()
->paginate(10);
The onlyTrashed() method should work for you. Docs for Laravel deleted entries. I have seen times where adding the raw select statement screws it up though.
Take out the extra bits with the select and DB::raw and then add them in after you have what you need. Start with the simplest:
$testOfDeletedOnlyJobs = Jobs::onlyTrashed()->get();
From here, add in the other parts of your query to see where and why it fails. If the above gives you nothing, perhaps there are no deleted records?
You can use
Model::onlyTrashed()->get();
Did you have looking for this post yet?
How to get all rows (soft deleted too) from a table in Laravel?
You can try this.
In your Model-
use Illuminate\Database\Eloquent\SoftDeletes;
class ModelName extends Model
{
use SoftDeletes;
}
To get only deleted rows
$search = $request->get('search');
$data = App\ModelName::onlyTrashed()
->where('id', $search)
->get();

how to limit the number of data in where has query laravel

I have a query like so
$data = City::with('hotel')->orwherehas('hotel', function ($query) use ($user_input) {
//here i want to limit this result to 5
$query->where('name', 'LIKE', '%' . $user_input . '%')->take(5);
// $query->take(5); i have tried this too
})->orWhere('name', 'LIKE', '%' . $user_input . '%')->get();
inside the whereHas clause, I have a query that I want to limit to 5, now I tried limit, take but no luck after that where nothing is working I don't know why
You can pass your query to the ->with() query builder method:
$data = City::with(['hotel' => function($query) use ($user_input) {
$query->where('name', 'LIKE', '%' . $user_input . '%')->limit(5);
}])
->where('name', 'LIKE', '%' . $user_input . '%')
->get();
This will get all hotels associated with a city which have the user input, where the city contains the user input.
Note that the ->orWhere() is not used here.

How to use count and orderBy on eloquent multiple relationship fields?

What I'm trying to do is setup a server side configuration for a table data. So I have a model CounterLog that has 3 relationships set [belongsTo] category, location, user. I want a query to filter all CounterLog data including relationships, with offset, limit and orderBy methods set and in the same time retrieve all the filtered rows ignoring offset and limit. Here is what I managed until now and maybe understand better what I want:
$search_query = function($q) use ($search) {
$q->where('name', 'like', '%' . $search . '%');
};
$query = CounterLog::where('created_at', 'like', '%' . $search . '%')
->orWhereHas('category', $search_query)
->orWhereHas('location', $search_query)
->orWhereHas('user', $search_query);
$logs = $query->offset($offset)->limit($limit)->get();
$logs_total = $query->offset(0)->count();
In the last line I'm using $query->offset(0) because for some reason if offset is set to a number $logs_total becomes 0. I'm not sure this is the proper way to do it.. but even like this I have no idea how to use orderBy for ex. category.name.
I know I can always use raw queries in eloquent but I want to know if there is a way to use ORM and relationships. I would really appreciate if you could help me with this..cuz the struggle is real.
Thanks a lot :)
Apparently I haven't got a solution with ORM so I did it with "raw" queries:
$query = $this->db->table('counter_logs')
->leftJoin('categories', 'counter_logs.category_id', '=', 'categories.id')
->leftJoin('locations', 'counter_logs.location_id', '=', 'locations.id')
->leftJoin('users', 'counter_logs.user_id', '=', 'users.id');
->where('counter_logs.created_at', 'like', '%' . $search . '%')
->orWhere('categories.name', 'like', '%' . $search . '%')
->orWhere('locations.name', 'like', '%' . $search . '%')
->orWhere('users.name', 'like', '%' . $search . '%');
->select('counter_logs.id as id', 'categories.name as category', 'locations.name as location', 'users.name as user', 'counter_logs.created_at as date');
$json['total'] = $query->count();
$logs = $query->offset($offset)->limit($limit)->orderBy($sort, $order)->get();
Try to swap statements:
$logs_total = $query->count();
$logs = $query->offset($offset)->limit($limit)->get();
Or clone base query, like this:
$total_count_query = clone $query;
$logs = $query->offset($offset)->limit($limit)->get();
$logs_total = $total_count_query->count();

Categories