Insert Blobs in MySql databases with php - php

I am trying to store an image in the DataBase, for some reason it doesn't seem to work. Here's the structure of my table.
mysql> describe ImageStore;
+---------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+----------+------+-----+---------+-------+
| ImageId | int(11) | NO | PRI | NULL | |
| Image | longblob | NO | | NULL | |
+---------+----------+------+-----+---------+-------+
2 rows in set (0.01 sec)
And here is my query which inserts the image or at least thats what it should:
//Store the binary image into the database
$tmp_img = $this->image['tmp_name'];
$sql = "INSERT INTO ImageStore(ImageId,Image)
VALUES('$this->image_id','file_get_contents($tmp_image)')";
mysql_query($sql);
If I print the value of file_get_contents($tmp_image), then there is a tons of data on the screen. But this value doesn't get stored in the database and that is the issue that I'm facing.

Problem
$sql = "INSERT INTO ImageStore(ImageId,Image)
VALUES('$this->image_id','file_get_contents($tmp_image)')";
This creates a string in PHP named $sql. Forget about MySQL for a minute, because you're not executing any query yet. You're just building a string.
The magic of PHP means that you can write a variable name — say, $this->image_id — inside the double quotes and the variable still gets magically expanded.
This functionality, known as "variable interpolation", does not occur for function calls. So, all you're doing here is writing the string "file_get_contents($tmp_image)" into the database.
Solution (1)
So, to concatenate the result of calling file_get_contents($tmp_image), you have to jump out of the string and do things explicitly:
$sql = "INSERT INTO ImageStore(ImageId,Image)
VALUES('$this->image_id','" . file_get_contents($tmp_image) . "')";
(You can see even just from the syntax highlighting how this has worked.)
Solution (2)
Now the problem you have is that if the binary data contains any ', your query is not valid. So you should run it through mysql_escape_string to sanitize it for the query operation:
$sql = "INSERT INTO ImageStore(ImageId,Image)
VALUES('$this->image_id','" . mysql_escape_string(file_get_contents($tmp_image)) . "')";
Solution (3)
Now you have a really big string, and your database is getting bulky.
Prefer not storing images in databases, where you can help it.

To expand on Tomalak's comment, you can't run a function inside of quotes.
Try:
$sql = "INSERT INTO ImageStore(ImageId,Image)
VALUES('{$this->image_id}','".file_get_contents($tmp_image)."')";

try this:
$tmp_img = $this->image['tmp_name'];
$sql = "INSERT INTO ImageStore(ImageId,Image)
VALUES('$this->image_id','" . addslashes(file_get_contents($tmp_image)) . "')";
mysql_query($sql);

As mentioned you are just saving the string "file_get_contents($tmp_image)" into the db
but you need to run the function file_get_contents instead
dont forget to hash the image using a hashing algorithm such as base64_encode before saving it to the db.

Related

Use like with PDO on JSON-String

Actualy I know how to use LIKE statement with PDO
Now I have a DB-Table called e.g. foobar
foobar contains a JSON-String like:
{"firstname":"foo","email":"aaa#aaa.aa","lastname":"bar"}
Now before I call my INSERT on the table I want to check if the Email is already in use.
$pdo->query("SELECT * FROM myTable WHERE foobar LIKE ?", array('%' . $email . '%'));
as you can see, I pass the email into the pdo query.
Notice ->query is my custom function that handles some stuff. In this case its not important to know what happens.
The problem I have is:
If the entry like above exists then its not possible anymore to add an email thats like:
aa#aaa.aa
^^....only two A's
So I thought I can simply change
array('%' . $email . '%')
to
array('%"' . $email . '"%')
but this doesnt work. Is there a way I can check the whole string part ?
{"firstname":"foo","email":"aaa#aaa.aa","lastname":"bar"}
If you can't break the JSON fields into their own columns, then I would suggest a JSON column type. It's native to MySQL, super fast for JSON of this size, and no more difficult to use than something like jq on the command line.
If that's not an option, I would use a REGEXP:
mysql> select * from foobar;
+-----------------------------------------------------------+
| json |
+-----------------------------------------------------------+
| {"firstname":"foo","email":"aaa#aaa.aa","lastname":"bar"} |
| {"firstname":"FOO","email":"aa#aaa.aa","lastname":"BAR"} |
+-----------------------------------------------------------+
mysql> select * from foobar where json regexp '"email":"aa#aaa.aa"';
+----------------------------------------------------------+
| json |
+----------------------------------------------------------+
| {"firstname":"FOO","email":"aa#aaa.aa","lastname":"BAR"} |
+----------------------------------------------------------+
1 row in set (0.00 sec)
This is serviceable, but hardly bullet-proof and, to borrow an excellent turn of phrase, will murder performance on anything but trivial row sets.

