PDO update challenges - php

So i built an application in mysql, and was having challenges updating records in the db. Everybody was more interested in telling me that i should just use PDO.
So rather than fight, I decided to start to learn PDO connection and query strings and the practices around using prep stmts.
Anyway in my practice and tutorials, I can pull and parse the information from my database with no challenges. but when it comes to updating or inserting a new record nothing is ever inserted and I can't find the reason why not.
originally I had a form post to the variables, but that didn't work
so i hardcoded the variables, but it still isn't working
i could use some help.... can anybody see what is wrong with this insert php script?
<?php
$user="111";
$pass="111";
$database="111";
$host="111";
$odb = new PDO("mysql:host=$host;dbname=$database", $user, $pass);
$event='Special Speaker';
$descript='We have special speakers comming on tuesday night';
$sp1='Speaker Mr.A';
$sp2='Speaker Mr.B';
$date='5-5-15';
$created = '5-5-15';
$id=7;
$stmt=$odb->Prepare("INSERT INTO events(ID,Event,Descript,Sp1,Sp2,Created,Date)
VALUES (:ID,:Event,:Descript,:Sp1,:Sp2,:Created,:Date");
$stmt->bindParam(':ID',$id);
$stmt->bindParam(':Event',$event);
$stmt->bindParam(':Descript',$descript);
$stmt->bindParam(':Sp1',$sp1);
$stmt->bindParam(':Sp2',$sp2);
$stmt->bindParam(':Created',$created);
$stmt->bindParam(':Date',$date);
$stmt->execute();
?>

You may have to specify that your ID is an int like so: $stmt->bindParam(':calories', $calories, PDO::PARAM_INT);
Your database may be preventing you from inserting IDs in that table if it's the Identity/Primary column and/or is auto-incrementing.
It'd be a good idea to enable PDO warnings or exceptions so that it can tell you what's wrong or what is failing. See here for more: http://php.net/manual/en/pdo.error-handling.php

Related

mysqli num_rows nested query

I'm updating a site from MySQL to MySQLi, using OOP.
For the most part things are going well, but this line is giving me divine trouble:
$pager_total = mysql_num_rows(mysql_query($MySQLctr,$MyDB));
I've tried
$pager_total = $MyDB->query($MySQLctr)->num_rows;
and
$pager_total = ($MyDB->query($MySQLctr))->num_rows;
and
$new_object = $MyDB->query($MySQLctr);
$pager_total = $new_object->num_rows;
but no avail.
Any thoughts?
OOP mysqli is very simple :) try this example
$DBH=new mysql('location of database','username','password','database');
$get=$DBH->prepare('SELECT COUNT(*) FROM table');//notice the count(*) in the query, it's not the same as mysql_num_row() but works in the same way
//prepare is also a more secure way of processing query, please look up the difference between prepare and query though.
//$DBH->prepare('SELECT * FROM table WHERE ID=2'); will not work.
$get->execute();//execute the above prepared statement
$get->bind_result($count);//get the result of the query, should be whatever COUNT(*) returns
$get->close();//don't forget to close your connection
The mysqli of mysql_num_row() is $query->num_rows().
I added a little bit extra to get you started with OOP mysqli :)
Notice though that I didn't use $get->num_rows() but COUNT(*) instead for a more simple example. Here is another method you may be more familiar with:
$counter=$DBH->query('SELECT * FROM table');
echo$counter->num_rows();
Also see here for more examples.
Thank you for your help everyone. It turns out that the db connection was being closed prematurely by one of the included files. I've noticed, during this project where I'm transitioning the code from procedural MySql to OOP MySQLi that the db closures didn't affect the functionality of the site before, but definitely do once OOP MySqli is in place. I'm curious why.

How do you escape ' on doctrine?

