PHP replace dash with 0 from array when inserting to mySQL - php

I'm inserting/updating a mysql table from json URL, but some of the values in $points contain a dash and I want to amend to a zero (or null would be fine) when updating so that I can have the column set to INT.
I know how to simply replace all - to 0 in mysql but stuck when it comes to trying to do as part of update from a json URL. My code is:
for ($i = 0; $i < $length; $i++) {
$sus = $array['formguide'][$i]['SUSPENSION'];
$wpoints = $array['formguide'][$i]['WEEKPOINTS'];
$tcode = $array['formguide'][$i]['TEAMCODE'];
$val = $array['formguide'][$i]['VALUE'];
$points = $array['formguide'][$i]['POINTS'];
$pname = $array['formguide'][$i]['PLAYERNAME'];
$tname = $array['formguide'][$i]['TEAMNAME'];
$sixwpoints = $array['formguide'][$i]['SIXWEEKPOINTS'];
$injury = $array['formguide'][$i]['INJURY'];
$playerid = $array['formguide'][$i]['PLAYERID'];
$pos = $array['formguide'][$i]['POS'];
//insert or update values into mysql
$sql = "INSERT INTO formguide (suspension, weekpoints, teamcode,
value, points, playername, teamname,
sixweekpoints, injury, playerid, pos)
VALUES ('$sus', '$wpoints', '$tcode','$val','$points','$pname','$tname',
'$sixwpoints','$injury','$playerid','$pos')
ON DUPLICATE KEY UPDATE suspension='$sus', weekpoints='$wpoints',
teamcode='$tcode', value='$val', points='$points', playername='$pname',
teamname='$tname', sixweekpoints='$sixwpoints', injury='$injury',
playerid='$playerid', pos='$pos'";
I tried REPLACE() on points within the UPDATE() section i.e.:
...points=REPLACE('$points','-','0'), playername='$pname', ...
however that didn't work.
Any ideas how I can do this, or is there an alternative to have the points column as INT and accept a dash?
Thanks

REPLACE is for modifying values coming from SQL, whereas you want to modify a value coming from PHP.
Use str_replace instead.
$points = str_replace('-', '0', $points);

First, you need to escape or cast all values to avoid SQL injection vulnerabilities. Since you did not post your table schema, I'm guessing the types. mysqli_real_escape_string() is for strings, (int) and (float) for numbers of the respective type.
Doing that, your original problem is solved automatically, as PHP returns 0, if you cast '-' to integer.
Second, your query is a usecase for a proper use of REPLACE, which works exactly like INSERT, except that if an old row in the table has the same value as a new row for a PRIMARY KEY or a UNIQUE index, the old row is deleted before the new row is inserted.
for ($i = 0; $i < $length; $i++)
{
$sus = mysqli_real_escape_string($link, $array['formguide'][$i]['SUSPENSION']);
$wpoints = (int) $array['formguide'][$i]['WEEKPOINTS'];
$tcode = mysqli_real_escape_string($link, $array['formguide'][$i]['TEAMCODE']);
$val = (float) $array['formguide'][$i]['VALUE'];
$points = (int) $array['formguide'][$i]['POINTS'];
$pname = mysqli_real_escape_string($link, $array['formguide'][$i]['PLAYERNAME']);
$tname = mysqli_real_escape_string($link, $array['formguide'][$i]['TEAMNAME']);
$sixwpoints = (int) $array['formguide'][$i]['SIXWEEKPOINTS'];
$injury = mysqli_real_escape_string($link, $array['formguide'][$i]['INJURY']);
$playerid = (int) $array['formguide'][$i]['PLAYERID'];
$pos = (int) $array['formguide'][$i]['POS'];
// Insert or update values into mysql
$sql = "REPLACE INTO formguide SET
suspension='$sus',
weekpoints=$wpoints,
teamcode='$tcode',
value=$val,
points=$points,
playername='$pname',
teamname='$tname',
sixweekpoints=$sixwpoints,
injury='$injury',
playerid=$playerid,
pos=$pos
";
// ...
}

Related

Is there a faster way to import data from a file to MySQL using php?

