Modifying many rows of mySQL data from PHP - php

I have some php script that I would like to run on EVERY row within a mySQL table. The php script:
function replacespaces($text) {
return preg_replace_callback('/[\<]pre(.*)[\>](.*)[\<]\/pre[\>]/i',
create_function(
'$matches',
'return "<pre".$matches[1].">".str_replace(" ", " ", $matches[2])."</pre>\n";'
), $text);
}
I need to cycle through the mySQL database in the table "jos_picmicro_content" passing the content of the field "fulltext" to the above function, and inserting the result back into the field "fulltext". Sounds easy enough to do, although I am not experienced in the area! The table is about 500 rows long.

$result = mysql_query("SELECT * FROM jos_posmicro_content");
while ($row = mysql_fetch_array($result)) {
$text = replacespaces($row['fulltext']);
$sql = "UPDATE jos_posmicro_content SET fulltext = '" . mysql_real_escape_string($text) . "' WHERE ????";
mysql_query($sql);
}
You just ned to change the ???? part to identify which row to update (eg, where id = $row['id'] or whatever your primary key is).

Related

Display data from several fields in MySQL-table with specific id

I have the following code (SQL-query tested in phpMyAdmin and seems to work) that fetch data from selected columns:
$ids = isset($_REQUEST['id']) ? $_REQUEST['id'] : array();
if (is_array($ids)) $ids = implode(',', $ids);
if (!empty($ids)) {
$sql = "SELECT upload, upload2, upload3, upload4, upload5 FROM wp_site_table WHERE cid IN($ids) ORDER BY FIELD(cid, $ids)";
$results = $wpdb->get_results($sql) or die(mysql_error());
foreach( $results as $result ) { ... } }
The problem I have is that I want to output all fields from selected cid.
This code will only display the first cid result.
echo $result->upload;
Let's say $ids contain cid 1, 4 and 7 I'd like to output upload, upload2, upload4, upload5 from all those specific rows. How? Use an array in some way?
kind regards
Johan
If you want to echo all the fields, just do it:
echo $result->upload . '<br>' . $result->upload2 . '<br>' . $result->upload3 .
'<br>' . $result->upload4 . '<br>' . $result->upload5;
You should perhaps consider redesigning your database so you don't have repeated fields in each row. It would be better to have another table where each upload is in a row of its own, so there's no hard-coded limit on the number of these values. Then you can use a JOIN query to get all the uploads, and they'll be in an array.
With '$wpdb->get_results' output defaults to OBJECT type. Try using pre defined constant : ARRAY_A , it will result the output as an associative array.
$sql = "SELECT upload, upload2, upload3, upload4, upload5 FROM wp_site_table WHERE cid IN($ids) ORDER BY FIELD(cid, $ids)";
$results = $wpdb->get_results($sql, ARRAY_A) or die(mysql_error());
To access, simply use :
foreach( $results as $result ){
echo $result['upload'];
}

PHP multiple entries

I'm creating a small project with PHP/MYSQL but i can't get my query working the way i need it. I have 2 tables
Table 1 (char):
Id, name.
Table 2 (spells):
Id, char, spell_name.
I'm getting the output:
Name Spell1
Name Spell2
Name Spell3
But I need it to be:
Name Spell1
Spell2
Spell3
Here's my query:
$query = "SELECT char.name AS name, spells.spell_name AS spell
FROM char, spells
WHERE (char.id = spells.spell_name)";
Any ideas?
I think you're gonna have to first get the ID of the character to query, and then pull the spells s/he has access to. Example:
$char_id = 0; // value would be assigned arbitrarily.
$query = "SELECT *
FROM 'spells' s
WHERE s.char = $char_id;";
$result = $pdo->query($query);
while($row = $result->fetchObj()){
// do something with the spells obj here
}
With SQL, you need to grab full rows at a time, so I believe the situation you want isn't possible.
As Goldentoa11 wrote. Make two selects, or create query with two result sets (more selects in one command), or accept current state (is normal and you can verify data consistency). I prefer current state, but sometimes use any of described solution (based on query frequency, size of result etc.).
If you need to list such data, you can than use something like this:
$currentName = null;
while ($row = mysql_fetch_object($result))
{
if ($currentName != $row->name)
{
echo "<b>" . $row->name . "</b><br />";
$currentName = $row->name;
}
echo $row->spell_name . "<br />";
}

PHP POST via AJAX loop through javascript sent object literal

