I have large tables in my database and instead of specifying each column name I am trying to build the query dynamically.
I am trying to do an update in the 'motherboard' table based on the POST data received. The $data object i receive has more fields than the table has. (I added some fields for some flags.)
Hence, I am retrieving the record I'm about to update and by comparing each of it's columns with my $data object fields I am constructing the UPDATE query.
I'm new to php, therefore I don't know the syntax well.
This is the code:
<?php
$data = json_decode($_POST["data"], true);
$id = $data["ID"];
include_once 'dbconnect.php';
$query = sprintf("SELECT * FROM `motherboard` WHERE ID = " . $id . ";");
$result = mysqli_query($con, $query);
$existingData = mysqli_fetch_assoc($result);
include_once 'dbclose.php';
$statement = "";
$statement = "UPDATE motherboard SET ";
$flag = false;
foreach ($existingData as $key => $value) {
if ($existingData->$key != $data->$key) {
$statement .= $key . " = " . $data->$key . " , ";
$flag = true;
}
}
if ($flag)
$statement = substr($statement, 0, strrchr($statement, ',') - 1);
$statement .= " WHERE ID = " . $id . ";";
echo $statement;
?>
My main problem is in the foreach loop. I don't know how can I compare and then use for building the query the $existingData and $data variables.
How can I achieve this?
Don't use this approach please, if you want a SOLID application that will outrun the ages, use specific column names and not some junkish foreach loop that builds your SQL for you. If you want to evade the writting of SQL, use an ORM, there are ton's that exist out there and most of them are bundled with a framework right off the start making it simpler to learn the ropes!
Examples of simple to learn frameworks: (But not necessarely weak frameworks)
Cake PHP
Laravel
Good luck
You need to change some code ...
$result = mysqli_query($con, $query);
$existingData = mysqli_fetch_assoc($result);
Now your $existingData is an array you can loop though;
Honestly I would recommend you take advantage of a framework with an ORM or just a standalone ORM. I suggest Laravel or CodeIgniter (if you are new to programming in general then CodeIgniter will be the easiest).
Next, why is your POST data JSON encoded? Why not just POST all the form variables? I would recommend that way instead to simplify it (even from JS).
Finally, you have to make sure you sanitize your inputs. You can use mysqli_real_escape_string(). I am assuming you will use the MySQLi DB interface. (Ref: http://php.net/manual/en/mysqlinfo.api.choosing.php)
Actually one last note: Laravel is, in my opinion, the future of PHP frameworks. It is beautiful, lightweight, and powerful. I HIGHLY recommend that you learn it. Ref: http://laravel.com/
I managed to get it working. Now I'm constructing my queries based on the difference between the existing data and the updates from the user. The foreach loop now looks like this:
foreach ($existingData as $key => $value) {
if ($existingData[$key] != $data[$key]) {
$statement .= $key . " = \"" . $data[$key] . "\" , ";
$flag = true;
}
}
This is the part that was interesting for me. The rest of the code should be updated according to the latest API.
Related
I want to have the fields names separated with ',' .
This query
show COLUMNS FROM ma_table;
Returns raw unseparated values
$sql = "show COLUMNS from ma_table ";
$req = mysql_query($sql) or die('Erreur<br>'.$sql.'<br>'.mysql_error());
while ($rslt = mysql_fetch_assoc($req)) {
$fields=$rslt['Field'];
}
mysql_close();
All you need to do is concatenate a comma onto $fields as you process round the while loop.
You also need to use the .= string concatenation operator in the loop so you are adding each new Field to the string and not overwriting it each time.
$fields = '';
while ($rslt = mysql_fetch_assoc($req)) {
$fields .= $rslt['Field'] . ',';
}
echo rtrim($fields, ',');
I am afraid I must also add
Every time you use the mysql_
database extension in new code
a Kitten is strangled somewhere in the world it is deprecated and has been for years and is gone for ever in PHP7.
If you are just learning PHP, spend your energies learning the PDO or mysqli database extensions.
Start here
I am moving a PHP page to my Joomla website and I was advised that I "should use Joomla's coding standards and methods for everything, this includes database queries"
My question is:
How should I transform my old PHP code regarding Joomla standards:
$query = "SELECT * FROM `TABLE 2` WHERE Power=".$input->get('Power', '', 'RAW')." AND Poles=".$input->get('Poles', '', 'RAW')."";
$results = mysql_query($query)
or die(mysql_error());
while ($row = mysql_fetch_array($results))
{
extract($row);
}
?>
This is the TABLE 2 contents. I use the values of each row as a variables on my page.
Most importantly make sure to filter the input to disallow sql injections. Seems both your inputs are numbers (Power is a float and Poles possibly an int?). Also use the #__ - in table names, it will be replaced by the table prefex when you use it in joomla functions. Simplest way to transform your code would be something like:
$app = JFactory::getApplication();
$power = $app->input->getFloat('Power'); // use the correct function
$poles = $app->input->getInt('Poles'); // for the datatype you want
see here for JInput docs
$db = $app->getDbo();
//short variant
$sql = "SELECT * from `#__table 2` WHERE power = "
. $db->quote($power) . " AND poles = " . $db->quote($poles);
$db->setQuery($sql);
$result = $db->loadRowList();
foreach($result as $array){
print_r($array);
}
It should be noted that there are more useful methods for retrieving the data, loadAssoc/loadAssocList for associative arrays, loadObject/loadObjectList for objects. Check the docs for JDatabaseDriver
Alternatively you could transform the query to a "Joomla query" like:
$q = $db->getQuery();
$q->select("*")->from($q->quoteName("#__Table 2"));
$q->where("Power = " . $db->quote($power));
$q->where("Poles = " . $db->quote($poles));
$db->setQuery($q);
...
Docs to JDatabaseQuery
I am doing work with php object oriented and mysqli. i have class name Database.php inside this class i have defined a function name update.
i did some thing wrong i think that's why it doesn't work fine. when i use to run click at update then data retrieves in Form but when i try to save the updated form it always updated only first column of my database. function code is given below:
public function update($tablename, $value, $where){
$Update = " UPDATE ".$tablename." SET ";
$array_keys = array_keys($value);
$array_values= array_values($value);
$count = count($array_keys);
for($i=0; $i< $count; $i++){
$value[$i] = " = '".$value[$array_keys[$i]]."' ";
}
//$value = implode(" ",$value);
print_r($value);
$Update .= " ".$value." WHERE ".$where;
$Utest = $this->DbCon->query($Update);
if($Utest){
return true;
}else{
return false;
}
here is php code that i have tried before
if(isset($_POST['update'])){
$id1 = $_POST['id'];
$name = $_POST['name'];
$city = $_POST['city'];
$success=$DbQuery->update("record", array(" name " => $name ,"city" => $city)," id =".$id1);
if($success){
header("LOCATION:index.php");
}else{
echo "try again ";
}
}
do you have any good suggestion for update function how ic an improve this function. actually i am new in php object oriented so suggest me easy method to this. Thanks
The problem is that you're trying to convert the $value array to a string in $Update .= " ".$value." WHERE ".$where;. You can't do that. You have to construct the query in the for loop above it instead of populating the $value array. Either way you shouldn't be building the query by hand. You REALLY should use PDO::prepare() or $mysqli::prepare() to prevent vulnerabilities. Yes, that might feel like an overkill if you're just learning, but you should start forming good habits from the very beginning.
Also, fix your formatting. Your code is really hard to read. I recommend reading through the PSR standard (or any widespread PHP standard) and adapting it in your code. Again, might feel like overkill, but it's a good habit to pick up early.
Here's an adapted version of your code for you to easily play with. You can see the problem if you run php index.php in the CLI window at the bottom.
I was wondering if you think this is possible:
Ok so I have a database storing usernames and I would like to echo the admins which are inside a file called admins.php IF they match the usernames inside the database so far I have got:
admins.php;
$admins = array("username","username2","username3");
and
$users="SELECT username from usrsys";
$query_users=mysql_query($users);
while loop here.
The while loop should hopefully echo the users which matches the admins.php file. I assume I should use something like (inarray()), but I am really not sure.
You should definitely use IN clause in your SQL to do this. Selecting everything from the table in order to determine in PHP if it contains the user names you're looking for makes no sense and is very wasteful. Can you imagine what would happen if you had a table of 1 million users and you needed to see if two of them were on that list? You would be asking your DBMS to return 1 million rows to PHP so that you can search through each of those names and then determine whether or not any of them are the ones you're looking for. You're asking your DBMS to do a lot of work (send over all the rows in the table), and you're also asking PHP to do a lot of work (store all those rows in memory and compute a match), unnecessarily.
There is a much more efficient and faster solution depending on what you want.
First, if you only need to know that all of those users exist in the table then use SELECT COUNT(username) instead and your database will return a single row with a value for how many rows were found in the table. That way you have an all or nothing approach (if that's what you're looking for). Either there were 3 rows found in the table and 3 elements in the array or there weren't. This also utilizes your table indexes (which you should have properly indexed) and means faster results.
$admins = array("username","username2","username3");
// Make sure you properly escape your data before you put in your SQL
$list = array_map('mysql_real_escape_string', $admins);
// You're going to need to quote the strings as well before they work in your SQL
foreach ($list as $k => $v) $list[$k] = "'$v'";
$list = implode(',', $list);
$users = "SELECT COUNT(username) FROM usrsys WHERE username IN($list)";
$query_users = mysql_query($users);
if (!$query_users) {
echo "Huston we have a problem! " . mysql_error(); // Basic error handling (DEBUG ONLY)
exit;
}
if (false === $result = mysql_fetch_row($query_users)) {
echo "Huston we have a problme! " . mysql_error(); // Basic error handling (DEBUG ONLY)
}
if ($result[0] == count($admins)) {
echo "All admins found! We have {$result[0]} admins in the table... Mission complete. Returning to base, over...";
}
If you actually do want all the data then remove the COUNT from the SQL and you will simply get all the rows for those users (if any are found).
$admins = array("username","username2","username3");
// Make sure you properly escape your data before you put in your SQL
$list = array_map('mysql_real_escape_string', $admins);
// You're going to need to quote the strings as well before they work in your SQL
foreach ($list as $k => $v) $list[$k] = "'$v'";
$list = implode(',', $list);
$users = "SELECT username FROM usrsys WHERE username IN($list)";
$query_users = mysql_query($users);
if (!$query_users) {
echo "Huston we have a problem! " . mysql_error(); // Basic error handling (DEBUG ONLY)
exit;
}
// Loop over the result set
while ($result = mysql_fetch_assoc($query_users)) {
echo "User name found: {$result['username']}\n";
}
However, I really urge you to reconsider using the old ext/mysql API to interface with your MySQL database in PHP since it is deprecated and has been discouraged from use for quite some time. I would really urge you to start using the new alternative APIs such as PDO or MySQLi and see the guide in the manual for help with choosing an API.
In PDO, for example this process would be quite simple with prepared statements and parameterized queries as you don't have to worry about all this escaping.
There's an example in the PDOStatement::Execute page (Example #5) that shows you just how to do use the IN clause that way with prepared statements... You can then reuse this statement in other places in your code and it offers a performance benefit as well as making it harder for you to inadvertently expose yourself to SQL injection vulnerabilities.
// Connect to your database
$pdo = new PDO("mysql:dbname=mydb;host=127.0.0.1", $username, $password);
// List of admins we want to find in the table
$admins = array("username","username2","username3");
// Create the place holders for your paratmers
$place_holders = implode(',', array_fill(0, count($admins), '?'));
// Create the prepared statement
$sth = $dbh->prepare("SELECT username FROM usrsys WHERE username IN ($place_holders)");
// Execute the statement
$sth->execute($admins);
// Iterate over the result set
foreach ($sth->fetchAll(PDO::FETCH_ASSOC) as $row) {
echo "We found the user name: {$row['username']}!\n";
}
Your PHP code even looks so much better with PDO :)
Just include admins.php file and use the next construction in your loop:
while ($row = mysql_fetch_array($users)) {
if (in_array($users[0], $admins))
echo $users[0];
}
Try this:
<?php
# include admins.php file that holds the admins array
include "admins.php";
# join all values in the admins array using "," as a separator (to use them in the sql statement)
$admins = join(",", $admins);
# execute the query
$result = mysql_query("
SELECT username
FROM usrsys
WHERE username IN ($admins)
");
if ($result) {
while ($row = mysql_fetch_array($result)) {
echo $row["username"] . "<br>";
}
}
?>
If your looking for syntax to pull in only the users from your $admins array then you could use something like:
$users="SELECT username FROM usrsys WHERE username IN ('".join("','",$admins)."')";
Where the php function JOIN will print username,username2,username3. Your resulting MySQL statement will look like:
SELECT username FROM usrsys WHERE username IN ('username','username2','username3')
Alternatively, if your looking to iterate through your $query_vars array and separate your admins from non-admins then you could use something like:
<?php
while($row = mysql_fetch_assoc($query_users)){
if(in_array($row['username'],$admins)){
//do admin stuff here
}else{
//do NON-admin stuff here
}
}?>
I have a submission script that I wrote in PHP. It is used by multiple surveys at our organization. The surveys are created by other users. When they submit to the script, PHP puts the data into the appropriate table in MySQL. The error that I run into sometimes is that the user(s) update the form. They add a field, or rename an input and the script doesn't account for it since it expects everything to be the same. So, I am trying to find a way to make it accomodate for when a new field is added. Here is what I have:
if( mysql_num_rows( mysql_query("SHOW TABLES LIKE '".$survey."'"))){
echo "table exists";
$sql = "SELECT * FROM " . $survey . ";";
$result = mysql_query($sql)
or die(mysql_error());
$i=0;
while($row = mysql_fetch_row($result));{
echo $row[0];
foreach($_POST as $k => $v){
$i++;
if($k != $row[$i]){
$query = "ALTER TABLE " . $survey . " ADD " . $k . " VARCHAR(100);";
mysql_query($query)
or die(mysql_error());
}
}
}
}
I am used to doing while loops in JS, so I don't know if using i works here (actually, I know it doesn't work... because it doesn't work...). What I am trying to say is that if a key doesn't match a current field name, then add it to the table. How can I return $row correctly?
When I submit to the script it says:
Duplicate column name 'V4'
I have echo $row[0] but it returns a 1. Which is the is the int used in the primary key for the for the first record.
You have a ; at the end of your while loop declaration that shouldn't be there. Not sure if that is causing the problem as you don't say what the above code does do. Update the question if the ; is not the issue.
Your while loop declaration should look like this: while($row = mysql_fetch_row($result)) {
Also, as Marc B so diplomatically put it in a comment to your question, you should be escaping any user input that goes directly into a query.
The easiest way to do this is to use $survey = mysql_real_escape_string($survey), before your first use of $survey, as a start or switch to PDO/MySQLi and use input binding (prepared statements). Here are the prepared statements docs for PDO. More can, and should, be done to protect yourself, but the above is a good start.