Applying string function in column Laravel 5.4 - php

I'm using the latest Laravel 5.4
I am trying to make a simple query to search users by name. The query written for MySQL looks like this:
SELECT *
FROM users
WHERE upper(name) LIKE '%FOO%';
I'm trying to make it work with Eloquent. Things I've tried but failed:
User::where('upper(name)', 'LIKE', '%FOO%')->get()
DB::table('users')->where('upper(name)', 'LIKE', '%FOO%')->get()
Both fail with the following error:
Illuminate\Database\QueryException with message 'SQLSTATE[42S22]: Column not found: 1054 Unknown column 'upper(name)' in 'where clause' (SQL: select * from users where upper(name) LIKE %FOO%)'
The query seems to fail because Eloquent wraps the upper(email) statement with backticks (" ` ", " ` "). Is there a way to go around this issue or do I have to use a particular eloquent function to get convert a column to uppercase, lowercase, e.t.c?

Use DB::raw()
User::where(DB::raw('upper(name)'), 'LIKE', '%FOO%')->get()
It would generate query like this
"select * from `users` where upper(name) LIKE ?"

You can use whereRaw() in laravel to achieve this :
User::whereRaw("upper(name) LIKE '%FOO%'")
->get();

Related

laravel select query create dynamic column name not working

I am trying Laravel join query to select the column dynamically but below line is returning error.
\DB::raw('table3.ElrA'.($effectiveYear'.-YEAR(table1.eff_date).'))
table3 having columns like this ElrA1, ElrA2 .....
common part is "ElrA" I am just making trailing number dynamically to create whole column name but it gives me err like "ElrA202-YEAR(table3.eff_date) is not a column". can you please suggest any solutions.
$query = DB::table('table1')
->join('table2', function($join) {
$join->on('table2.policy_period_id', '=', 'table1.id');
$join->where('status','1');
})
->leftjoin('table3', function($join) use($effective_date)
{
$join->on('table3.class_code', '=', 'table2.code');
$join->where('table3.date', '=', DB::raw("(select max(`date`) from table3 where date <= '".$effective_date."' limit 1)"));
})
->select(\DB::raw('table3.ElrA'.($effectiveYear'.-YEAR(table1.eff_date).')))
->where('table1.mod_id',$id);
Thanks
When you look at the error code, it says clearly that laravel try to find column ElrA202-YEAR(table3.eff_date)
What happen is because you make mistake in this part
'table3.ElrA'.($effectiveYear'.-YEAR(table1.eff_date).'
the exact part is in this one
'.-YEAR(table1.eff_date).'
because you use '' and it will parsed as string and not the variable that you want
I don't know why you will use dynamic column, but it is really not a good idea, because as the documentation says, it's very vulnerable with sql injection attack because there is no parameter binding in dynamic column. But if you know what you are doing then it's okay

Laravel query builder two tables in left join

I have the following query which I'm trying to convert into Laravel's query builder so I can take advantage of automatic escaping etc.
SELECT subjects.name, report_comments.comment
FROM subjects
LEFT JOIN (report_comments, library_comments) ON subjects.id = library_comments.subject_id
AND report_comments.library_comment_id = library_comments.id
AND report_comments.report_id = 1
Effectively what the query says is 'get the names of all the subjects, and if they have a matching report_comment (via the intermediate library_comments table), return that along with the subject' (a subject has either one or zero report_comments for the given criteria). The query works if I run it directly in MySQL and returns the results I'd expect. The report_comment.report_id = 1 is hard-coded at the moment but will eventually be a placeholder so that any report_id can be passed in.
So far I've managed to get:
DB::table('subjects')->select(['subjects.name', 'report_comments.comment'])->leftJoin('report_comments', function ($join) {
$join->on('subjects.id', '=', 'library_comments.subject_id')
->on('report_comments.library_comment_id', '=', 'library_comments.id')
->on('report_comments.report_id', '=', '1');
})
If I add toSql the result is:
select `subjects`.`name`, `report_comments`.`comment` from `subjects` left join `report_comments` on `subjects`.`id` = `library_comments`.`subject_id` and `report_comments`.`library_comment_id` = `library_comments`.`id` and `report_comments`.`report_id` = `1`
This is almost what I want, except it fails because the library_comments table is not mentioned at all:
Illuminate/Database/QueryException with message 'SQLSTATE[42S22]: Column not found: 1054 Unknown column 'library_comments.subject_id' in 'on clause' (SQL: select `subjects`.`name`, `report_comments`.`comment` from `subjects` left join `report_comments` on `subjects`.`id` = `library_comments`.`subject_id` and `report_comments`.`library_comment_id` = `library_comments`.`id` and `report_comments`.`report_id` = `1`)'
What I need to do is tell the leftJoin function about report_comments and library_comments, but there doesn't seem to be any way to do this. I tried:
leftJoin(['report_comments', 'library_comments'], function($join)
on a guess that Laravel might convert an array of table names into (report_comments, library_comments), but that didn't work and gave me the following warning:
PHP Notice: Array to string conversion in /home/paul/sites/report-assistant/vendor/laravel/framework/src/Illuminate/Database/Grammar.php on line 39
Is there a way to pass multiple tables into leftJoin, or do I need to completely rewrite the query in order to work with Laravel's query builder?
I'm using laravel/framework version 5.8.21 and all my dependencies are up to date (composer update && npm update).
Use BD::raw
write query like this and It will work
DB::table('subjects')->select(['subjects.name, report_comments.comment'])->leftJoin(DB::raw('(report_comments, library_comments)'), function ($join) {
$join->on('subjects.id', '=', 'library_comments.subject_id')
->on('report_comments.library_comment_id', '=', 'library_comments.id')
->on('report_comments.report_id', '=', '1');
})
Not sure if this will work but i assume it will be somthing along these lines, hopefully you get something out of it.
Basically added a check to see if the relationship exists if it does then join it.
Subject::select('subjects.name, report_comments.comment')
->leftJoin('library_comments', 'subjects.id, '=', library_comments.subject_id')
->leftJoin('report_comments', function($join){
if(report->library->relationship){
$join->on('report_comments.library_comment_id', '=', 'library_comments.id')
->where('report_comments.report_id', '=', '1');
}
})
After a bit of tinkering, I managed to find the answer in two parts:
First, I had to tweak this part of the join:
on('report_comments.report_id', '=', '1')
and replace it with:
where('report_comments.report_id', '=', '1')
If I didn't do this, Laravel would quote 1 with backticks, causing MySQL to interpret it as a column name.
The other change was to use DB::raw, which I was trying to avoid but I don't think it's too bad in this situation because I'm passing a hardcoded string rather than user input (or anything influenced by user input). The leftJoin now looks like:
leftJoin(DB::raw('(report_comments, library_comments)')

Laravel: Left join sql error

I have written a sql query using Laravel, but I am not understanding, why the error is creating! The codes are given below,
The join operation:
MeetingRoom::select('mr_id')
->leftJoin('meetingroomhistory',function($join)
{
$join->on('country','=',Session::get('country'));
$join->on('location','=',Session::get('location'));
$join->on('building','=',Session::get('building'));
$join->on('floor','=',Session::get('floor'));
$join->on('name_of_mr','=',Session::get('room'));
})
->where('meetingroom.id','=','meetingroomhistory.mr_id')
->get();
The error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'Bangladesh' in
'on clause' (SQL: select `mr_id` from `meetingroom` left join
`meetingroomhistory` on `country` = `Bangladesh` and `location` =
`Dhaka` and `building` = `Uttara` and `floor` = `3` and `name_of_mr` =
`1` where `meetingroom`.`id` = meetingroomhistory.mr_id)
But if I run the query manually to change this syntax `Bangladesh` to "Bangladesh" using phpmyadmin so it runs well and show me the result. Please someone let me know, how can I fix it?
I think you've confused the where part and the join part.
$join->on($x, $y) statements are for connecting your tables together. Both $x and $y should be names of columns in your tables - that is why Laravel is adding backticks to them.
$where() statements are for comparing with values that you supply. Your Session::get() calls indicate that's what you're doing.
Here's a suggested rewrite, but it may need to be tweaked to suit your exact needs.
MeetingRoom::select('mr_id')
->leftJoin('meetingroomhistory', 'meetingroom.id', '=', 'meetingroomhistory.mr_id')
->$where('meetingroom.country','=',Session::get('country'))
->$where('meetingroom.location','=',Session::get('location'))
->$where('meetingroom.building','=',Session::get('building'))
->$where('meetingroom.floor','=',Session::get('floor'))
->$where('meetingroom.name_of_mr','=',Session::get('room'))
->get();
I assumed the country, location, etc. columns are part of the meetingroom table, if not you can just change them to $where('meetingroomhistory.country', ...) and so on instead.
Finally, I'm not sure why you're selecting only one value, but of course, that's up to you. If you need only a single cell, you can use pluck(), and if you need a lot of single results you could do lists().
I think you should try this.
MeetingRoom::select('mr_id')
->join('meetingroomhistory', function($join)
{
$join->on('meetingroom.id','=','meetingroomhistory.mr_id')
->where('meetingroomhistory.country','=',Session::get('country'));
->where('meetingroomhistory.location','=',Session::get('location'));
->where('meetingroomhistory.building','=',Session::get('building'));
->where('meetingroomhistory.floor','=',Session::get('floor'));
->where('meetingroomhistory.name_of_mr','=',Session::get('room'));
})
->get();

Having trouble with sql LIKE

I have the following query:
SELECT * FROM `alerts` WHERE `title` LIKE `%template%`
This should return at least 3 results with titles that includes the word 'template' but I'm getting the following error: -
1054 - Unknown column '%template%' in 'where clause'
As far as I can tell its syntactically correct and calling the correct column names. What am I missing?
Use single quotes for the %template%:
SELECT * FROM `alerts` WHERE `title` LIKE '%template%'

Order clause with 'like' clause in Zend DB

Query:
select * from table_name ORDER BY name like 'C%' DESC;
This query work fine in MySql, but i am unable build the query using Zend DB.
I am getting error while executing.
PHP DB code:
$result = $this->getDefaultAdapter()
->select()
->from($this->_name,array('*'))
->order("name like 'C%' DESC")
->query()
->fetchAll();
Error:
Column not found: 1054 Unknown column 'name like 'C%'' in 'order clause'
Thanks in advance
Zend_Db_Select tries to delimit strings as column names, but it skips doing that if you pass an object of type Zend_Db_Expr instead of a string:
->order(new Zend_Db_Expr("name like 'C%' DESC"))->
There's also an undocumented shortcut: the column-delimiting function assumes that any string containing parentheses is very likely to be an expression instead of just a column name. So the following would work too:
->order( "(name like 'C%' DESC)" )->
I'm not familiar with zend but Try to rewrite your sql query in Zend like this
select *, (`name` like 'C%') as theFiled from table_name by theFiled desc;
Though i'm not so sure I guess that the Zend Code must be something like this,
$result = $this->getDefaultAdapter() ->select()
->from($this->_name,array('*', "theFiled" => "name like 'C%'") ->order("theFiled DESC")
->query() ->fetchAll();

Categories