9

I need a simple and fast solution to replace nth occurrence (placeholder) in a string.

For example, nth question mark in sql query should be replaced with a provided value.

$subject = "SELECT uid FROM users WHERE uid = ? or username = ?";

So, i need function like str_replace_nth($seach, $replace, $subject, $nth) and for second question mark it should be called as str_replace_nth("?", $username, $subject, 2);

Any ideas?

P.S. Please, don't suggest me to use PDO, because I'm working on FDO (Facebook Data Object) a library with an interface similar to PDO, but for FQL.

Important notice! I've figured out that this approach is bad because after first replacement the query is modified and indexes are lost. (Bad approaches come when you're programming late at night :() So, as @GolezTrol mention in comment, it's better to replace all at once.

4
  • 1
    If it is about SQL queries, or something similar, you are probably going to replace every question mark, so if you start with the first one, then afterwards the second will be the first. Eventually you will always replace the first one. Commented Nov 11, 2013 at 13:09
  • It should be called with $fdo->bindValue($parameter, $value), I would like to keep it order-neutral. Commented Nov 11, 2013 at 13:16
  • 1
    And what would you pass as $parameter if you only have question marks? An index? If so, you could save up the values and only process them (in the right order) just before executing the query. That also allows the user to set a default value for a parameter and overwrite it later but before executing. But actually, I like the named parameters solution as proposed by @RaphaëlMalié better. Commented Nov 11, 2013 at 13:19
  • Parameter is an index, but can be named placeholder, also. "Overwrite just before executing" sounds good. Thank you. P.S. Placeholders are already supported, check the link... Commented Nov 11, 2013 at 13:28

4 Answers 4

15

Here is the function you asked for:

$subject = "SELECT uid FROM users WHERE uid = ? or username = ?";

function str_replace_nth($search, $replace, $subject, $nth)
{
    $found = preg_match_all('/'.preg_quote($search).'/', $subject, $matches, PREG_OFFSET_CAPTURE);
    if (false !== $found && $found > $nth) {
        return substr_replace($subject, $replace, $matches[0][$nth][1], strlen($search));
    }
    return $subject;
}

echo str_replace_nth('?', 'username', $subject, 1);

Note: $nth is a zero based index!

But I'll recommend to use something like the following to replace the placeholders:

$subject = "SELECT uid FROM users WHERE uid = ? or username = ?";

$args = array('1', 'steve');
echo vsprintf(str_replace('?', '%s', $subject), $args);
Sign up to request clarification or add additional context in comments.

1 Comment

preg_quote has to be called with delimiter to make it work: preg_quote($search, '/')
6

Instead of using question marks, why don't use markers like that :

$subject = "SELECT uid FROM users WHERE uid = :uid or username = :username";
$parameters = array(
    ':uid' => 42,
    ':username' => 'John',
);
$subject = str_replace(array_keys($parameters), $parameters, $subject);

1 Comment

Using question marks is very useful and I'm already implemented named placeholders github.com/salebab/FDO/blob/master/src/fdo/FDOStatement.php#L99
0

Validation on input parameter not done

 function str_replace_nth($search, $replace, $subject, $nth){
  $match_arr = explode($search,$subject);
  $match_arr = array_filter($match_arr);

   foreach($match_arr as $key=>$val){

      if($key == $nth-1){ // array index start with Zero
        $match_arr[$key] .=  $replace;
      }else{
        $match_arr[$key] .=  '?';
      }

   }
   return implode('',$match_arr);
}

Comments

0

None of your solutions worked for me, so I made this:

$sql1 = "SELECT * FROM allegro_user WHERE User_Emp_Nb = ? AND User_Activ_status = ?";
$sql2 = "SELECT * FROM allegro_user WHERE User_Emp_Nb = :emp_nb AND User_Activ_status = :activ";

function prepare_query($sql, $args) {
    foreach ($args as $key => $value) {
        if (is_numeric($key)) {
            $sql = preg_replace('/\?/', "'" . $value . "'", $sql, 1);
        } else {
            $sql = str_replace($key, "'" . $value . "'", $sql);
        }
    }
    return $sql;

}

tab($sql1);
$sql = prepare_query($sql1, array('0216313', 'A'));
tab($sql1);

tab($sql2);
$sql = prepare_query($sql2, array(':emp_nb' => '0216313', ':activ' => 'A'));
tab($sql2);

tab() is just a function I use for printing :

echo '<pre>';
print_r($tab);
echo '</pre>';

Comments

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.