how to set count(*) as field name in laravel - php

I am using larvel eloquent.
i am using this query using model. My code is
$books = Book::select('title', 'author', Book::raw('count(*) as copies'))
->where('title', 'like', '%'.$name.'%')
->orWhere(function ($query) use ($name) {
$query->where('author', 'like', '%'.$name.'%')
->where('subject', 'like', '%'.$name.'%');
})
->groupBy('title','author')
->get();
I got the error
"strtolower() expects parameter 1 to be string, object given"
I know the error is in count(). The code
raw('count() as copies') is used in table.
But I dont know how to use count(*) as copies in model eloquent. My model name is Book.
One more doubt i have, can we use multple fields in groupBy, ie
groupBy('title','author')

use selectRaw()
$books = Book::select('title', 'author'))
->where('title', 'like', '%'.$name.'%')
->orWhere(function ($query) use ($name) {
$query->where('author', 'like', '%'.$name.'%')
->where('subject', 'like', '%'.$name.'%');
})
->selectRaw('count(*) as copies')
->groupBy('title','author')
->get();

Try this, SelectRaw
$books = Book::select('title', 'author')
->selectRaw('count(*) as copies')
->where('title', 'like', '%'.$name.'%')
->orWhere(function ($query) use ($name) {
$query->where('author', 'like', '%'.$name.'%')
->where('subject', 'like', '%'.$name.'%');
})
->groupBy('title','author')
->get();
You have this posiblity also
->select('title','author', DB::raw('count(*) as copies'))
Laravel Documentation Raw

Related

Laravel With() along side with Where()

Take as example the following eloquent code:
Customers::with('ShippingMode')
->with('PaymentMethod')
->with('BarCodes')
->where(function($query) use ($find)
{
$query->where('name', 'like', "%$find%")
->orWhere('vat_number', 'like', "%$find%");
});
Now I would like to add more orWhere conditions but looking into PaymentMethod table, like such:
Customers::with('ShippingMode')
->with('PaymentMethod')
->with('BarCodes')
->where(function($query) use ($find)
{
$query->where('name', 'like', "%$find%")
->orWhere('vat_number', 'like', "%$find%")
->orWhere('PaymentMethod.description', 'like', "%$find%");
});
But this does not work as it returns the error:
Column not found: 1054 Unknown column 'PaymentMethod.descricao' in
'where clause'
I know that if I use the old joins it works great:
Customers::select('customer.*')
->from('customers AS customer')
->leftJoin('payment_methods AS payment_method', 'payment_method.id', '=', 'customer.payment_method_id')
->where(function($query) use ($find)
{
$query->where('name', 'like', "%$find%")
->orWhere('vat_number', 'like', '%$find%')
->orWhere('payment_method.description', 'like', '%$find%');
});
PLEASE NOTE: The variable $find can be empty and when it's empty it returns all the results without filter applied, which means I cannot use the whereHas function.
orWhereHas allow you to add customized constraints to a relationship constraint:
Customers::with('ShippingMode')
->with('PaymentMethod')
->with('BarCodes')
->where(function($query) use ($find) {
$query->where('name', 'like', "%$find%")
->orWhere('vat_number', 'like', "%$find%");
})->orWhereHas('PaymentMethod', function($query) use ($find) {
$query->where('description', 'like', "%$find%");
});
Something like this should work:
use Illuminate\Database\Eloquent\Builder;
Customers::with(['ShippingMode', 'PaymentMethod', 'BarCodes'])
->when($find, function (Builder $query, $find) {
$query->where(function (Builder $query) use ($find) {
$query->where('name', 'like', "%{$find}%")
->orWhere('vat_number', 'like', "%{$find}%")
->orWhereHas('PaymentMethod', function (Builder $query) use ($find) {
$query->where('description', 'like', "%{$find}%");
});
});
})->get();
With when() it will only apply the filter when $find has a value and it allows you to search on the Customer columns with the where() / orWhere() and the PaymentMethod relationship with orWhereHas().
You can read more about when() and whereHas() here:
when
whereHas

Laravel where clause is not returning data after multiple orWhere clauses?

