preg_replace_callback does not work

Asked

Viewed 158 times

0

I’m trying to replace a variable with preg_replace_callback, but I’m not succeeding, does anyone know where the error is??

 $replacements = array(
                '[PEDIDO]' => $oID,
                '[NOME]' => $order->customer['name'],
                '[VALOR]' => $order->totals['ot_subtotal'],
                '[FRETE]' => $order->totals['ot_shipping'],
                '[DESCONTO]' => $order->totals['ot_payment'],
                '[TOTAL]' => $order->totals['ot_total'],
            );

 $msg = preg_replace_callback('/[\w+]/', 
                        create_function('$matches',
                          'return $replacements[$matches[0]];'
                    , $m['msg']));

3 answers

2


Good that solved, but I need to consider some points and even explain why your code didn’t work as you expected.

create_function() is not only a dangerous resource because it is subject to all security issues related to evil val(), as it is also bad performance.

Not to mention that Closures were introduced as an alternative in PHP 5.3 released in June 2009 (more than 5 years ago). I strongly suggest an upgrade.

Also, whenever possible, consider nay use Ers. If you don’t have any regular pattern, as you yourself solved, working directly with the strings is much easier (and fast).

But the reason it didn’t work, hereafter of two syntax errors, since create_function() expects two and not three arguments and preg_replace_callback() wait three and not two, And of the lack of leakage of the brackets as pointed out by @Jader, you suffered from the old case of Scope of Variables.

Despite create_function return a string, to preg_replace_callback() she is a callable. Not that create_function returns a function, but it is interpreted as one and is therefore subject to local and global "restrictions".

In short:

$order = "Pedido: [PEDIDO]\nNome: [NOME]\nValor: [VALOR]\nFrete: [FRETE]\n Desconto: [DESCONTO]\nTotal: [TOTAL]";

$replacements = array(
                '[PEDIDO]' => 123,
                '[NOME]' => 'Bruno Augusto',
                '[VALOR]' => 69.00,
                '[FRETE]' => 0,
                '[DESCONTO]' => 69.00,
                '[TOTAL]' => 'It\'s FREE!',
            );

  $order = preg_replace_callback(

          '/\[\w+\]/', // Colchetes escapados

          create_function(

               // Variável globalizada

              '$matches', 'global $replacements; return $replacements[$matches[0]];'
          ),

          // Número de argumentos corrigido

          $order
);

Would return, as expected:

Order: 123 Name: Bruno Augusto Price: 69 Shipping: 0 Discount: 69 Total: It’s FREE!

1

That’s how it worked right here:

$replacements = array(
                '[PEDIDO]' => $oID,
                '[NOME]' => $order->customer['name'],
                '[VALOR]' => $order->totals['ot_subtotal'],
                '[FRETE]' => $order->totals['ot_shipping'],
                '[DESCONTO]' => $order->totals['ot_payment'],
                '[TOTAL]' => $order->totals['ot_total'],
            );

   $msg = preg_replace_callback('/\[\w+\]/', 
                        function ($matches) {
                            global $replacements;
                            return $replacements[$matches[0]];
                        }
                    , $m['msg']);
  • not here, and I have to use create_function because of the php version

  • I’m on my cell right now... Put the global before the Return and check the closing of the create_function, you are closing there at the end and must close before the comma.

  • I decided to change the function of that keep breaking the head, thanks for the help

  • I am glad that you were able to solve it. But I forgot to say that your regex was also wrong, the [ ]...

  • 1

    If you’re gonna use Closures don’t use global. Prefer the use() ;)

0

The solution for me was to change the way I was doing so I didn’t waste any more time.

$in = array('[PEDIDO]','[NOME]','[VALOR]','[FRETE]','[DESCONTO]','[TOTAL]');
$out = array($oID, $order->customer['name'],$order->totals['ot_subtotal'],$order->totals['ot_shipping'],$order->totals['ot_payment'],$order->totals['ot_total']);  

$msg = str_replace($in, $out, $m['msg']);

It’s there to help someone.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.