Okay, so I get around 100k-1M lines of text that I always import to a database. The code that i use is as follows:
$lines = new SplFileObject('/home/file.txt');
while(!$lines->eof()) {
$lines->next(); //Skipping first line
$row = explode(',',$lines);
for($i = 0; $i<4; $i++){
if(!isset($row[$i])){
$row[$i] = null;
}
}
$y = (float) $row[1];
$z = (float) $row[2];
$load_query = "INSERT IGNORE INTO new (datetime_gmt,field2,field3)
VALUES ('".$row[0]."','".$y."','".$z."');";
if(!$mysqli->query($load_query)){
die("CANNOT EXECUTE".$mysqli->error."\n");
}
}
$lines = null;
However, it takes waaayyy too long. Is there any faster way to do it, or am I stuck with this method?
PS. I don't want to use MySQL's "INSERT DATA INFILE".
As written, you're running an insert statement for every line. It'll be much faster if you compile a single multi-insert statement in the format of INSERT INTO table (foo, bar) VALUES (1, 2), (3, 4), (5, 6); that is executed once at the end. Something along the lines of this, though it could be cleaned up more.
$lines = new SplFileObject('/home/file.txt');
$load_query = "INSERT IGNORE INTO new (datetime_gmt,field2,field3)
VALUES ";
while(!$lines->eof()) {
$lines->next(); //Skipping first line
$row = explode(',',$lines);
for($i = 0; $i<4; $i++){
if(!isset($row[$i])){
$row[$i] = null;
}
}
$y = (float) $row[1];
$z = (float) $row[2];
$load_query .= "('".$row[0]."','".$y."','".$z."'),";
}
if(!$mysqli->query(rtrim($load_query, ','))) {
die("CANNOT EXECUTE".$mysqli->error."\n");
}
$lines = null;
Also keep make sure the data is trusted. If the file can come from an outside user, appending directly to the query string creates an SQL injection vector.

Can i select data from mysqli database using SUBSTR to refine the query

I am trying the use refine tools for a search on my website. The bit i'm stuck with is search by start letter. For example i could use a wildcard '%X%' but his would return anything that contained the letter 'x'.
I read on few sites that SUBSTRING can be used in mysql queries
http://dev.mysql.com/
http://www.kirupa.com/
https://stackoverflow.com/questions/6302027
This is what I have so far but returns nothing. There is data in the database that should return with the query.
public function refineUsersFollowers($user_id,$q){
if($this->databaseConnection()){
// get the users followers
$state = array(1,2);
$stmt = $this->db_connection->prepare("SELECT * FROM friends WHERE id_2 = :1 AND Friend_Request_State = :2 OR id_2 = :3 AND Friend_Request_State = :4");
$stmt->bindParam(':1', $user_id);
$stmt->bindParam(':2', $state[0]);
$stmt->bindParam(':3', $user_id);
$stmt->bindParam(':4', $state[1]);
$stmt->execute();
// format the SQL OR statements
$sql = '';
$ids = [];
while($rows = $stmt->fetch(\PDO::FETCH_ASSOC)){
array_push($ids,$rows['id_1']);
}
for($x = 0; $x < count($ids); $x++){
if(count($ids) == 1){
//if there is one result
$sql.= ' user_id = :'.$x." AND SUBSTRING('first_name',0,1) = :".$x.$x;
}else if($x == (count($ids) - 1)){
// last entry
$sql.= ' user_id = :'.$x." AND SUBSTRING('first_name',0,1) = :".$x.$x;
}else{
//continue loop
$sql.= ' user_id = :'.$x." AND SUBSTRING('first_name',0,1) = :".$x.$x." OR";
}
}
$stmt = $this->db_connection->prepare("SELECT * FROM account WHERE ".$sql);
for($x = 0; $x < count($ids); $x++){
$stmt->bindParam(':'.$x,$ids[$x]);
$insert = $x.$x.'';
$stmt->bindParam(':'.$insert,$q);
}
$stmt->execute();
$results = $stmt->fetch(\PDO::FETCH_ASSOC);
print_r($results);
// check for followers that start with letter
}
}
The first part of the function is fine, this gets an array of id's which is then placed together as an SQL string. Is the SQL not returning results because SUBSTRING is not supported in this way?
If so is there a way of producing a query like this or would it be easier to pull every result from the database then check them in a different function?
You have two issues with this expression:
SUBSTRING('first_name', 0, 1) = :".$x.$x;
First, substr() in SQL (in general) starts counting with 1 and not 0. So, the first argument should be 1.
Second, you have the first argument in single quotes. So, at best, this would return the letter 'f'. Here is a simple rule: Only use single quotes for string and date constants. Never use single quotes to refer to column names.
There are several way to write what you want. Here are three:
SUBSTRING(first_name, 1, 1) = $x
LEFT(first_name, 1) = $x
first_name like '$x%'
You query can be greatly simplified with the LIKE operator. This:
"AND SUBSTRING('first_name',0,1) = :".$x.$x;
can become this:
"AND first_name LIKE '".$x.$x."%'";
I'm not sure what the $x.$x is for, so I just left it in for illustrative purposes.

different value of variable while inserting

