|
preg_replace_callback
Perform a regular expression search and replace using a callback
(PHP 4 >= 4.0.5, PHP 5)
Example 1723. preg_replace_callback() and create_function()<?php Example 1724. preg_replace_callback() example<?php The above example will output: April fools day is 04/01/2003 Example 1725. preg_replace_callback() using recursive structure to handle encapsulated BB code<?php Code Examples / Notes » preg_replace_callbackvlad4321
You can use this function to display url address as a link or image based on suffix of the url. Every string beginning with www or http(s):// will be displayed as an URL address. But if the string ends with *.jpg or *.gif, it will be displayed as an image. Please note: This function also verifies the size of the image. If is it more than 600x400, it changes it. <?php $pattern_html = "/\b((http(s?):\/\/)|(www\.))([\w\.]+)"; $pattern_html .= "([\#\,\/\~\?\&\=\;\%\-\w+\.]+)\b/i"; $text = preg_replace_callback($pattern_html,'Check_if_Image',$text); . . function Check_if_Image($matches) { $suffix = strtolower(substr($matches[0],-4)); if ( $suffix == '.jpg' or $suffix == '.gif') { $dsn = 'http'.$matches[3].'://'.$matches[4].$matches[5]; if (list($width, $height, $type, $attr) = getimagesize("$dsn")) { if ( ($width > 600) ) { $koef = $width / 600; $width = 600; $height /= $koef; } if ( ($height > 400) ) { $koef = $height / 400; $height = 400; $width /= $koef; } } else { $height=400; $width=600; } $ret = "<img src=\"$dsn\""; $ret .= "\" border=0 width=\"$width\" height=\"$height\">"; } else { $ret = '<a href="http'.$matches[3].'://'.$matches[4].$matches[5]; $ret .='" target="_blank">'.$matches[0].'</a>'; } return ("$ret"); } ?> sjon
preg_replace_callback returns NULL when pcre.backtrack_limit is reached; this sometimes occurs faster then you might expect. No error is raised either; so don't forget to check for NULL yourself
sjungwirth domain matrix-consultants com
one way to 'pass' extra info other than just the matches and still use preg_replace_callback is to have your callback function be a class method, and just before you call preg_replace_callback, store the info in that class. I am using static methods/variables for my implementation; I'm not sure if its required. <?php class foo { private static $bar; public static function do_something($bar) { self::$bar = $bar; // store bar $input = $bar->get_somevar(); $pattern = "match me"; $output = preg_replace_callback($pattern, array('self', 'do_something_callback'), $input); return $output; } private static function do_something_callback($matches) { $bar = self::$bar; // retrieve bar // do stuff like $bar->get_someothervar(); return $replacement; } } ?> matt
it is much better on preformance and better practice to use the preg_replace_callback function instead of preg_replace with the e modifier. function a($text){return($text);} // 2.76 seconds to run 50000 times preg_replace("/\{(.*?)\}/e","a('\\1','\\2','\\3',\$b)",$a); // 0.97 seconds to run 50000 times preg_replace_callback("/\{(.*?)\}/s","a",$a); vinyanov
If you want to replace your matches with a unique calculation and you do not want to use: 1. preg_replace() and /e flag* 2. preg_replace_callback() and create_function()** 3. preg_replace_callback() and fill the namespace with an additional function You can insert both call and solution within one function. Then, you may supply callback with the __FUNCTION__ predefined constant, and the function will separate its responsibilities itself by the type of the argument. Since preg_replace_callback() returns an array, this is easy. Quite useless example: <?php function debug($s) { if(is_string($s)) { return preg_replace_callback('/{\?(cl|co|f|i|v)}/', __FUNCTION__, $s); } foreach(array( 'co' =>'nstants', 'f' =>'unctions', 'v' =>'ars', 'cl' =>'asses', 'i' =>'nterfaces', ) as $p[1] => $p[2]) { if($p[1] === $s[1]) { $p[0] = in_array($p[1], array('cl', 'i')) ? 'declared' : 'defined'; $f = vsprintf('get_%3$s_%2$s%1$s', $p); return var_export($f(), 1); } } } echo debug('Variables: {?v} Nothing: {?n} Interfaces: {?i}'); ?> * I do not know whether it evokes eval() or not ** http://tinyurl.com/3azwyy e-mail
If you want to do a date function in a template system you'll have to use the callback here. Ex.: function date_match ($matches) { return date ($matches['2']); } $output = preg_replace_callback ('/({DATE=")(.{1,})("})/', 'date_match', $input); oyoryelnospam
If you want to be able to change variables of the class in the callback function, you have to use preg_replace_callback(pattern, array(&$this, 'method_name'), subject) Probably very obvious, but it kept me busy for a while... spamhoneypot
I thought I'd post this as I'd been using the function preg_replace_callback with NP within functions, but as soon as I re-wrote my script as a class, it all fell apart. When debugging I ended up writing test code and this is what follows. It works as I'd expect, YMMV of course. <?php // v v over simplified class foo { function parse() { $pattern = "/<a(.*?)href\s*=\s*['|\"|\s*](.*?)['|\"|>](.*?)>(.*?)<\/a>/i"; $string = "<a class='whatever' href='http://foo.com' target='_blank'>foo</a>"; print preg_replace_callback($pattern,array($this,'cb'),$string); } function cb($matches) { return "<a" . $matches[1] . "href='http://someothersite.com/foo.php?page=" . urlencode($matches[2]) . "'" . $matches[3] . ">" . $matches[4] . "</a>"; } } $bar = new foo(); $bar->parse(); /** output is <a class='whatever' href='http://someothersite.com/foo.php?page=http%3A%2F%2Ffoo.com' target='_blank'>foo</a> */ ?> ak
Add this snippet to your callback function to make sure you don't replace HTML code. Useful when searching / replacing / highlighting HTML. Change 90 to whatever threshold you need if you have extra extra long tags for some weird reason (lots of inline styles?) function scanForTags($position, $maintext) { for($i = 1;$i < 90; $i++) { if($maintext{$position-$i} == "<" || $maintext{$position+$i} == ">") return true; if($maintext{$position-$i} == ">" || $maintext{$position+$i} == "<") return false; } return false; } roytam
> sjungwirth domain matrix-consultants com It may fail in nested condition if $bar needs to be changed. |