MySQL and PHP, is there something wrong with my syntax?

Currently, my query (in my PHP script) is
mysql_query('INSERT INTO julian.guestbook (name, message, email, date) VALUES ("Julian Davis", ".'$newmsg.'", ".'$newmail'.", NOW());');
and it returns an error. A moment ago (before I jumped through that hoop with the variables) (and yes! I made sure to sanitize them!), it returns a broken page. Even with error reporting on, it won't report an error. If you just pass the name of the variables, it will submit
mysql> SELECT * FROM julian.guestbook;
+--------------+---------+----------+---------------------+
| name | message | email | date |
+--------------+---------+----------+---------------------+
| Julian Davis | $newmsg | $newmail | 2015-09-18 17:53:50 |
+--------------+---------+----------+---------------------+
but I want my (sanitized) data from my HTML form earlier in these boxes. I can't seem to get PHP to pass these strings along without messing something up in MySQL and not telling me anything it's doing.
The . that you used for concatenating needs to be outside the string.
mysql_query('INSERT INTO julian.guestbook (name, message, email, date) VALUES ("Julian Davis", "' . $newmsg . '", "' . $newmail . '", NOW());');

PHP & MySQL: Select account from database which hasn't been refreshed for more than 2 minutes

I have something like this in my database:
ID | ACCOUNT | PASSWORD | LAST_REFRESH
1 | acc1 | pass1 | 1386506130
And in my PHP script I have this:
$allowed_time = time() - 121;
$query = mysql_query('SELECT account FROM accounts WHERE last_refresh >= '.$allowed_time.'');
But if I try this query, nothing will be returned, even if $allowed_time is bigger than last_refresh in the database.
Try:
$query = mysql_query("SELECT account FROM accounts WHERE last_refresh >= $allowed_time");
Using double quotes for your query will allow you to use variables without concatenating them. Also, you're trying to compare a number and originally you were wrapping the variable in sinle quotes causing mysql to read it as a string rather than a number.
Hope this helps! :)

how to trace duplicate data