I am using laravel 6.10 version in that I am implementing search,
I have 3 tables
1) course_category
2) course_sub_category
3) course [course_id_category(foreign key),course_sub_category_id(foreign key)]
below is my code
$course = $request->searchItem;
if ($course=="") {
$Courses = DB::table('course')
->join('course_category', 'course.course_category_id', '=', 'course_category.id')
->select('course.*','course_category.title as category_title','course_category.thumb as category_thumb')
->orderBy('course.title','asc')
->paginate(15);
}
else{
$Courses = DB::table('course')
->join('course_category', 'course.course_category_id', '=', 'course_category.id')
->join('course_sub_category', 'course.course_sub_category_id', '=', 'course_sub_category.id')
->select('course.*','course_category.title as category_title','course_category.thumb as category_thumb')
->where('course.title', 'LIKE', '%'.$course.'%')
->orWhere('course_category.title', 'LIKE', '%'.$course.'%')
->orWhere('course_sub_category.title', 'LIKE', '%'.$course.'%')
->get();
}
when i am retunring the values i am gatting 0 arrays but when i am removing one orwhere from existing my query is working and its returnig we all values with match
means when i am using multiple orWhere in laravel my where is not working, please share the solution on same.
->orWhere doesnt work like typical SQL. You should use it like that:
$Courses = DB::table('course')
->join('course_category', 'course.course_category_id', '=', 'course_category.id')
->join('course_sub_category', 'course.course_sub_category_id', '=', 'course_sub_category.id')
->select('course.*','course_category.title as category_title','course_category.thumb as category_thumb')
->where(function($query) use ($course){
$query->where('course.title', 'LIKE', '%'.$course.'%')
$query->orWhere('course_category.title', 'LIKE', '%'.$course.'%')
$query->orWhere('course_sub_category.title', 'LIKE', '%'.$course.'%')
})
->get();

How to return query from variable?

I try to search first_name, last_name and city but city is now always set whether the users want to set it with city or not. so I make query like this if request has city then filter it
$users = \App\User::join('profiles', 'users.id', '=', 'profiles.member_id')
->where(function($query) {
$query->where('first_name', 'like', '%z%')
->orWhere('last_name', 'like', '%z%');
})
->paginate(10);
if ($request->has('city')) {
$users->where('location', 'like', '%bandung%');
}
but where location like its like never used even request has city. i've try var_dump $users and count it and end up with no city query
Do little change in sequence of your lines of code:
$users = \App\User::join('profiles', 'users.id', '=', 'profiles.member_id')
->where(function($query) {
$query->where('first_name', 'like', '%z%')
->orWhere('last_name', 'like', '%z%');
});
if ($request->has('city')) {
$users->where('location', 'like', '%bandung%');
}
$users_data = $users->paginate(10);
The variable $users_data will be having proper result.

Laravel join with "and" and "or" in the where clause

