We've made a search system on our website, with a brands table being made. There are some brands that have spaces in their names and some that don't.
We have for example
"Turtle Wax"
What I'd like to do, is when a user searches for say Turtlewax my search looks for both versions...
Turtle Wax
TurtleWax
Is this even possible?
My current code is as follows...
$products = Product::select('product.*')
->join('brand', 'product.brand_id', '=', 'brand.id')
->join('child_product', 'product.id', '=', 'child_product.product_id')
->leftJoin('tax_rates', 'tax_rates.id', '=', 'child_product.tax_rate_id')
->with('brand', 'categories', 'childProducts', 'childProducts.attributeValues', 'images')
->where('product.active', true)
->where('brand.active', true)
->where(function ($query) use ($search_term)
{
$query->whereLike('product.name', $search_term)
->orWhereLike('product.description', $search_term)
->orWhere('brand.slug', str_slug($search_term, ''))
->orWhereLike('brand.slug', str_slug($search_term, '-'))
->orWhereLike('brand.name', str_replace(' ', '', $search_term))
->orWhere('brand.name', 'LIKE', '%'. $search_term);
})->get();
I have made 2 query scopes for the WhereLike and orWhereLike
public function scopeWhereLike($query, $column, $value)
{
return $query->where($column, 'like', '%'.$value.'%');
}
public function scopeOrWhereLike($query, $column, $value)
{
return $query->orWhere($column, 'like', '%'.$value.'%');
}
If they're using PascalCase ("TurtleWax"), you can do the following:
public function scopeWhereLike($query, $column, $value)
{
return $query
->where($column, 'like', '%'.implode(' ', preg_split('/(?=[A-Z])/', $value)).'%') // "word/space case"
->orWhere($column, 'like', '%'.ucwords(strtolower($value)).'%') // Titlecase
->orWhere($column, 'like', '%'.$value.'%'); // PascalCase
->orWhere("REPLACE(".$column.", ' ', '')", 'like', '%'.$value.'%'); // fallback
}
Related
I've been stuck onto a problem with laravel, since I'm new to this I try things, and things still don't work.
I have a search function that, seek through the users, using the name, the specialty of the user, or his location, the function work if you fill just one input, if you start to fill a second input, it shows the first condition which is coded in the controller.
Exemple :
if i put
Name : -empty-
Specialty : -empty-
Location : New
It shows me everyone that lives in cities starting with "New", but if I do
Name : Maria
Specialty : -empty-
Location : New
It shows me everyone whose name is Maria, or, I want "Maria" who live in cities starting with "New"
So I search how to make my code work with that, making if inside of if, making double condition, but since I'm with laravel I have trouble doing it (my version is 5.0, i'll go for update after this bug is resolved)
Here is the part where I'm stuck on, with the things I tried,
if($attributs['specialty'] != "") {
$users = User::where('status_user', '=', '1')
->where('specialty_id', $attributs['specialty'])
->where('city', 'LIKE', '%'.$attributs['locality'].'%') //;
/* if($attributs['name']!= ""){
$query->where(function ($query) use ($name){
$query->where(('CONCAT(lastname, " ", firstname)'), 'LIKE', $name.'%')
->orWhere(('CONCAT(firstname, " ", lastname)'), 'LIKE', $name.'%');
})
}
->where('address', 'LIKE', '%'.$attributs['locality'].'%')
->where(DB::raw('CONCAT(address, " ", postal_code, " ", city)'), 'LIKE', '%'.$address.'%')*/
->confirmed()
->get();
}
else if($attributs['name'] != ""){
$users = User::where(function ($query) use ($name) {
$query->where(function ($query) use ($name) {
$query->where(DB::raw('CONCAT(lastname, " ", firstname)'), 'LIKE', $name.'%')
->orWhere(DB::raw('CONCAT(firstname, " ", lastname)'), 'LIKE', $name.'%');
})
->where('status_user', '=', '1')
->confirmed();
})
->orWhere(function ($query) use ($name) {
$query->where(function ($query) use ($name) {
$query->where(DB::raw('CONCAT(lastname, " ", firstname)'), 'LIKE', $name.'%')
->orWhere(DB::raw('CONCAT(firstname, " ", lastname)'), 'LIKE', $name.'%');
})
->where('status_user', '=', '1')
->where('invite', '=', '1');
})
->get();
}
else if($attributs['address'] != ""){
$users = User::where('status_user', '=', '1')
->where('address', 'LIKE', '%'.$attributs['locality'].'%')
->where(DB::raw('CONCAT(address, " ", postal_code, " ", city)'), 'LIKE', '%'.$address.'%')
->confirmed()
->get();
}
Thanks in advance, it's been days since I'm on it ><
Edit : Here's a few more info since it isn't not that clear, sorry about that
I want to make multiple search, the code I present you works, but do not provides multiple search, i tried to make if with multiple condition, and it don't work, i tried to make several where clause with if inside of the first if, and it don't work either, so here I am, thanks a lot in advance, but I'm still stuck ^^'
Try when() conditional operator. https://laravel.com/docs/5.7/queries#conditional-clauses
$users = User::when($attributs['specialty'] != "", function($q){
return $q->where('status_user', '=', '1')
->where('specialty_id', $attributs['specialty'])
->where('city', 'LIKE', '%'.$attributs['locality'].'%')
->confirmed();
})
->when($attributs['name'] != "", function($q){
return $q->where(function ($query) use ($name) {
$query->where(function ($query) use ($name) {
$query->where(DB::raw('CONCAT(lastname, " ", firstname)'), 'LIKE', $name.'%')
->orWhere(DB::raw('CONCAT(firstname, " ", lastname)'), 'LIKE', $name.'%');
})
->where('status_user', '=', '1')
->confirmed();
})
->orWhere(function ($query) use ($name) {
$query->where(function ($query) use ($name) {
$query->where(DB::raw('CONCAT(lastname, " ", firstname)'), 'LIKE', $name.'%')
->orWhere(DB::raw('CONCAT(firstname, " ", lastname)'), 'LIKE', $name.'%');
})
->where('status_user', '=', '1')
->where('invite', '=', '1');
})
})
->when($attributs['address'] != "", function($q){
return $q->where('status_user', '=', '1')
->where('address', 'LIKE', '%'.$attributs['locality'].'%')
->where(DB::raw('CONCAT(address, " ", postal_code, " ", city)'), 'LIKE', '%'.$address.'%')
->confirmed();
})
->get();
I have a table and search bar.
When user input in the search that when I grab that and query my database.
This is what I got
public function getLogsFromDb($q = null) {
if (Input::get('q') != '') {
$q = Input::get('q');
}
$perPage = 25;
if ($q != '') {
$logs = DB::table('fortinet_logs')
->orWhere('account_id', 'like', '%'.$q.'%')
->orWhere('cpe_mac', 'like', '%'.$q.'%')
->orWhere('p_hns_id', 'like', '%'.$q.'%')
->orWhere('g_hns_id', 'like', '%'.$q.'%')
->orWhere('data', 'like', '%'.$q.'%')
->orWhere('created_at', 'like', '%'.$q.'%') <----🐞
->orderBy('updated_at', 'desc')->paginate($perPage)
->setPath('');
//dd($logs);
$logs->appends(['q' => $q]);
} else {
$logs = DB::table('fortinet_logs')
->orderBy('created_at', 'desc')->paginate($perPage)
->setPath('');
}
return view('telenet.views.wizard.logTable', get_defined_vars());
}
Result
In the network tab, I kept getting
Undefined function: 7 ERROR: operator does not exist: timestamp without time zone ~~ unknown
How would one go about debugging this further?
PostgreSQL is strict about different data types. Convert the timestamp column to text:
->orWhereRaw('created_at::text like ?', ['%'.$q.'%'])
sanitize your inputs to avoid such problems
$remove = array("'","!",";","+",'|','||',"&&","}","{","[","]");
$replace = array("","","","","","","","","","","");
$q = str_replace($remove, $replace, $q);
Use the new defined $q in your queris
first step on debuggin to make an sql by tihs. And you look what is the problem for your query.
Like this:
dd($logs = DB::table('fortinet_logs')
->orWhere('account_id', 'like', '%'.$q.'%')
->orWhere('cpe_mac', 'like', '%'.$q.'%')
->orWhere('p_hns_id', 'like', '%'.$q.'%')
->orWhere('g_hns_id', 'like', '%'.$q.'%')
->orWhere('data', 'like', '%'.$q.'%')
->orWhere('created_at', 'like', '%'.$q.'%')//This is the cri
->orderBy('updated_at', 'desc')->toSql());
This is show for you whats the problem of this query.
By the way, can you cast $q to daterange and can find in this range the logs.
I use this : https://github.com/rinvex/repository
My query is like this :
$query = $this->store_repository
->join('favorites', function ($join) {
$join->on('stores.id', '=', 'favorites.favoritable_id')
->where('favorites.favoritable_type', 'like', 'App\\\Models\\\Store');
})
->where('stores.status', '=', 1)
->select('stores.id', 'stores.name', 'stores.photo','stores.address');
if($location)
$query->where('stores.address', 'like', "%$location%");
if($q) {
$query->where('stores.name', 'like', "%$q%")
->where('stores.address', 'like', "%$q%", 'or');
}
$result = $query->orderBy('favorites.updated_at', 'desc')->paginate($num);
When executed, there exist error like this :
Missing argument 3 for
Rinvex\Repository\Repositories\BaseRepository::join()
How can I solve it?
I don't think you need the clojure to make what you want.
I guess this should be fine :
$query = $this->store_repository
->join('favorites', '=', 'favorites.favoritable_id')
->where('favorites.favoritable_type', 'like', 'App\\\Models\\\Store');
->where('stores.status', '=', 1)
->select('stores.id', 'stores.name', 'stores.photo','stores.address');
I want do following query in laravel elequent
select from table where cond1 and(cond or cond or cond..)and cond3.
I have used following code,
$invoice = Invoice::with("items", "salesPerson", "client");
if ($q = Request::input("q")) {
$invoice->where("invoices.invoice_number", 'LIKE', "%$q%");
$invoice->orWhere("invoices.reference_number", 'LIKE', "%$q%");
$invoice->orWhere("invoices.client_name", 'LIKE', "%$q%");
$invoice->orWhere("invoices.invoice_date", 'LIKE', "$q%");
$invoice->orWhere("invoices.due_date", 'LIKE', "$q%");
}
$invoice->whereNull("invoices.deleted_at");
but it return deleted records as well.How can I fix this?
In this case a nested where comes in handy:
$invoice = Invoice::with("items", "salesPerson", "client");
if ($q = Request::input("q")) {
$invoice->where(function($query) use ($q){
$query->where("invoices.invoice_number", 'LIKE', "%$q%");
$query->orWhere("invoices.reference_number", 'LIKE', "%$q%");
$query->orWhere("invoices.client_name", 'LIKE', "%$q%");
$query->orWhere("invoices.invoice_date", 'LIKE', "$q%");
$query->orWhere("invoices.due_date", 'LIKE', "$q%");
});
}
$invoice->whereNull("invoices.deleted_at");
I'm trying to search two optional tables using eloquent:
$users = User::where('ProfileType', '=', 2)
->where(function($query) {
$query->where('BandName', 'LIKE', "%$artist%");
$query->or_where('Genre', 'LIKE', "%$genre%");
})->get();
This works fine for return all results when a user does an empty search, but I am not sure how to adjust this for to search for bandname when that is present and vise versa.
Just to explain what happens on answer below:
Eloquent does a tricky thing here: When you call User::where(...) it returns a Database\ Query object. This is basically the same thing as DB::table('users')->where(...), a chainable object for constructing SQL queries.
So having:
// Instantiates a Query object
$query = User::where('ProfileType', '=', '2');
$query->where(function($query) {
// Adds a clause to the query
if ($artist = Input::get('artist')) {
$query->where_nested('BandName', 'LIKE', "%$artist%", 'OR');
}
// And another
if ($genre = Input::get('genre')) {
$query->where_nested('Genre', 'LIKE', "%$genre%", 'OR');
}
});
// Executes the query and fetches it's results
$users = $query->get();
Building on Vinicius' answer here's what worked:
// Instantiates a Query object
$query = User::where('ProfileType', '=', '2');
// Adds a clause to the query
if ($artist = Input::get('artist')) {
$query->where('BandName', 'LIKE', "%$artist%");
// Temp Usernamesearch
$query->or_where('NickName', 'LIKE', "%$artist%");
}
// Genre - switch function if artist is not empty
if ($genre = Input::get('genre')) {
$func = ($artist) ? 'or_where' : 'where';
$query->$func('Genre', 'LIKE', "%$genre%");
}
// Executes the query and fetches it's results
$users = $query->get();
Turns out that the second optional field must use or_where only if $artist is not set.
Thanks for your help
I think this is what youre after. Your view would have a form to search artist/genre one or the other can be set, or both, or none.
$users = User::where('ProfileType', '=', 2);
if (Input::has('artist')) {
$users = $users->where('BandName', 'LIKE', '%'.Input::get('artist').'%');
}
if (Input::has('genre')) {
$users = $users->where('Genre', 'LIKE', '%'.Input::get('genre').'%');
}
$users = $users->get();
$query = FormEntry::with('form')->where('domain_id', $id);
$query->where(function($query) use ($search, $start, $limit, $order, $dir) {
$query->where('first_name', 'LIKE', "%{$search}%")
->orWhere('last_name', 'LIKE', "%{$search}%")
->orWhere('email', 'LIKE', "%{$search}%")
->offset($start)
->limit($limit)
->orderBy($order, $dir);
});
$entries = $query->get();
$totalFiltered = $query->count();