How can I use this mysql query to laravel 5.2? - laravel

I want to use below sql query into laravel 5.2
SELECT * FROM `products` WHERE soundex(`products`.`name`)=soundex('Neckholder Creme');
I Have tried here like
return $query->select([ 'products.slug', 'products.id', 'sku', 'name', 'regular_price', 'sale_price', 'sale_from', 'sale_to', 'stock_status', 'product_type', 'featured_image_id' ])
->with('media_featured_image')
->with('categories')
->where('products.product_type', '<>', 'variation')
->where('products.status', 'publish')
->where(function($query) use ($keyword){
foreach($keyword as $k){
$query->where('soundex(products.name)',soundex($k));
}
})
->paginate(120);
But it gives an error like below and having issue because of `` in column name
Column not found: 1054 Unknown column 'soundex(products.name)' in 'where clause' (SQL: select count(*) as aggregate from `products` where exists (select * from `categories` inner join `category_product` on `categories`.`id` = `category_product`.`category_id` where `category_product`.`product_id` = `products`.`id` and `categories`.`slug` <> shoparchiv) and `products`.`product_type` <> variation and `products`.`status` = publish and (`soundex(products`.`name)` = C352 and `soundex(products`.`name)` = J520))
How can I use in Laravel ? Any help will be appreciated.
Thanks

If you need just basic query then you can use DB::raw (documentation)
select(DB::raw('SELECT * FROM products WHERE soundex(products.name)=soundex("Neckholder Creme")'));
Or you can use whereRaw in eloquent and use it in your existing query (documentaion)
return $query->select([ 'products.slug', 'products.id', 'sku', 'name', 'regular_price', 'sale_price', 'sale_from', 'sale_to', 'stock_status', 'product_type', 'featured_image_id' ])
->with('media_featured_image')
->with('categories')
->where('products.product_type', '<>', 'variation')
->where('products.status', 'publish')
->where(function($query) use ($keyword){
foreach($keyword as $k){
$query->whereRaw("soundex(products.name) = '".soundex($k)."'");
}
})
->paginate(120);
Hope it helps

Related

How to fix Laravel query builder where clause integer variable translated to string

I have a function to get a pass a language number to get language categories record for API purpose. I use a database query statement to select categories table and join the category language table to get category id, parent_id and name (specified language). When execute return error and select the underlying SQL converted the language value to string (e.g. languages_id = 1). I google a lot and no ideas what's wrong. Can anyone advise how to resolve. Thanks a lot.
I tried to copy the underlying SQL to MySQL Workbench and remove the languages_id = 1 --> languages_id = 1 can working properly. I guess the 1 caused error.
Code Sample:
private function getCategories($language) {
$categories = DB::table('categories')
->select(DB::raw('categories.id, categories.parent_id, categories_translation.name'))
->join('categories_translation', function($join) use ($language) {
$join->on('categories_translation.categories_id', '=', 'categories.id');
$join->on('categories_translation.languages_id', '=', $language);
})
->where([
['parent_id' ,'=', '0'],
['categories.id', '=', $id]
])
->get();
return $categories;
}
Error return the converted SQL:
"SQLSTATE[42S22]: Column not found: 1054 Unknown column '1' in 'on
clause' (SQL: select categories.id, categories.parent_id,
categories_translation.name from categories inner join
categories_translation on categories_translation.categories_id =
categories.id and categories_translation.languages_id = 1
where (parent_id = 0 and categories.id = 1))"
You are trying to join using a comparison to an scalar value, instead of a column. I think you actually want to put that comparison as a "where" condition, rather than a "join on"
->where([
['parent_id' ,'=', '0'],
['categories.id', '=', $id],
['categories_translation.languages_id', '=', $language]
])
there is another thing i just discover with your code. when joining table, you are suppose to be joining 'categories_translation.languages_id' with another table id field. in your case, it is not so. you are not joining 'categories_translation.languages_id' with any table field. so ideally, what you are going to do is this
private function getCategories($language) {
$categories = DB::table('categories')
->select(DB::raw('categories.id, categories.parent_id, categories_translation.name'))
->join('categories_translation', function($join) use ($language) {
$join->on('categories_translation.categories_id', '=', 'categories.id');
})
->where([
['parent_id' ,'=', '0'],
['categories.id', '=', $id]
['categories_translation.languages_id', '=', $language]
])
->get();
return $categories;
}
hope this helps