Hey all i normally grab the ajax sent js object literal by doing this:
$_POST['called']
$_POST['chk1']
etc etc...
But now i have a problem that i cant seem to find a solution for.
Depending on how many checkboxes are selected, i loop (using js) to see all checked boxes and add them to the js object that ends up looking like this:
doBulk = {
called: "Approved",
chk0: "1789156857",
chk2: "5134465673753",
chk3: "234123554646",
chk10: "25511545542"
};
Now the chkXX can be any number from 0-19 (so 20 check boxes per page). I am sending that just fine to my PHP page but i am unsure on how to go about looping to get the needed data to update the database.
$chk1 = $_POST['chk0'];
$chk2 = $_POST['chk1'];
$chk3 = $_POST['chk2'];
$chk4 = $_POST['chk3'];
$chk5 = $_POST['chk4'];
$chk6 = $_POST['chk5'];
$chk7 = $_POST['chk6'];
$chk8 = $_POST['chk7'];
$chk9 = $_POST['chk8'];
$chk10 = $_POST['chk9'];
$chk11 = $_POST['chk10'];
$chk12 = $_POST['chk11'];
$chk13 = $_POST['chk12'];
$chk14 = $_POST['chk13'];
$chk15 = $_POST['chk14'];
$chk16 = $_POST['chk15'];
$chk17 = $_POST['chk16'];
$chk18 = $_POST['chk17'];
$chk19 = $_POST['chk18'];
$chk20 = $_POST['chk19'];
I could do a lot of if than else to check to see if each has data but there has got to be a better way of doing that?
So if i am doing a bulk mySQL update then i would have to run a query for each checkbox that i have a value for above? Is there also a better way of updating all the records that are needed in one swoop?
$result = mysql_query("UPDATE userAccount SET Accept = 1 WHERE ID = " . $chk1 . "");
Thanks!
UPDATE
foreach($_POST as $key => $value)
{
// $key = CHK1-20
// $value = XXXXXXXXX
$dbBuilder = $value . ", " . $dbBuilder;
}
$dbBuilder = '(' . $dbBuilder . ')';
$result = mysql_query("UPDATE userAccount SET Accept = 1 WHERE ID in $dbBuilder");
You can pass in the id's inside an IN SQL Clause. So, for instance you will have:
UPDATE userAccount SET Accept = 1 WHERE ID in $idCollection
Where $idCollection will be all of the IDs checked, separated by commas and inside parentheses, like so:
(1, 2, 3)
For the looping, you can iterate through the $_POST array as you would in any other array, and populate this string with the values read.
Hope that helps
for ($i=1;$i<=20;$i++){
${'chk'."$i"}=$_POST["chk"."$i"];
}
For UPDATE, i think you can use Mysql create procedure like this
$query=mysql_query("CREATE PROCEDURE dorepeat(p1 INT) SET $i = 0; REPEAT SET #i = #i + 1; UPDATE userAccount SET Accept = 1 WHERE ID = ${'chk'."$i"}; UNTIL #i =p1 END REPEAT; END") or (die mysql_error());
$result=mysql_query("CALL dorepeat(20)") or (die mysql_error());
EDIT: perhaps this is better without using CREATE PROCEDURE.
for ($i=1;$i<=20;$i++){
${'chk'."$i"}=$_POST["chk"."$i"];
$exp.=${'chk'."$i"}.',';
}
$exp=substr($exp,0,-1);
$exp='('.$exp.')';
$query=mysql_query("UPDATE userAccount SET Accept = 1 WHERE ID IN '$exp') or (die mysql_error());

Is it possible to return the nth field of a table in MySQL?

I'm trying to use PHP to populate drop-down menus with data from certain columns of separate tables. But, I have many menus to populate, so instead of making a function specific to each, I wanted to pass the column name (which is the field, right?) to the function.
Currently I have this for one menu
function print_dropdown($query, $link){
$queried = mysql_query($query, $link);
$menu = '<select name="wholesaler" id="wholesaler">';
while ($result = mysql_fetch_array($queried)) {
$menu .= '<option value="' . $result['id'] . '">' . $result['wholesaler'] . '</option>';
}
$menu .= '</select>';
return $menu;
}
...
<?php echo print_dropdown("SELECT id, wholesaler FROM wholesaler_flag LIMIT 0, 10", $connect_normas_boudoir);
?>
But, I'd like to do this:
function get_field($table){
$col_2 = mysql_query('SHOW COLUMNS FROM "$table" WHERE FIELD = 2');
return $col_2;
}
function print_dropdown($query, $link){
$queried = mysql_query($query, $link);
$menu = '<select name="'$col_2'" id="'$col_2'">';
while ($result = mysql_fetch_array($queried)) {
$menu .= '<option value="' . $result['id'] . '">' . $result['$col_2'] . '</option>';
}
$menu .= '</select>';
return $menu;
}
...
<?php
get_field(wholesaler_flag);
echo print_dropdown("SELECT id, wholesaler FROM wholesaler_flag LIMIT 0, 10", $connect_normas_boudoir);
?>
Is it bad form to try and select the second field of each table? In my case there are only two columns in each table concerned. But, I understand that in future a new column could, theoretically, be inserted after id. Is there a better way to do this? Please excuse if I've botched up my single and double quotes. Still learning.
Note: I've tried SHOW COLUMNS FROM wholesaler_flag WHERE FIELD = 2; in the MySQL console. Of course it didn't work, but I thought there might be a way of accessing that. This is the specific area with which my question is concerned.
function print_dropdown($query, $link,$field0,$field1){
$queried = mysql_query($query, $link);
$menu = '<select name="'.$field1.'" id="'.$field1.'">';
while ($result = mysql_fetch_array($queried)) {
$menu .= '<option value="' . $result[0] . '">' . $result[1] . '</option>';
}
$menu .= '</select>';
return $menu;
}
<?php
echo print_dropdown("SELECT id, wholesaler FROM wholesaler_flag LIMIT 0, 10", $connect_normas_boudoir,"id","wholesaler");
?>
Since you are passing the sql statement to the function, why not pass the option id and option value name you want. With the above, you should always supply id as first column, name as second column in the sql statement since option value is fixed to first column and value to second column ie $result[0] and $result[1] respectively.You could try out the above. Thanks.
What exactly are you trying to do? To select the nth row from a field, if you were doing a SELECT query, would be:
SELECT * FROM table LIMIT n-1,1
However, you're doing this on the query SHOW COLUMNS, which does not rely on the row number. You can select the 5th row or the 50th row (which is not possible anyway in that query) and it would still return the same result (information on the columns of the table).
You can easily pass field/table names to a function and build a query like that. However, in your given example, given the incorrect PHP/SQL syntax, it is unclear what you're trying to accomplish with your functions.
EDIT BASED ON COMMENT FEEDBACK:
You can write a function that will take the table and the target column number, which will then pass back the column name to you. The following function takes your SQL table (i.e. "wholesaler_flag") and the number of the column you want (i.e. 2 as stated in your example).
function getColumnName($sqlTable, $targetColumn = 2) {
$currentColumn = 1; // indicate our starting position for the column traversal
$theQuery = mysql_query("SHOW COLUMNS FROM " . $sqlTable); // get columns from table
// traverse columns until we reach the desired column number; return column name
while ($theColumn = mysql_fetch_array($theQuery)) {
if ($currentColumn == $targetColumn) {
return $theColumn["Field"];
}
$currentColumn++;
}
return false; // returns Boolean false if column number is not found
}
This can be called through:
$columnName = getColumnName("wholesaler_flag", 2);
// $columnName = getColumnName("wholesaler_flag"); also works since 2 is set as the function's default column
You could also use it to get column 3, 4, etc. or whatever you want. With a little modification, you can also make it return a range of columns.

How to remove htmlentities() values from the database?

Long before I knew anything - not that I know much even now - I desgined a web app in php which inserted data in my mysql database after running the values through htmlentities(). I eventually came to my senses and removed this step and stuck it in the output rather than input and went on my merry way.
However I've since had to revisit some of this old data and unfortunately I have an issue, when it's displayed on the screen I'm getting values displayed which are effectively htmlentitied twice.
So, is there a mysql or phpmyadmin way of changing all the older, affected rows back into their relevant characters or will I have to write a script to read each row, decode and update all 17 million rows in 12 tables?
EDIT:
Thanks for the help everyone, I wrote my own answer down below with some code in, it's not pretty but it worked on the test data earlier so barring someone pointing out a glaring error in my code while I'm in bed I'll be running it on a backup DB tomorrow and then on the live one if that works out alright.
I ended up using this, not pretty, but I'm tired, it's 2am and it did its job! (Edit: on test data)
$tables = array('users', 'users_more', 'users_extra', 'forum_posts', 'posts_edits', 'forum_threads', 'orders', 'product_comments', 'products', 'favourites', 'blocked', 'notes');
foreach($tables as $table)
{
$sql = "SELECT * FROM {$table} WHERE data_date_ts < '{$encode_cutoff}'";
$rows = $database->query($sql);
while($row = mysql_fetch_assoc($rows))
{
$new = array();
foreach($row as $key => $data)
{
$new[$key] = $database->escape_value(html_entity_decode($data, ENT_QUOTES, 'UTF-8'));
}
array_shift($new);
$new_string = "";
$i = 0;
foreach($new as $new_key => $new_data)
{
if($i > 0) { $new_string.= ", "; }
$new_string.= $new_key . "='" . $new_data . "'";
$i++;
}
$sql = "UPDATE {$table} SET " . $new_string . " WHERE id='" . $row['id'] . "'";
$database->query($sql);
// plus some code to check that all out
}
}
Since PHP was the method of encoding, you'll want to use it to decode. You can use html_entity_decode to convert them back to their original characters. Gotta loop!
Just be careful not to decode rows that don't need it. Not sure how you'll determine that.
I think writing a php script is good thing to do in this situation. You can use, as Dave said, the html_entity_decode() function to convert your texts back.
Try your script on a table with few entries first. This will make you save a lot of testing time. Of course, remember to backup your table(s) before running the php script.
I'm afraid there is no shorter possibility. The computation for millions of rows remains quite expensive, no matter how you convert the datasets back. So go for a php script... it's the easiest way
This is my bullet proof version. It iterates over all Tables and String columns in a database, determines primary key(s) and performs updates.
It is intended to run the php-file from command line to get progress information.
<?php
$DBC = new mysqli("localhost", "user", "dbpass", "dbname");
$DBC->set_charset("utf8");
$tables = $DBC->query("SHOW FULL TABLES WHERE Table_type='BASE TABLE'");
while($table = $tables->fetch_array()) {
$table = $table[0];
$columns = $DBC->query("DESCRIBE `{$table}`");
$textFields = array();
$primaryKeys = array();
while($column = $columns->fetch_assoc()) {
// check for char, varchar, text, mediumtext and so on
if ($column["Key"] == "PRI") {
$primaryKeys[] = $column['Field'];
} else if (strpos( $column["Type"], "char") !== false || strpos($column["Type"], "text") !== false ) {
$textFields[] = $column['Field'];
}
}
if (!count($primaryKeys)) {
echo "Cannot convert table without primary key: '$table'\n";
continue;
}
foreach ($textFields as $textField) {
$sql = "SELECT `".implode("`,`", $primaryKeys)."`,`$textField` from `$table` WHERE `$textField` like '%&%'";
$candidates = $DBC->query($sql);
$tmp = $DBC->query("SELECT FOUND_ROWS()");
$rowCount = $tmp->fetch_array()[0];
$tmp->free();
echo "Updating $rowCount in $table.$textField\n";
$count=0;
while($candidate = $candidates->fetch_assoc()) {
$oldValue = $candidate[$textField];
$newValue = html_entity_decode($candidate[$textField], ENT_QUOTES | ENT_XML1, 'UTF-8');
if ($oldValue != $newValue) {
$sql = "UPDATE `$table` SET `$textField` = '"
. $DBC->real_escape_string($newValue)
. "' WHERE ";
foreach ($primaryKeys as $pk) {
$sql .= "`$pk` = '" . $DBC->real_escape_string($candidate[$pk]) . "' AND ";
}
$sql .= "1";
$DBC->query($sql);
}
$count++;
echo "$count / $rowCount\r";
}
}
}
?>
cheers
Roland
It's a bit kludgy but I think the mass update is the only way to go...
$Query = "SELECT row_id, html_entitied_column FROM table";
$result = mysql_query($Query, $connection);
while($row = mysql_fetch_array($result)){
$updatedValue = html_entity_decode($row['html_entitied_column']);
$Query = "UPDATE table SET html_entitied_column = '" . $updatedValue . "' ";
$Query .= "WHERE row_id = " . $row['row_id'];
mysql_query($Query, $connection);
}
This is simplified, no error handling etc.
Not sure what the processing time would be on millions of rows so you might need to break it up into chunks to avoid script timeouts.
I had the exact same problem. Since I had multiple clients running the application in production, I wanted to avoid running a PHP script to clean the database for every one of them.
I came up with a solution that is far from perfect, but does the job painlessly.
Track all the spots in your code where you use htmlentities() before inserting data, and remove that.
Change your "display data as HTML" method to something like this :
return html_entity_decode(htmlentities($chaine, ENT_NOQUOTES), ENT_NOQUOTES);
The undo-redo process is kind of ridiculous, but it does the job. And your database will slowly clean itself everytime users update the incorrect data.

Categories