I want to generate a pair of random numbers 1234567890-9876543210 (10 digits each)
I made this code. It works fine it generates a pair of random numbers BUT if I try to insert it into database I get same results multiple times. Let's say I get 1234567890 more than once. If I echo the insert statement I get different results but when I want to query it into database I get same results.
$numbers = array(0,1,2,3,4,5,6,7,8,9);
srand(time());
$f = fopen('sql0.txt', 'w');
for($i=0;$i<100000;$i++)
{
$r = NULL;
$r2 = NULL;
for($x=0;$x<10;$x++)
{
$n = rand(0,9);
$r .= $numbers[$n];
}
for($x=0;$x<10;$x++)
{
$n1 = rand(0,9);
$r2 .= $numbers[$n1];
}
echo("INSERT INTO ci_codes VALUES (NULL, '$r', '$r2', '0')<br>");
}
Do you need the INSERT expression inside your loop? That might cause the trouble.
As others have mentioned, it is better to just generate the numbers once with the php function, then run your MySql Query.
$r = mt_rand(0, 10000000);
$r2 = mt_rand(0, 10000000);
echo("INSERT INTO ci_codes VALUES (NULL, '$r', '$r2', '0'");

PHP Nested for loops

I basically want to scan a load of comments for illegal words and then replace those illegal words with a clean version.
I have two arrays, one array has all the comments to check, the other array has all of the illegal words to look for.
The first for loop gets the comments, the nested for loop then scans the comments for each of the illegal words and replaces them. The thing is though - it doesn't actually seem to work. Could you please advise if it is a problem with my loop structure, or the actual update logic?
$numComments = count($commentsToCheck);
$numIllegalWords = count($illegalWords);
for($i = 0; $i <= $numComments; $i++)
{
$message = $commentsToCheck[$i]['message'];
$commentId = $commentsToCheck[$i]['id'];
//error_log($message.'-'.$commentId);
for($j = 0; $j <= $numIllegalWords; $j++)
{
//Get word to replace with
$word = $illegalWords[$j]['word'];
//error_log($word);
$length = strlen($word);
$first = substr($word,0);
$last = substr($word,-1);
$starLength = $length - 2;
$replacement = $first.str_repeat('*',$starLength).$last;
$newMessage = preg_replace('/\b'.$word.'\b/i', $replacement, $message);
//Update the comment
$sql = "UPDATE ow_base_comment SET message = $newMessage WHERE id = $commentId LIMIT 1";
OW::getDbo()->query($sql);
}
}
Shouldnt your query not be what I placed below, since it wont see now the actual variables in the query. It will technincally just update nothing, cause there is no actual variable set.
$sql = "UPDATE ow_base_comment SET message = '".$newMessage."' WHERE id = '".$commentId."' LIMIT 1";
It's a common error to forget the quotes within PHP.

Format string using php to insert into mysql db

I have the following string:
$result = "category,date,product,cost
car,10/10/2005,toyota,3000
bike,12/12/2007,yamaha,1000";
I need to arrange the string into the best format to insert into a database (needs to be efficient as there might be lots of data also first row will not be needed).
The string is on new lines, so I can:
$n = explode("\n", $result);
which puts it in this format:
[0] => category,date,product,cost
[1] => car,10/10/2005,toyota,3000
[2] => bike,12/12/2007,yamaha,1000
now how would i go about formatting this to insert in a db, once again the solution needs to be efficient (for performance), also I would like the first row to not be inserted and finally on the insert I wish for the date to not be inserted.
Hope it makes sense, thanks for the help in advance.
--------edit---------------
The table (item) is structured with the following fields:
category, product, cost
thanks
If you are going to have a similar string with the same columns every time, then you could do something like this:
$n = explode("\n", $result);
// skip the first row since it's just column names
for ($i = 1; $i <= count($n); $i++)
{
$cat = $n[$i][[0]; // category
$date = $n[$i][[1]; // date
$prod = $n[$i][[2]; // product
$cost = $n[$i][[3]; // cost
// and you can put it into a query like so
$sql = "insert into myTable ('category', 'date', 'product', 'cost') values ('$cat', '$date', '$prod', '$cost')";
}
Does this answer your question?
Improving from previously answered post:
$n = explode("\n", $result);
// skip the first row since it's just column names
$sql = "insert into myTable ('category', 'date', 'product', 'cost') values ";
for ($i = 1; $i <= count($n); $i++)
{
$cat = $n[$i][[0]; // category
$date = $n[$i][[1]; // date
$prod = $n[$i][[2]; // product
$cost = $n[$i][[3]; // cost
$sql .= "('$cat', '$date', '$prod', '$cost'),";
}
$sql = trim($sql, ",");
if(count($n) != 0)
mysql_query($sql)
This gives you just one single query which will insert multiple rows.

Categories