CodeIgniter Query Escaping Quotes - php

I have the following simple query which works perfectly in MySQL;
select * from client_contact
where date_format(client_next_contact_on, '%Y-%m-%d') = '2018-07-25'
I've then added this in my codeigniter query but the error I get is;
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''2018-07-25'' at line 3
SELECT * FROM (client_contact) WHERE
dateformat(client_next_contact_on, '%Y-%m-%d') '2018-07-25'
By the looks of the above, it's missing the = in the query.
Here's my query in codeigniter;
$today = new DateTime();
$today_formatted = $today->format('Y-m-d');
$this->db->where('dateformat(client_next_contact_on, \'%Y-%m-%d\')', $today_formatted);
$return = $this->db->get('client_contact')->row_array();
If you're wondering why I need to use date_format, it's because it's stored as a date time in my database for other purposes. For this purpose, I need a list of clients that I need to contact today, regardless of the time.

Just include the equals in the where statement, and rename dateformat as it isn't a function in MySQL. Use DATE_FORMAT:
$this->db->where('DATE_FORMAT(client_next_contact_on, \'%Y-%m-%d\') =', $today_formatted);
Now, onto the guts of why code igniter chose not to include an equals sign, which (by the documentation, it should have). On this line of the codeigniter source, it calls this function to determine if it contains an operator. Apparently because you put a space after the , it believed you included an operator, so a simple manual adjustment to add this in is fine.
protected function _has_operator($str)
{
return (bool) preg_match('/(<|>|!|=|\sIS NULL|\sIS NOT NULL|\sEXISTS|\sBETWEEN|\sLIKE|\sIN\s*\(|\s)/i', trim($str));
}
You can see where the regex matched here: https://regex101.com/r/BTuZxj/1

Related

PHP/MySQL/PDO search on date from database