I would like to ask something here.
now I make form that insert data into table.
this table kemaskini that already have
+------+----------+----------+
| no | Item | kuantiti |
+------+----------+----------+
| 1 | Speaker | 10 |
+------+----------+----------+
| 2 | Laptop | 10 |
+------+----------+----------+
| 3 | Mouse | 10 |
+------+----------+----------+
when I type "Speaker" in form then I submit it.
it trace and say try again. it because already have.
coding that I write here. it only trace row 1 of table kemaskini.
when I type "Laptop" in form then I submit it.
it insert normally.
i more thing how I can trace "Speaker" and "speaker" are same.
if (isset($_POST['submit']))
{
$result = mysql_query("SELECT Item FROM kemaskini");
$test = mysql_fetch_array($result);
$trace=$test['Item'];
if($_POST['Item']==$trace)
{
echo "Try Again";
}
else
{
$item=$_POST['Item'] ;
$kuantiti= $_POST['kuantiti'] ;
mysql_query("INSERT INTO `kemaskini`(Item,kuantiti)
VALUES ('$item','$kuantiti')");
header("Location: kemaskini.php");
}
}
The reason for that is because you are not looping the result from mysql_fetch_array() that is why you are only checking for the first value of the result. If you don't want to Iterate, you can change the query into:
$itemToSearch = "Speaker";
$result = mysql_query("SELECT COUNT(*) result
FROM kemaskini
WHERE Item = '$itemToSearch'")
which will give you the total number of items found,
$test = mysql_fetch_array($result);
$trace = $test['result'];
if($trace > 0)
{
echo "Try Again";
}
else
{
// insert value
}
As a sidenote, the query is vulnerable with SQL Injection if the value(s) of the variables came from the outside. Please take a look at the article below to learn how to prevent from it. By using PreparedStatements you can get rid of using single quotes around values.
How to prevent SQL injection in PHP?
Regarding, how can you trace "Speaker" and "speaker" are the same, you can use the upper() or lower() function that most database engines support. I don't work with mysql so I am going on an assumption here. Your check would be something like this:
select count(*) records
from kemaskini
where lower(item) = 'speaker'
Having said that, I have to warn you that using functions in the where clause like this make your queries run slower.
If JW's comment about PreparedStatements includes using query parameters (I don't work with php either), it's very good advice. Not only do they increase the security of your applications, but they escape special characters such as apostrophes. Since you are doing a character search, you would not want your query to crash if the user submitted something like "Dave's keyboard" to your application.

PHP MySQL max() function producing 5

I am working on a survey created by PHP and MySQL. So the issue is, I am trying to create a ResponseID, which is an ID specific for every person submitting the survey. So the code was created to add 1 to the existing max value from the ResponseID column. Here's the code:
//Response ID creation
$query = "SELECT max(ResponseID) FROM survey";
$res = mysql_query($query);
$RID = $res+1;
I know I can condense it, but here's the problem: I already entered one item on the table with the ResponseID of 1. When I tested the survey with different answers, the next ResponseID was 5. It should have been 2. So I tested again to see if it would produce 6 next time.
Unfortunately, it produced 5 again. I had my PHP guru looked it over and he said the coding was correct and it should be something from the database. I didn't set anything in the ResponseID except for it being an int. So why is it producing a 5? If anyone could please tell me how to go about fixing it, that would be super cool of you.
I am somewhat new to PHP.
$res will be a mysql statement handle, NOT the result of the query. you still have to actually FETCH a row from this $res result to access the value of the max() function in the query.
This handle probably internally has identifier #5, which is why you're getting that "odd" result.
The code should be:
$sql = "SELECT MAX(responseID) AS max ...";
$result = mysql_query($sql) or die(mysql_error());
$row = mysql_fetch_assoc($result);
$RID = $row['max'] + 1;
$res is a resource, not the value of the query, please read the manual: http://nz.php.net/manual/en/function.mysql-query.php
Why don't you use an AUTO_INCREMENT column and retrieve the new value using mysql_insert_id?
You need to use an AUTO_INCREMENT column for this. The problem is that if two instances of the PHP script are running at the same time (extremely likely assuming you're using a multithreaded server like Apache), then you could have a case like this:
|PHP #1 | PHP #2 |
=================================
|Accept client |(waiting) |
|SELECT MAX... |(waiting) |
|Send to MySQL | Accept client |
|(waiting) | SELECT MAX... |
|(waiting) | Send to MySQL |
|Get response 4 |Get response 4 | //Nothing inserted yet, max is still 4
|Try to insert 5| (waiting) |
|Succeeded | (waiting) |
|(waiting) |Try to insert 5|
| ... | Failed! |
(This in addition to what Dagon said)
Use $row = mysql_fetch_assoc($res) to get the resulting row from your query.
See mysql_fetch_assoc().
The reason why you are not getting the correct value is because mysql_query doesn't return a value, it returns a resource.
Try this instead:
//Response ID creation
$query = "SELECT max(ResponseID) FROM survey";
$res = mysql_query($query);
if($res !== FALSE) $res = mysql_fetch_array($res); // If $res === FALSE, something went wrong
$RID = $res[0] + 1;
Also I suggest you to use AUTO_INCREMENT on the ResponseID field, this makes your life a lot easier :)
i'm not really sure if i understood ur problem but if u wanna generate a response ID specific to every user or every survey posted, then what u can do is use auto_increment for the response ID. the response id will be incremented every time a new survey is posted. also get the last id posted using mysql_insert_id to get the last id posted.
so u can get the last id using
$last_id = mysql_insert_id ();
u need to put that statement right after ur query. that way u can get the last id.

Categories