0

I have a code which kinda works, but not really i can't figure out why, what im trying to do is check inside the database if the URL is already there, if it is let the user know, if its not the go ahead and add it.

The code also makes sure that the field is not empty. However it seems like it checks to see if the url is already there, but if its not adding to the database anymore. Also the duplicate check seems like sometimes it works sometimes it doesn't so its kinda buggy. Any pointers would be great. Thank you.

    if(isset($_GET['site_url']) ){

    $url= $_GET['site_url'];


    $dupe = mysql_query("SELECT * FROM $tbl_name WHERE URL='$url'");
    $num_rows = mysql_num_rows($dupe);
    if ($num_rows) {
    echo 'Error! Already on our database!';
    }
    else {
    $insertSite_sql = "INSERT INTO $tbl_name (URL) VALUES('$url')";
    echo $url;
    echo ' added to the database!';

    }

}
else {
echo 'Error! Please fill all fileds!';
}
user1294097
  • 153
  • 1
  • 5
  • 14

3 Answers3

4

Instead of checking on the PHP side, you should make the field in MySQL UNIQUE. This way there is uniqueness checking on the database level (which will probably be much more efficient).

ALTER TABLE tbl ADD UNIQUE(URL);

Take note here that when a duplicate is INSERTed MySQL will complain. You should listen for errors returned by MySQL. With your current functions you should check if mysql_query() returns false and examine mysql_error(). However, you should really be using PDO. That way you can do:

try {
    $db = new PDO('mysql:host=localhost;db=dbname', $user, $pass);

    $stmt = $db->query('INSERT INTO tbl (URL) VALUES (:url)');
    $stmt->execute(array(':url' => $url));
} catch (PDOException $e) {
    if($e->getCode() == 1169) { //This is the code for a duplicate
        // Handle duplicate
        echo 'Error! Already in our database!';
    }
}

Also, it is very important that you have a PRIMARY KEY in your table. You should really add one. There are a lot of reasons for it. You could do that with:

ALTER TABLE tbl ADD Id INT;
ALTER TABLE tbl ADD PRIMARY KEY(Id);
Community
  • 1
  • 1
Bailey Parker
  • 15,599
  • 5
  • 53
  • 91
  • Currently the database only has one field the URL field, does this make a difference at all? Sorry <- im new to this world – user1294097 Jul 18 '12 at 01:56
  • @user1294097 No difference. I'm updating my post with more information. Run the query in my answer *once* (and substitute your table name in) from phpmyadmin (or another manager). You can remove all PHP duplicate checking code then. – Bailey Parker Jul 18 '12 at 01:59
  • +1 for PDO. -1 for not putting in the exact code for the error handling. Oops, you just added it, you thief! Well not quite, but at least you have the error number. – Buttle Butkus Jul 18 '12 at 02:16
  • @ButtleButkus How not quite? I left a comment where the OP could drop in whatever he wants to do when a duplicate is found. – Bailey Parker Jul 18 '12 at 02:21
  • @PhpMyCoder I'm giving you +1 for putting in the $e->getCode(). I think that will help him a lot. – Buttle Butkus Jul 18 '12 at 02:24
  • PDO is taotally new to me, I hate that i feel its written in a totally new language, yay something new to learn. Thanks! – user1294097 Jul 18 '12 at 03:13
  • @user1294097 It offers some great features. Transactions (rollbacks for failed blocks of queries), prepared statements (with escaping for all values), and fetching/querying to bound parameters as well as fetching as an object. You should really look into it. There are some great tutorials and SO posts on it. Just search around! And let us know if you need help. – Bailey Parker Jul 18 '12 at 03:25
1

You should take PhpMyCoder's advice on the UNIQUE field type.

Also, you're not printing any errors.

Make sure you have or die (mysql_error()); at the end of your mysql_* function(s) to print errors.

You also shouldn't even be using mysql_* functions. Take a look at PDO or MySQLi instead.

You're also not executing the insert query...

Try this code:

if(isset($_GET['site_url']) ){

$url= $_GET['site_url'];


$dupe = mysql_query("SELECT * FROM $tbl_name WHERE URL='$url'") or die (mysql_error());
$num_rows = mysql_num_rows($dupe);
if ($num_rows > 0) {
echo 'Error! Already on our database!';
}
else {
$insertSite_sql = "INSERT INTO $tbl_name (URL) VALUES('$url')";
mysql_query($insertSite_sql) or die (mysql_error());
echo $url;
echo ' added to the database!';

}

}
else {
echo 'Error! Please fill all fileds!';
}
  • 1
    -1, printing errors can make it easier for attackers to discern your database queries and structure. – Waleed Khan Jul 18 '12 at 02:05
  • Yes, but in case you haven't worked the current situation out, the code is in development, and something is wrong. Do you really think developers just magically guess the error when mysql complains? No, they don't. They use `mysql_error()` (well, those who still use `mysql_*` anyway). Think about it. –  Jul 18 '12 at 02:07
  • @navnav you can also log errors. It's not hard to do and not hard to check. But if you know that no one can see your pages who shouldn't, then it is fine to print errors. – Buttle Butkus Jul 18 '12 at 02:14
  • Thanks a lot, Taking all the advice here under close consideration, im having trouble making the url field unique because it exceeds the max key length so its something i have to figure out now :D – user1294097 Jul 18 '12 at 02:15
  • @ButtleButkus Yeah I suppose. But most developers use a testing server. So it's perfectly fine throwing errors on the screen during development. Also, I find it a pain in the neck having to keep checking my logs for errors, when I can just have it instantly on screen... –  Jul 18 '12 at 02:18
  • @navnav I suppose he is playing around with his home computer as a web server so it is probably completely safe. – Buttle Butkus Jul 18 '12 at 02:20
0

As PhpMyCoder said, you should add a unique index to the table.

To add to his answer, here is how you can do what you want to do with only one query.

After you add the unique index, if you try to "INSERT INTO" and it result in a duplicate, MySQL will produce an error.

You can use mysql_errno() to find out if there was a duplicate entry and tell the user.

e.g.

$sql = "INSERT INTO $tbl_name (URL) VALUES('$url')";
$result = mysql_query($sql);

if($result === false) {
  if(mysql_errno() == $duplicate_key_error) {
    echo 'Error! Already in our database!';
  } else {
    echo 'An error has occurred. MySQL said: ' . mysql_error();
  }
}

mysql_error() will return the mysql error in plain english.

mysql_errno() returns just the numeric error code. So set $duplicate_key_error to whatever the code is (I don't know it off the top of my head) and you are all set.

Also note that you don't want to print any specific system errors to users in production. You don't want hackers to get all kinds of information about your server. You would only be printing MySQL errors in testing or in non-public programs.

ALSO! Important, the mysql functions are deprecated. If you go to any of their pages ( e.g. http://php.net/manual/en/function.mysql-errno.php) you will see recommendations for better alternatives. You would probably want to use PDO.

Anyone who wants to edit my answer to change mysql to PDO or add the PDO version, go ahead.

Buttle Butkus
  • 9,206
  • 13
  • 79
  • 120