Trying to make a little Search feature for a user, so he can type in a date on a webpage made with HTML/PHP, and see which people in the db have registered as member on or after (a date). My user inputs the date in format 2015-10-01. This gets sent to a PHP page with a jqxGrid on it, populated with member details of members conforming to my query on the MySQL database (using PDO).
The query uses the operator >= on a string passed as (for example) "2015-10-01" in the WHERE clause, so I am using STR_TO_DATE to make the comparison work:
WHERE `lastUpdated` >= STR_TO_DATE( ? , '%Y-%m-%d');
With PDO, the ? later gets bound to the date (which was passed in as a string).
The db column for registration date is in DATETIME format, and in the db values look like: "2015-10-12 17:12:52".
My query returns an empty array every time, - and this after many hours of trying every conceivable permutation of date format, both in the MySQL statement and on the page that prepares the data for populating the grid.
Can someone show me what's wrong here?
Thanks!!
SP
Make it
WHERE `lastUpdated` > ?
and check your data and stuff.
Basically, you should never touch PDO until you get raw SQL to work.
okay, so here is the PDO version that works - passing in ? instead of the date:
function getJSONAllMembersByDate($PDOdbObject, $regDate)
{
try
{
$membersByDateSQL = "SELECT `id`, `name_first`, `name_last`, `organization`,`email`, `phone`,`source`,`comments`,`language_id`, `lastUpdated` FROM `member` WHERE lastUpdated>=?";//'$regDate'
$get=$PDOdbObject->prepare($membersByDateSQL);
$get->execute(array($regDate));
$rows = $get->fetchAll(PDO::FETCH_ASSOC);
$json=json_encode($rows);
return $json;
}
The fact that it works proves there were other errors in the file containing the jqxwidget (the version before I posted here). I certainly tried about a million different things to get this working.
I don't know if this counts as an answer, but at least it WORKS! There are so many variables in this problem - json, jqxgrid, pdo ... not forgetting that there are several ways to use PDO. I probably had several errors in different places.
(#apokryfos, the STR_TO_DATE was indeed unnecessary.)
In the end, this is what works:
In the PHP page containing the jqxGrid, the url sent to the server is:
url: 'my-json-responses.php?fct=getJSONAllMembersByDate&regDate=<?php echo $fromDate ?>'
This $fromDate comes from the $_POST when the user typed in a date (in the format 2015-10-01) on the input page. When the PHP page containing the jqxGrid loads, it does
$fromDate = $_POST['regDate'];
The url "transits" through the file my-json-reponses.php, which contains many functions. It finds the right one:
if ($_GET['fct'] == 'getJSONAllMembersByDate')
{
$result = getJSONAllMembersByDate($connectionObject, $_GET['regDate']);
echo $result;
}
The $result is called on the file that contains all my PDO database requests, including:
function getJSONAllMembersByDate($PDOdbObject, $regDate) { try
{
$membersByDateSQL = "SELECT `id`, `name_first`, `name_last`, `organization`,`email`, `phone`,`source`,`comments`,`language_id`, `lastUpdated` FROM `member` WHERE lastUpdated>='$regDate'";
$get=$PDOdbObject->query($membersByDateSQL);
$rows = $get->fetchAll(PDO::FETCH_ASSOC);
$json=json_encode($rows);
return $json;
}
catch (PDOException $e)
{
echo "There was a problem getting all members with this search query.";
echo $e->getMessage();
}}
Note that I couldn't make the version using "?" in the query work at all, hence passing in the variable $regDate directly, with single quotes around the variable just to make life interesting.
This returns a nice list of all my users as of 2015-10-01 - but is presumably still open to MySQL injection attacks ...
But after this marathon of debugging I am happy enough for now. (All improvements welcomed, naturally!)
SP

Codeigniter $this->db->select() not work with Round(Max()) or FORMAT(MAX())

I write following code
$this->db->select('SUM(qty) as total_qty,(FORMAT(SUM(amount),2)) as total_amount');
$this->db->where('Invoice_Rec_No',$Invoice_Rec_No);
$result=$this->db->get($this->invoice_products_tbl);
$total_data=$result->row();
but getting error
Error Number: 1064
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FROM (tbl_invoice_products) WHERE Invoice_Rec_No = 7' at line 2
SELECT SUM(qty) as total_qty, (FORMAT(SUM(amount), 2)) as total_amount FROM (tbl_invoice_products) WHERE Invoice_Rec_No = 7
Filename: C:\wamp\www\admin_followme247_master\system\database\DB_driver.php
I want to execute this query with codeigniter ActiveRecord.
User second parameter FALSE in db select method
$this->db->select('SUM(qty) as total_qty,
(FORMAT(SUM(amount),2)) as total_amount', FALSE);
CI db class is automatic add (apostrophe) when manipulate sql query, if you pass send parameterFALSEinselect` method then it is keep same as input.
You can format your code like this
$select = array(
'SUM(qty) as total_qty',
'(FORMAT(SUM(amount),2)) as total_amount'
);
$this->db->select($select);
$this->db->where('Invoice_Rec_No',$Invoice_Rec_No);
$result=$this->db->get($this->invoice_products_tbl);
$total_data=$result->row();
For simple column selection it is fine to use string but for complex selection like this one you can either use an array or select each column separately

combine columns into one column mysql

I would like to combine two columns in one column as Fullname, and for that I have written the following code:
$this->db->select('CONCAT(first_name," ",last_name) AS FullName');
$this->db->from('customer');
$this->db->where('user_id',1);
$query = $this->db->get();
return $query->result_array();
The resulting query would be:
SELECT CONCAT(first_name," ",last_name) AS FullName
FROM customer
WHERE user_id = 1
but when i execute the above code it gives me:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FROM (customer) WHERE user_id = '1' at line 2
I have also tried with concat_ws group_concat but not able to get it work. Can anyone see what I'm doing wrong?
By default, CI tries to escape what you pass to db->select() (in case you were passing in user-generated values). You can disable this feature by passing false as a second argument.
$this->db->select('CONCAT(first_name," ",last_name) AS FullName', false);
I have been through this before with CI, in my case CI was wrongly creating the query, for example putting simgle quotes where they shouldn't be.
My advice create the query yourself and run it, you could be surprise :P

Filtering by date range in SQL query

I am unable to get the following code to work:
// dd/mm/yyyy for dates in SQL queries
$todayforw = date('d/m/Y');
$aweekago = date('d/m/Y', time() - 604800);
$week_e_check = mysql_query("SELECT * FROM earningslog WHERE user_id = '".$info['id']."' WHERE day >='".$aweekago."' AND day <'".$todayforw."'");
while ($week_e_info = mysql_fetch_array($week_e_check)) {
$week_e = $week_e + $week_e_info['user_earnings_amnt'];
}
The query returns zero rows, however, it should be returning data that matches the criteria.
Check your date format:
Should be:
YYYY-mm-dd HH:mm:ss
E.G.
2012-01-01 00:00:00 (January 1, 2012 at midnight local time)
Other date formats MAY work, but the best way to go about it is to use the same format that MySQL uses when they display the date, that's the only way I know that works every time.
http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html
Also your syntax is incorrect, you have two wheres, you should use AND.
Take a closer look at your query:
SELECT * FROM earningslog WHERE user_id = '".$info['id']."' WHERE day >='".$aweekago."' AND day <'".$todayforw."'"
Your Where clause appears twice.
Two things to think about - when you are selecting data, try and stay away from select * - you may get unexpected results of the table is ever modified.
Second, try and create the query as a parameterized query, instead of injecting the parameters directly into the where clause. By directly injecting your criteria the way you have, you are opening yourself up to a SQL injection attack.
By turning it into a parameterized query, you get the side benefit of being able to debug the queries directly against the database, reducing the amount of effort needed to copy it from a query tool into your code.
Your issue appears to be with your query syntax. You are stating WHERE twice, whereas you should only state it once and then use the AND or OR operators for further criteria. I would also suggest that you either move your statement into a variable or use die() to assist with debugging.
$week_e_check = mysql_query("SELECT * FROM earningslog WHERE user_id = '".$info['id']."' AND day >='".$aweekago."' AND day <'".$todayforw."'") or die(mysql_error());
In addition, you should not be using the mysql extension as use of this extension is discouraged. Instead, use the MySQLi or PDO_MySQL extension. Using one of these alternative extensions will help serve as the first step in preventing SQL injection. I would also suggest that you avoid using * and specify the column names to be returned instead.
Using PDO:
<?php
/* Execute a prepared statement by passing an array of values */
$sth = $dbh->prepare('SELECT * FROM earningslog WHERE user_id = ? AND day >= ? AND day < ?');
$sth->execute(array($info['id'], $aweekago, $todayforw));
$results = $sth->fetchAll();
?>
Try change the format of your strings from from d/m/Y to Y-m-d.
MySQL might be expecting it year first. In which case it could be doing the wrong thing with d/m/Y.
Also don't use the WHERE clause twice. Instead, combine conditions using AND, eg:
WHERE user_id = '".$info['id']."'
AND day >='".$aweekago."'
AND day <'".$todayforw."'
By the way, you can also try saying WHERE day BETWEEN ".$aweekago." AND ".$todayforw.", which might be easier syntax to read (as long as you change $todayforw to be the day before).

Magento: Filtering a getCollection is not working

My getCollection code is providing the wrong query string (i think).
I have a table called banner which I can load all records from easy enough. When I try to filter it I'm getting errors.
Here is the code:
$banner = Mage::getModel('banner/banner')->getCollection()->addFieldToFilter('group', array('eq'=>'search_group'));
The page crashes and I get this error:
1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'group = 'search_group')' at line 1";i:1;s
As you can see it seems like the code is messing up the quotes after group.
'group = 'search_group')'
Can anyone advice on how to fix this?
Thanks,
Billy
group is an SQL keyword. If group is also an attribute name you'll need to escape it somehow. Try using backticks (the typically unused key below Esc).
$banner = Mage::getModel('banner/banner')
->getCollection()
->addFieldToFilter('`group`', 'search_group');
You're misinterpreting the error text.
to use near 'group = 'search_group')'
The outer quotes are the error messages way of blocking something off as code. This probably would have been clearer
to use near [group = 'search_group')]
It's always best to look at the select your collection is using (assuming a a non-eav collection here, given your Module Creator style class alias) and try running in directly in your MySQL client (PHPMyAdmin, Command Line app, Query analyzer, Sequel Pro, etc.)
header('Content-Type: text/plain');
echo (string) $widget->getSelect();
echo "\n";
var_dump ( (string) $widget->getSelect());
Mage::Log((string) $widget->getSelect());
exit;
Seeing the entire query in context usually makes spotting an error easier.
One way will be:-
Write the following function in your collection class:-
public function setGroupBy($group)
{
$this->getSelect()->group($group);
return $this;
}
Then you can use it like:-
$banner = Mage::getModel('banner/banner')->getCollection()->setGroupBy('search_group');
Hope this helps.

Categories