Well there's a challenge for PHP gurus:
I'm developing an application that use a huge number of MySql queries distributed in a great bunch of files and functions. Those queries uses, obviously, some parameters derived from the functions that contains them.
My goal is: group all those queries on a single constants file, but maintain the functionality. There's an example:
This is an example function:
public function doQuery ($aParameter) {
.
.
.
$sqlQuery = mysql_query("SELECT * FROM Table WHERE id = '".$aParameter."'");
.
.
.
}
And this is what I want to do, using constants:
public function doQuery ($aParameter) {
.
.
.
$sqlQuery = mysql_query(THE_QUERY);
.
.
.
}
As you can see, the problem is that if I use a defined constant as the query, it loses the parameter that I need to use to get the correct data from database.
So the final question is: There's a way to define a constant than can contain a variable to be determined when the constant is used? Something like:
define("THE_QUERY", "SELECT * FROM Table WHERE id = '".$aParameter."'");
Yes, with a parameterized query:
define("Q_QUERY1", "SELECT * FROM Table WHERE id = :1");
$cn = new PDO();
/* more code ... */
$arr = array();
$arr[":1"] = $parameterValue;
$s = $cn->prepare(Q_QUERY1);
$s->execute($arr);
The main idea is to have constants or even files to store queries (for example so you can have a query for sqlserver and another for mysql...) with the parameters declared inside with some kind of custom recognizable notation (:1, :PARAM1, etc.) that you have to match within an associative array such as $arr[":1"] in this case.
The ->execute method will match the parameters to the values for you, protecting your query against sql injections and adding the quotes around the parameters when necessary.
If you need specific data types you would need to use the ->bindParam method instead to specify a PDO::PARAM_XXX parameter of your choice.
The php documentation is pretty helpful if you need further details: http://php.net/manual/en/pdo.constants.php
Related
The function searches the $variable named table using SQL as showed here:
class Search{
`public function query(){`
`SELECT * FROM $tableName`
`}`
}
$object = new Search();
$object->query('tableName');
Is this a good practice or a door to SQL Inyection?
The short answer is NO, don't do this.
That said it may be perfectly safe depending on where your parameter is coming from.
consider mapping a variable to the table names, so you can verify that you are only building a query with a valid table name and not open-ended text.
A simple solution could look something like this:
public function query($tableName){
$allowedTables = ['accounts', 'items', 'products'];
$table = in_array($tableName, $allowedTables) ? $tableName : null;
if(empty($table)){
return false;
}
$sql = "Select * FROM " . $table;
...
}
You can do it in the safe way by "whitelisting" allowed tables. There are many different implementations depends on your needs. For example, get full or filtered list of your tables with:
SHOW TABLES;
BTW, PHP has a function for this. Then check if input table is in the list.
I think it's safe way to do this.
I have a database with many rates named rate1, rate2, rate3 ....... I need to be able to access them by a dynamically created PHP variable eg:
$fieldname = "rate". "2";
$cost = $qty * $mysqlresult->$fieldname;
I am sure there must be an answer already but have not been able to phrase the right question.
Without more info as to your specific problem, all I can provide is a simple solution as to how to format an SQL query in PHP where both the key and val are variables
$sql= "SELECT * FROM ". DB_TABLE ." WHERE ". $myKey ." = ". $myValue;
If you expand your question and supporting info some more I can expand my answer further if this doesn't help.
When your $mysqlresult is an Object, you can access the properties by using this:
$mysqlresult->{$fieldname}
I usually don't work with MSSQL and wonder how i can match a md5 value of a field value stored as string.
In mysql i would use
SELECT * FROM table WHERE md5(field) = $md5value
but i can't find a simple solution for this in mssql.
Now i loop all posts and check for the matched value in the loop, but this is way to slow.
How do I solve this in MSSQL?
I have no possibility to add a extra field in the table and store the md5 value, so i have to do the check this way.
Using odbc driver in php.
MSSQL uses no MD5(), but a function called HASHBYTES:
SELECT * FROM table WHERE HASHBYTES('MD5',field) = $md5value
This function appends '0x' to the hash though, so to fully check it, you need:
SELECT * FROM table WHERE HASHBYTES('MD5',field) = '0x' . $md5value
Edit: in PHP, it looks like this:
$query = "SELECT * FROM table WHERE HASHBYTES('MD5',field) = \"0x" . $md5value . '"';
I know how to perform mysql searches using for example the WHERE word. But my problem is that i need to search on different values, but these can vary in number. For example:
I can search for 3 variables Name, LastName, Age
BUT
I in other search, i can look for 2 variables Name, Age.
Is there a way to perform a MYSQL search with the same script, no matter the quantity of values i search.??
Ot it is a better practice to "force" the search of a fixed amount of variables.??
Thanks.!
Roberto
IMHO, it is far better to limit the search to a fixed number of variables. That way you are answering a specific question for a specific reason, not trying to fit a general answer to your specific question. Limiting the search criteria makes the statement(s) easier to debug and benchmark for performance.
Hope this helps.
Just use a variable for your search parameters and inject that into your query. Just ensure that in the function/method you put the variable into the proper format (which will depend on how you select the different values.)
SELECT *
FROM db
$variable;
There will be no WHERE clause seen, unless it is passed your values (meaning you can use this same query for a general search of the db) without fear of having an empty/required $variable.
Your $variable when constructed would need to have to have the WHERE clause in it, then each value you add, insert it (in a loop perhaps) in the proper format.
Hope this makes sense, if not let me know and I will try to clarify. This is the same method most people use when paginating (except they put the variable in the LIMIT instead of the WHERE)
EDIT:
Also make sure to properly sanitize your variable before injection.
Simple example of dynamically building a query:
$conditions = array();
if (...) {
$conditions['age'] = $age;
}
if (...) {
$conditions['name'] = $name;
}
...
if (!$conditions) {
die('No conditions supplied');
}
// if you're still using the mysql_ functions and haven't done so before:
$conditions = array_map('mysql_real_escape_string', $conditions);
foreach ($conditions as $field => &$value) {
$value = "`$field` = '$value'";
}
$query = 'SELECT ... WHERE ' . join(' AND ', $conditions);
It's really not hard to dynamically cobble together the exact query you want to create. Just be careful you don't mess up the SQL syntax or open yourself to more injection vulnerabilities. You may want to look at database abstraction layers, which pretty much allow you to pass a $conditions array into a function which will construct the actual query from it, more or less the way it's done above.
In my PHP file,I'm reading out bulk of information using query like below:
SELECT GROUP_CONCAT(CONCAT('<comment><body><![CDATA[',body,']]></body>','<replier>',if(screen_name is not null and !anonymous,screen_name,''),'</replier>','<created>',created,'</created></comment>') SEPARATOR '')
FROM idiscussion
LEFT JOIN
users
ON idiscussion.uid=users.id
WHERE idiscussion.iask_id = 1
yes,it's like xml format,but seems it's not easiest to parse in PHP,
Any recommendation on which format to use in order to parse easily later on?
AS for my I need to concatenating them all together,
You can think about this case: To retrieve 1 topic and discussions under this topic at a time. 1 topic corresponds to multiple discussions.How can you do it in 1 query without concatenating it together?
If you're getting data from a SQL database, it's much easier not to use SQL to clobber it into some text format, but to instead perform a regular query and use the SQL functions to work with the results that you're given.
If you end up needing to serialize data to other PHP clients, I would recommend PHP's standard serialization format.
Depends on the data structure, but a list of values may easily be saved as a semi-colon separated list of entries using join(), and then easily parsed using split().
This is extremely simple, but may not be ideal for slightly more complex data.
Answer to comment: if the data contains a semi-colon, it needs to be escaped as appropriate.
You could use DOM or SimpleXML to parse XML files, but also JSON or YAML. All are quite easy to use as you can rely on high-level parsers for PHP. They have advantages and disadvantages depending on how you want to use the format.
Can I ask why you're not just retrieving the data without concatenating it all together?
SELECT body,
IF(screen_name IS NOT NULL AND !anonymous, screen_name, '') AS replier,
created
FROM idiscussion
LEFT JOIN
users
ON idiscussion.uid = users.id
WHERE idiscussion.iask_id = 1
This should execute as quickly as your original query, and you can access its data as you would any other result set. Assuming you're using MySQL and not using PDO:
$result = mysql_query($sql);
if ($result) {
while ($row = mysql_fetch_assoc($result)) {
// $row is an associative array containing the current row's data.
}
}
If you need to create the XML but also want to access the data in its raw form, just create it in the PHP.
$xml =
'<comment>' .
'<body><![CDATA[' . $row['body'] . ']]></body>' .
'<replier>' . $row['replier'] . '</replier>' .
'<created>' . $row['created'] . '</created>' .
'</comment>';
You may need to escape the data if it hasn't been sanitised already. You could also use an XML builder such as XMLWriter, though that's beyond the scope of this question.