Perform order by relationship field in Eloquent

I want to create product filter with Eloquent.
I start like this
$query = Product::whereHas('variants')
->with('variants')
->with('reviews')
$query = $this->addOrderConstraints($request, $query);
$products = $query->paginate(20);
Where
private function addOrderConstraints($request, $query)
{
$order = $request->input('sort');
if ($order === 'new') {
$query->orderBy('products.created_at', 'DESC');
}
if ($order === 'price') {
$query->orderBy('variants.price', 'ASC');
}
return $query;
}
However, that doesn't work, cause Eloquent is performing this query like this (information from Laravel DebugBar)
select count(*) as aggregate from `products` where exists
(select * from `variants` where `products`.`id` = `variants`.`product_id`)
select * from `products` where exists
(select * from `variants` where `products`.`id` = `variants`.`product_id`)
select * from `variants` where `variants`.`product_id` in ('29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48')
And so on
So when I try to use sorting by price it just obvious error
Unknown column 'variants.price' in 'order clause' (SQL: select * from
`products` where exists (select * from `variants` where `products`.`id` =
variants.product_id) order by variants.price asc limit 20 offset 0)
So is it possible to perform relationship ordering with Eloquent or not?
This will sort the subquery. Not the "first query (the product query)".
Basically, your subquery will be:
select * from variants where product_id in (....) order by price, and that is not what you want, right?
<?php
// ...
$order = $request->sort;
$products = Product::whereHas('variants')->with(['reviews', 'variants' => function($query) use ($order) {
if ($order == 'price') {
$query->orderBy('price');
}
}])->paginate(20);
If you want to sort product +/or variant you need to use join.
$query = Product::select([
'products.*',
'variants.price',
'variants.product_id'
])->join('variants', 'products.id', '=', 'variants.product_id');
if ($order == 'new') {
$query->orderBy('products.created_at', 'DESC');
} else if ($order == 'price') {
$query->orderBy('variants.price');
}
return $query->paginate(20);
If you want to sort product and variants, you don't need joins, because you won't have the related model loaded (like $product->variants), just all the fields of the variants table.
To sort models by related submodels, we can use Eloquent - Subquery Ordering.
To order the whole model by a related model, and NOT the related model itself, we can do it like this:
return Product::with('variants')->orderBy(
Variants::select('price')
// This can vary depending on the relationship
->whereColumn('variant_id', 'variants.id')
->orderBy('price')
->limit(1)
)->get();

Convert a many to many raw sql statement to eloquent query builder

I need to translate this working sql statement:
select model_names.name
FROM blog_posts
INNER JOIN model_names_relations
INNER JOIN model_names
ON blog_posts.id = model_names_relations.blog_post_id and model_names.id = model_names_relations.model_name_id
WHERE blog_posts.id = '12'
to laravel query builder. I'm NOT using the full orm, so I can't use the belongstomany feature. I'm restricted to the query builder.
I tried this:
$query = ( new DbSql )->db()->table( 'blog_posts' )
->join( 'model_names_relations', 'blog_post_id.id', '=', 'model_names_relations.blog_post_id' )
->join( 'model_names', 'model_names.id', '=', 'model_names_relations.model_name_id' )
->where( 'blog_posts.id', '12')
->select( 'model_names.name' )
->get();
var_dump( $query );
exit;
But it won't work I get:
protected 'message' => string 'SQLSTATE[42S22]: Column not found: 1054 Unknown column 'blog_post_id.id' in 'on clause' (SQL: select model_names.name from blog_posts inner join model_names_relations on blog_post_id.id = model_names_relations.blog_post_id inner join model_names on model_names.id = model_names_relations.model_name_id where blog_posts.id = 12)' (length=357)
private 'string' (Exception) => string '' (length=0)
What would be the correct conversion syntax ?
Here is Laravel query builder
$query =DB::table('blog_posts')
->join('model_names_relations', 'blog_posts.id', '=', 'model_names_relations.blog_post_id')
->join('model_names', 'model_names.id', '=', 'model_names_relations.model_name_id')
->where('blog_posts.id', '12')
->get();
However your error means there is no 'id' in blog_post_id table.

