Convert PHP closing tag into comment

  • Added:
  • |
  • In: Basic PHP

One of the lines in my script contains a PHP closing tag inside a string. Under normal operation this does not cause a problem, but I need to comment out the line.

I have tried to comment out this line with //, /* */ and # but none of them work, the parser considers closing tag to be an actual closing tag.

Here is the line in question:

$string = preg_replace('#<br\s*/?>(?:\s*<br\s*/?>)+#i', '<br />', $string);
//                              ^^             ^^

What can I do to comment out the above line?

This Question Has 6 Answeres | Orginal Question | v1n_vampire

Why your attempts didn't work:

// $string = preg_replace('#<br\s*/?>(?:\s*<br\s*/?>)+#i',...
                                   ^ doesn't work due to ?> ending php

/* $string = preg_replace('#<br\s*/?>(?:\s*<br\s*/?>)+#i',... */
                                 ^ doesn't work due to */ closing comment

What works:

/* $string = preg_replace('#<br\s*[/]?>(?:\s*<br\s*[/]?>)+#i',... */
                                  ^ ^              ^ ^
// $string = preg_replace('#<br\s*/?[>](?:\s*<br\s*/?[>])+#i',...
                                    ^ ^              ^ ^


After the above, you should be able to use /* to comment out the line. If you leave the ?> intact, // cannot possibly comment out an entire line. The text following ?> could be html, which is outside the control of the PHP interpreter, so that wouldn't work.

From the documentation:

The "one-line" comment styles only comment to the end of the line or the current block of PHP code, whichever comes first. This means that HTML code after // ... ?> or # ... ?> WILL be printed: ?> breaks out of PHP mode and returns to HTML mode, and // or # cannot influence that.

The easiest way

Create a separate variable to hold your regular expression; this way you can simply comment out the preg_replace() statement:

$re = '#<br\s*/?>(?:\s*<br\s*/?>)+#i';
// $string = preg_replace($re, '<br />', $string);

Fix using character classes

To fix line comments, you can break up ?> by putting > inside a character class like so:

$string = preg_replace('#<br\s*/?[>](?:\s*<br\s*/?[>])+#i', '<br />', $string);
                                 ^ ^              ^ ^

To fix block comments, you can apply it to /:

$string = preg_replace('#<br\s*[/]?>(?:\s*<br\s*[/]?>)+#i', '<br />', $string);
                               ^ ^              ^ ^

To fix both comment styles, you can put / and > in their own character class.

Fix using the /x modifier

The x modifier - aka PCRE_EXTENDED - ignores spaces and newlines in a regular expression (except when they occur inside a character class); this makes it possible to add spaces to separate the problematic characters. To fix both comment styles:

$string = preg_replace('#<br\s* /? >(?:\s*<br\s* /? >)+#ix', '<br />', $string);
                               ^  ^             ^  ^

Use a trick: concatenate the string from two pieces. This way, the closing tag is cut in two, and is not a valid closing tag anymore. '?>' --> '?'.'>'

In your code:

$string = preg_replace('#<br\s*/?'.'>(?:\s*<br\s*/?'.'>)+#i', '<br />', $string);

This will make // comments work.

For /* */ comments to work, you'd have to split the */ sequence too:

$string = preg_replace('#<br\s*'.'/?'.'>(?:\s*<br\s*'.'/?'.'>)+#i', '<br />', $string);

Remember, sometimes, even though the whole is more than the sum of its parts - but being greedy is bad, there are times you are better left with less. :)

Why use complicated, difficult to read "tricks" to work around the problem?

? is just a quantifier shortcut for convenience, so

Just use the long version of the quantifier {0,1}, means "minimum 0 maximum 1 occurrence":

$string = preg_replace('#<br\s*/{0,1}>(?:\s*<br\s*/{0,1}>)+#i', '<br />', $string);

A few other ways worth adding to the RegEx trick book:

First you could compact your RegEx to: /(<br\s*/?>)+/i and replace with <br /> (no need to burden the RegExP with lookaheads) and you'll always end up with your chosen XHMTL line break.

Other ways to modify your RegEx so it won't trip */ end comment or ?> end script:

  • Use possessive quantifiers : #(<br\s*+/?+>)+#i - which basically mean for \s*+ if you found whitespace match as many as there are and keep it, and for /?+ if you found a slash keep it!
  • Enclose \s* and /* in capture groups => #(<br(\s*)(/?)>)+#i

Live demos:

And since we leaned the possessive behavior the fastest RegEx that also bypasses the commenting problem is: #(<br\s*+/?+>)++#i explained demo

As for commenting in tricky situations

When you can't change the code, or have already used a multiline comment and:

1. Use a nowdoc:

$string='Hello<br>World<br><br />World<br><br><br>Word!';
    $string = preg_replace('#(<br\s*/?>)+#i', '<br />', $string);

Live code:

Note: a nowdoc is similar to a heredoc but it does not parse the content and has to have it's starting delimiter enclosed in 'single quotes' (note that the ending delimiter can't be idented, must be followed by ; and a new line !)

2. Jump over the code with a goto:

$string='Hello<br>World<br><br />World<br><br><br>Word!';
goto landing;
$string = preg_replace('#(<br\s*/?>)+#i', '<br />', $string);

Live example:

3. Jump over the code with if(false) or if(0):

$string='Hello<br>World<br><br />World<br><br><br>Word!';
$string = preg_replace('#(<br\s*/?>)+#i', '<br />', $string);


Another idea: Escape the > (and the /, if you want to use a /*...*/ comment):

$string = preg_replace('#<br\s*\/?\>(?:\s*<br\s*\/?\>)+#i', '<br />', $string);

An "unnecessary" escape is ignored by the regex engine, but is useful in this case (for reasons outlined in the other answers).

Meet with owner

Sajjad Hossain

Hey, I am Sajjad, working in web development sector since 2012. I love to do amazing things. Let's do a project together.
Connect Social With PHPAns