In regards to your question, this was already answered here: URL rewriting with PHP
In the future, please make sure to search for possible solutions. Consider the following in your .htaccess file:
<ifModule mod_rewrite.c>
Options +FollowSymLinks
RewriteEngine on
RewriteRule ^/proyecto/id/([0-9]+)/$ /proyecto.php?id=$1
RewriteRule ^([^\.]+)$ $1.php [NC,L]
ErrorDocument 404 /error404.php
</ifModule>
This is the first step to creating a more secure GET Request. For example, this will pass:
www.mywebsite.com/proyecto/id/1/
While a malicious attempt should fail:
www.mywebsite.com/proyecto/id/%5Cxbf%5Cx27%20OR%201%3D1%20%2F*
This would pass \xbf\x27 OR 1=1 /*
to your script and could be potentially harmful payload. Since this value is not 0 through 9, the rewrite condition should not be met.
On to your SQL Query. This is the next level of defense, we want to ensure that we only use an integer variable type. To do this, we want to sanitize the input from the browser in some way. More than one way to do this. We can do it before passing the variable to the query or we can use PDO Functions.
Example 1: Santize the variable before Query
Instead of using:
$valorid = $_GET['id'];
Where whatever is entered as id
will be placed in the variable, we can force it to be a number. Something like:
$valorid = sprintf("%d", $_GET['id']);
This is a less used method, since it's basically formatting the variable into a digit.
Example 2: Using PDO Prepared Statement
Refer to: http://php.net/manual/en/pdo.prepared-statements.php
Consider the following:
$conn = new PDO("mysql:host=$host;dbname=$db_name;charset=utf8",$username, $password);
$stmt = $conn->prepare('SELECT * FROM grafica WHERE id = ? LIMIT 1');
if ($stmt->execute(array($_GET['id']))) {
while ($row = $stmt->fetch()) {
// Do the needful
}
}
This is considered a better method. One, we have improved the statement with LIMIT 1
to ensure we only get 1 result. Two, PDO will prepare the statement and ensure that all potentially harmful elements are handled, commented, or obscured.
Prepares an SQL statement to be executed by the PDOStatement::execute() method. The SQL statement can contain zero or more named (:name) or question mark (?) parameter markers for which real values will be substituted when the statement is executed. You cannot use both named and question mark parameter markers within the same SQL statement; pick one or the other parameter style. Use these parameters to bind any user-input, do not include the user-input directly in the query.
Hope that helps.