Laravel left join showing error on 'ON' multiple condition

When i tried using left join in laravel I am getting below error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column '$dat' in 'on clause' (SQL: select students.id, students.name, attendance_student.date from students left join attendance_student on students.id = attendance_student.student_id and attendance_student.date = $dat)
Basically I am trying to get attendance of all students on a particular date
My Code:
$dat = 2015-10-15;
$student = DB::table('students')
->leftJoin('attendance_student', function($join)
{
$join->on('students.id', '=', 'attendance_student.student_id');
$join->on('attendance_student.date', '=', $dat);
})
->select('students.id', 'students.name', 'attendance_student.date'
)
->get();
PLease help
Your issue: Variable scopes
Solution:
$dat = 2015-10-15;
$student = DB::table('students')
->leftJoin('attendance_student', function($join) use ($dat)
{
$join->on('students.id', '=', 'attendance_student.student_id');
$join->on('attendance_student.date', '=', $dat);
})
->select('students.id', 'students.name', 'attendance_student.date'
)
->get();
Explanation:
When accessing variables that were declared outside the scope of the lambda function (the function($join) one), make use of use statement to allow access to those variables inside the function.
Source: http://php.net/manual/en/functions.anonymous.php

Laravel QueryBuilder where clause with user info on other model

I have a Model ImageRequest that is related to my User model like this:
public function user()
{
return $this->belongsTo('App\User');
}
An my User model like this:
public function imageRequests()
{
return $this->hasMany('App\ImageRequest');
}
Now I use this package to build my filterable query to fetch all ImageRequests:
spatie/laravel-query-builder
this is what my query looks like:
$query = QueryBuilder::for(ImageRequest::class)
->with(['requestTypes'])
->allowedIncludes('requestTypes')
->orderByRaw("FIELD(status , 'new') desc")
->orderBy('functional_id', 'asc')
->allowedFilters(
'id',
'pv_number',
'created_at',
Filter::scope('starts_between'),
'location_of_facts',
'train_nr',
'status',
'result_of_search',
Filter::custom('type', RequestTypeFilter::class)
);
I need to add a where clause for the User model something like this:
->where('zone', Auth::user->zone);
But it says:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'zone' in 'where clause' (SQL: select count(*) as aggregate from image_requests where zone = a)
Please look into this code, Here I added a whereHas instead for where. so it will take only matching records to user table for desired zone.
hope it helps..
$query = QueryBuilder::for(ImageRequest::class)
->with(['requestTypes'])
->whereHas('user'=>function($q){
$q->where('zone', Auth::user->zone);
})
->allowedIncludes('requestTypes')
->orderByRaw("FIELD(status , 'new') desc")
->orderBy('functional_id', 'asc')
->allowedFilters(
'id',
'pv_number',
'created_at',
Filter::scope('starts_between'),
'location_of_facts',
'train_nr',
'status',
'result_of_search',
Filter::custom('type', RequestTypeFilter::class));
Please have try this, used direct join query.
$query = ImageRequest::selectRaw('column1,column2')
->join('user', function($join){
$join->on('ImageRequest.user_id','=','user.id');
})
->leftJoin('request_types', function($join){
$join->on('request_types.image_request_id','=','image_request.id')
})
->where('user.zone', Auth::user->zone)
->orderByRaw("FIELD(status , 'new') desc")
->orderBy('functional_id', 'asc')
->allowedFilters(
'id',
'pv_number',
'created_at',
Filter::scope('starts_between'),
'location_of_facts',
'train_nr',
'status',
'result_of_search',
Filter::custom('type', RequestTypeFilter::class)
);

Resources