How do you escape ' on doctrine?
I made this code
$query = $em->createQuery(
"SELECT a FROM AcmeTopBundle:ArtData a WHERE
a.name = '". mysql_escape_string($name) ."'");
but when the $name is A'z
it returns error
[Doctrine\ORM\Query\QueryException]
SELECT a FROM AcmeTopBundle:ArtData a WHERE
a.name = 'A\'s'
I think I escaped by mysql_escape_string in case of using raw sql.
How can I avoid this error on doctrine?
The way I usually handle this is using parameters and querybuilder (https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/query-builder.html)...
$qb = $em->createQueryBuilder(
"SELECT a FROM AcmeTopBundle:ArtData a WHERE
a.name = :name")
->setParameter('name',$name);
$result = $qb->getQuery()->execute();
Well, even though there is accepted answer it is not for question as it is in title.
#Sven's answer comes close, but fails to mention:
Doctrine documentation
To escape user input in those scenarios use the Connection#quote() method.
And I have a gripe with "scenarios", or more with people pushing prepared statements like some holy grail. Well they are nice in theory, in practice at least in PHP they are quite shity, as they are unable to do simple stuff like IN (<list>) or multi inserts with VALUES (<bla bla>), (<more stuff>) which is a huge ass deal, as without it one ends up resorting to quite sub-optimal SQL (to put it lightly) quite commonly (well if one religiously insist on prepared statements at least).
This does not answer your question, but explains what's wrong with your code. It didn't fit into a comment.
You cannot and should not use mysql_escape_string()
It is the wrong escape function, the right one used to be mysql_real_escape_string(). Reading the documentation does not sound like it, but to properly escape, you have to know which character encoding is being used. In western encoding schemes like ASCII, ISO-8859-x or even UTF-8 it probably does not make a difference, but there are some exotic chinese encodings around which absolutely need to know whether that " byte belongs to another byte, or comes on it's own.
When using mysql_real_escape_string(), you need to have an already open DB connection created with mysql_connect(). If you don't, PHP tries to open a new connection with default user and password as defined in the php.ini file. This usually results in an error because without password the database won't let you do anything. And additionally, if you have success, then the encoding setting of this connection most likely is not the one used by Doctrine.
Using any of the mysql_* functions is wrong, because these are deprecated. The correct way would be to use mysqli_* functions.
Doctrine may use any of the three database connection methods: mysql, mysqli or PDO. You have to choose the one really being used if you want to manually call the correct escaping function. While the connection is already created. And somehow you need to grab that connection resource to allow the function you are calling to detect the used encoding.
So in the end there are plenty of reasons why it is wrong to just use any escaping that sound like it is doing the job.
The right way is to use the escaping of the database layer you are using. If you use Doctrine, the use it for escaping. Or better, avoid escaping, use prepared statements or the query builder and let Doctrine deal with the rest.
Based on https://stackoverflow.com/a/13377430/829533
you can use prepared statements http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/data-retrieval-and-manipulation.html#using-prepared-statements
From the documentation:
$date = new \DateTime("2011-03-05 14:00:21");
$stmt = $conn->prepare("SELECT * FROM articles WHERE publish_date > ?");
$stmt->bindValue(1, $date, "datetime");
$stmt->execute();
This will show how to insert the data into the database where you would normally have to use real_escape_string.
Doctrine and Symfony 3 using prepared not QueryBuilder:
// get the post value
$value = $request->request->get('value');
$sql = "INSERT INTO `table_name`
(`column_name1`,`column_name2`)
VALUES
('Static Data',?)
";
$em = $this->getDoctrine()->getManager();
$result = $em->getConnection()->prepare($sql);
$result->bindValue(1, $value);
$result->execute();
Now for a bonus to get a success/fail if you are using auto increment records:
$id = $em->getConnection()->lastInsertId();
if $id has a value then it executed the insert. If it does not the insert failed.

pdo insert without variables

I'm trying to insert a new record into a table that contains only an auto number primary key using the following code,
$pdo_conn = new PDO("mysql:host=$dbhost;dbname=$dbname", $dbuser, $dbpass);
$sqla = "insert into tbl_gen (gen_sk) values (null)";
$qa = $pdo_conn->prepare($sqla);
$qa->execute();
is this the right way to go about it?
running the sql command in mysql workbench does the job, I'm just feeling like maybe I'm using pdo the wrong way.
Prepared statements are intended to be re-used. If you're just doing a simple one-shot query, then use $pdo->exec() instead. This avoids the overhead of preparing the statement, and just simply "does it".
But regardless, there's nothing "wrong" with how you're going about it.

Ckeditor only submits part of the content

I'm using ajax to gather the ckeditor data to be submitted. The problem is only the content before the first apostrophe is being submitted to the database. What could I be doing wrong?
Edit:
$date = strtotime($formData['date']);
$article=mysql_real_escape_string($formData['article'],$DBconnect);
$DBconnect=mysql_connect($dbVals['host'],$dbVals['user'],$dbVals['pass']);
mysql_select_db($dbVals['db'], $DBconnect);
$SQLstring="INSERT INTO PressRelease (ip, tym, title, date, article) VALUES('${_SERVER['REMOTE_ADDR']}', ".time().",'${formData['title']}', '$date', '$article')";
I'm fairly new at this so if there is anything else you need to see in order to help let me know.
It sounds like you aren't escaping the text data before you insert it into the database. Use this function on the data before you pass it into your SQL query:
http://www.php.net/manual/en/function.mysql-real-escape-string.php
Edit: sorry, that's assuming you are using MySQL.
A different, more complicated, and arguably superior method to the one suggested by Mark, is using Parameterized Statements.
To borrow an example from Wikipedia:
<?php
$db = new mysqli("localhost", "user", "pass", "database");
$stmt = $db -> prepare("SELECT priv FROM testUsers WHERE username=? AND password=?");
$stmt -> bind_param("ss", $user, $pass);
$stmt -> execute();
?>
It leaves the escaping up to the MySQL driver, severely reducing the chance of SQL Injection and things like accidental double-escaping.
Note that this is not possible using the old MySQL functions. You need the Improved MySQLI functions/object, or something like PDO.
If I understand correctly the following is the case:
You've got a textarea that's "taken over" by CKeditor
You're reading the content of that textarea with Javascript
You're sending the gathered content to the server with AJAX
If you alert() the content that Javascript gets from the textarea, you can see whether step 2 succeeds. If not, please post your Javascript.
If step 2 is correct, then maybe there's a problem server side, dump your db query to look at that.
Update:
Make sure you when you're developing that you turn on all errors and notices. And if you're doing stuff which you can't "see" easily, like AJAX, make sure to keep an eye on your server's error log.
In your code example line 2 you use $DBconnect, and then in line 4 you define what that is. As you can see in the PHP.net entry for mysql_real_escape_string if the function cannot find a connection to the database the function generates an error and returns FALSE. The FALSE is put into your database and that's what goes into your database.
My advice to you is: try harder at debugging. Test all your assumptions, test the value of variables at every step, check if they have the value you expect them to have. Use var_dump(), print_r(), echo and die(). Or if you want something more advanced use a debugger (I don't).

mysqli->prepare function returns null

This is a terrible question because I don't have a simple way to reproduce it. However, I'm using the Zend Framework to connect to my MySQL database on OS X. Sometimes a call to the prepare function on a mysqli object returns null. The stated return values for the prepare function are false or a statement object.
I can't figure out where else to look for info on why the prepare statement is failing. Is there any way to get visibility into the prepare process to see why it is failing? All of my problems are coming up while a transaction is open.
Sorry for the lack of specifics, but I really can't nail down why this is happening.
Just to correct ToughPal, you should be using:
mysqli_query($db, "INSERT INTO table (variable1, variable2) VALUES (hello, mynameis);
Remember that you need to have the db connection defined and stated in the query first, before your actual SQL.
Remember to enclose the table name, column names and value data in backtick escapes.
Example prepared statement
$result = $db->query( 'INSERT INTO server (key, value) VALUES (:key, :value)',
array('key' => $foo, 'value' => $bar)
Can you let us know your DB query?
Try and execute your DB query with test data and see if the query works fine to start with. If the query is ok then we can look why the code fails.
Well I managed to find the issue over the weekend but was really only able to fix the symptoms and not the cause.
I didn't include any SQL in the original issue because the problem was happening randomly, the same code would sometimes work and sometimes not. The issue looks like it was a memory pointer problem. Whenever I had a problem Zend Debugger told me that I had a mysqli object. I believe this because otherwise I would've gotten an error when trying to run the prepare function on it. I have a singleton object that acts as a container for my mysqli connection but whenever the prepare function failed, === showed that the mysqli being used was not the same as the mysqli connection in my singleton object.
In the end, Zend Framework's only issue is that it doesn't fail if the the prepare function returns null. If you are seeing this problem use === to verify that the connection is actually the same as the one that you've previously initiated.
if you're doing something like this
$mysqli = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
$query = "...";
$mysqli->prepare($query);
then you can inspect mysqli::$error next to see useful errors about why prepare() failed
print_r($mysqli->error);

Categories