How can I write a Laravel 5 Eloquent query like this SQL?
where ( (table1.fname like %xxxxx% )
OR (table1.lname like %xxxxx%) )
AND table1.is_active != 0
I have already tried
->where('users.is_active', '!=', 2)
->where('users.name', 'like' , '%'. $search .'%')
->orWhere('users.lname', 'like' , '%'. $search .'%')
->orWhere('users.email', 'like' , '%'. $search .'%') ->get();
Take a look at the Advanced join Clauses in Laravel Documentation
DB::table('users')
->join('contacts', function ($join) {
$join->on('users.id', '=', 'contacts.user_id')
->where('contacts.user_id', '>', 5);
})
->get();
joins
EDIT
I think i misunderstood the question. To do nested wheres you can do the following thing:
\DB::table('table1')->...->where(function($query) {
$query->where('table1.fname', 'like', '%xxxxx$')->orWhere('table1.lname', 'like', '%xxxx%);
})->where('table1.is_active', '!=', 0);
You can use Model for this:
TableModel::where('fname', 'like', '%xxxxx%')
->orWhere('lname', 'like', '%xxxxx%')
->where('is_active', '!=', 0)
->get();
$data = DB::table('table1')->where('fname', 'like', '%xxxxx%')
->orWhere('lname', 'like', '%xxxxx%')
->where('is_active', '!=', 0)
->get();
//add use DB; in your controller
To have grouped sub-clauses that should evaluate as a whole, you can pass where() a closure. Then you want a second where call for the check on the is_active column:
$value = '%xxxxx%';
$collection = Model::where(function ($models) use ($value) {
$models->where('fname', 'like', $value)
->orWhere('lname', 'like', $value);
})
->where('is_active', '!=', 0)
->get();

Laravel multiple where condition in whereHas callback

I am creating a general search function with Laravel 5.2 and I want to display all the books in which occurs the searched keyword in: the book's title, book's subject, book's plot, book's author name, book's author surname;
I thought that this code would work:
$results = Book::whereHas('author', function ($query) use ($keyword)
{
$query->where('surname', 'LIKE', '%'.$keyword.'%')
->orWhere('name', 'LIKE', '%'.$keyword.'%');
})
->orWhere('title', 'LIKE', '%'.$keyword.'%')
->orWhere('plot', 'LIKE', '%'.$keyword.'%')
->orWhere('subject', 'LIKE', '%'.$keyword.'%')
->get();
But when I use as a keyword the name of an author, I get as a results the whole library.
Instead if I enter the surname of an author it works perfectly.
I found out this solution, that is not optimal in my opinion, but at least it works:
$results = Book::whereHas('author', function ($query) use ($keyword)
{
$query->where('surname', 'LIKE', '%'.$keyword.'%');
})
->orWhereHas('author', function ($query) use ($keyword)
{
$query->where('name', 'LIKE', '%'.$keyword.'%');
})
->orWhere('title', 'LIKE', '%'.$keyword.'%')
->orWhere('plot', 'LIKE', '%'.$keyword.'%')
->orWhere('subject', 'LIKE', '%'.$keyword.'%')
->get();
Any suggestions?
Thank you in advance for your help!
The issue is that the where clauses added in your closure aren't the only where clauses being applied to the subquery. The whereHas() method generates a subquery that starts with a where clause on the ids for the relationship. Because of this, your subquery isn't just where x or y, it is actually where x and y or z.
Given this set of where clauses, and the order of operations for logical operators, if the z condition is true (your 'name' condition), the whole where clause will return true, meaning the constraint on only looking at related objects is completely ignored. Since the constraint on related objects is ignored, the has condition will be true for every record (if 'name' matches any record).
Below is an example of your logical conditions:
// first boolean is the related keys check
// second boolean is the surname check
// third boolean is the name check
// this is your current logic
// as you can see, this returns true even when looking at an
// author not even related to the book.
var_export(false && false || true); // true
// this is what your logic needs to be
var_export(false && (false || true)); // false
So, to solve this issue, you need to wrap your or conditions in parentheses, so they're evaluated as you intended. You can do this by passing a closure to the where() method, and then any conditions added inside the closure will be inside parentheses:
$results = Book::whereHas('author', function ($query) use ($keyword) {
$query->where(function ($q) use ($keyword) {
$q->where('surname', 'LIKE', '%'.$keyword.'%')
->orWhere('name', 'LIKE', '%'.$keyword.'%');
});
})
->orWhere('title', 'LIKE', '%'.$keyword.'%')
->orWhere('plot', 'LIKE', '%'.$keyword.'%')
->orWhere('subject', 'LIKE', '%'.$keyword.'%')
->get();
have you tried creating a local query scope for your author/user model such as named() then applying that
public function scopeNamed($query)
{
return $query->where('surname', 'LIKE', '%'.$keyword.'%')
->orWhere('name', 'LIKE', '%'.$keyword.'%');
}
Then your query
$results = Book::whereHas('author', function ($query) use ($keyword)
{
$query->named();
})
->orWhere('title', 'LIKE', '%'.$keyword.'%')
->orWhere('plot', 'LIKE', '%'.$keyword.'%')
->orWhere('subject', 'LIKE', '%'.$keyword.'%')
->get();
https://laravel.com/docs/master/eloquent#query-scopes

Categories