0

Ok, so I am needing either a workaround or some new direction with the way I am trying to run this query through PHP.

Basically, I only want to update columns if and only if the API string passes a string for that column. so If user updates name, but nothing else, then it only updates name column in the table. This explains the query... Now for the issue.

The issue is in order to compare if the API parameter being sent is blank or actually holds content (this is an iPhone App), I have to insert the PHP variable into the SQL statement and say, if this is blank then use the table's pre-existing value... this direct variable usage in the SQL is obviously causing errors. For example, if the password or any content with " or ' in the variable name, then it blows up the whole query because the variable is inserting an apostrophe into the SQL and screwing up the statement. No way to escape it that I know of and if I use PDO quote(), it inserts quotes in the database column and I don't want that! Is there a better way to do what I am trying to do? Please advise. I am open to completely redoing my statement and I don't like what I have because I think it is very labor intensive for the SQL server.

 //Assign passed parameters
$usr_id = $the_request['user_id'];
$usr_name = $the_request['name'];
$usr_email = $the_request['email'];//needs to re-validate
$usr_pass = $the_request['password'];//rehash
$usr_phone = $the_request['phone'];
$usr_img = $the_request['user_img'];

$queryUpdate = "UPDATE TABLE SET name = CASE WHEN '$usr_name' = '' THEN name ELSE ? END,
email = CASE WHEN '$usr_email' = '' THEN email ELSE ? END,
password = CASE WHEN '$usr_pass' = '' THEN password ELSE ? END,
phone = CASE WHEN '$usr_phone' = '' THEN phone ELSE ? END,
user_img = CASE WHEN '$usr_img' = '' THEN usr_img ELSE ? END
WHERE id = ? LIMIT 1";

if ($stmtUpdate =  $dbh->prepare($queryUpdate)) {
    $stmtUpdate->execute(array($usr_name,$usr_email,$hash,$usr_phone,$usr_img,$id));
        if( $stmtUpdate->rowCount() == 1 ) {
            echo json_encode(array('error' => ''));
        } else {
            echo json_encode(array('error' => 'Profile left unaffected'));
        }
}
6
  • 3
    Why do you have variables in the string if you're using parameters? Use parameters for everything.
    – Barmar
    Commented Mar 7, 2014 at 0:15
  • You seem to be mistyping the variables. In the query string, they're $user_XXX, but in the arguments to execute() they're $usr_XXX. Are those supposed to be the same variables?
    – Barmar
    Commented Mar 7, 2014 at 0:20
  • edited question... those variables are for POST and GET from the API string passed from the iPhone App.
    – jflay
    Commented Mar 7, 2014 at 0:58
  • Your execute statement is not using the variables you assigned. Don't you see the difference between user and usr?
    – Barmar
    Commented Mar 7, 2014 at 1:05
  • If you build SQL statements with variables, you are open to SQL injection. Commented Mar 7, 2014 at 1:35

1 Answer 1

2

Why not build up the query as required, eg

if (!isset($the_request['user_id'])) {
    throw new RuntimeException('Required request param "user_id" not found');
}

// Filter request using array of allowed keys
$params = array_intersect_key($the_request, array_flip(['name', 'email', 'password', 'phone', 'user_img']));

// Remove any empty values
$params = array_filter($params);

if (!count($params)) {
    exit; // or throw an exception, just end the program here though
}

// Build an array of SET parameters
$set = array_map(function($key) {
    return sprintf('%s = :%s', $key, $key);
}, array_keys($params));

$params['id'] = $the_request['user_id'];

$sql = sprintf('UPDATE TABLE SET %s WHERE id = :id LIMIT 1', implode(', ', $set));
$stmt = $dbh->prepare($sql);
$stmt->execute($params);

Demo here - http://ideone.com/jQ9etj

1
  • Really slick. Thanks so much! What did your edit do differently? I got it working prior...
    – jflay
    Commented Mar 7, 2014 at 4:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.