Home > database >  Output buffering doesn't write PHP within HTML code when creating a new PHP file
Output buffering doesn't write PHP within HTML code when creating a new PHP file

Time:08-16

I have a form that sends some data to my database after submission. Also, when the button is clicked PHP code creates a new PHP page (it should display the same content that was just uploaded to the database). Everything works fine (data is sent, the file is created), but the content is in a form of normal text, not PHP code. I think that seeing the code and the output will explain this better:

// some PHP code that sends data to the database (not important and too much code to write)
// here is the code for creating the page (note: VERY simplified)

<?php

$filename = "../Recipes/".$_POST["name"].".php"; // input from the HTML form
$recipefile = fopen($filename, "w") or die("Unable to open file!");

ob_start();
?>

<!doctype html>
<html>
<head>
</head>
<body>
  
  <?php
  function display(){
    $con = mysqli_connect("localhost", "root", "", "cookbook");

    $product = "pizza";
    $sql = "SELECT * FROM product WHERE name = '$product'";
    $res = mysqli_query($con,$sql);

    while($row = mysqli_fetch_assoc($res)) {
        $name = $row['name'];
        $description = $row['description'];

        echo $name;
        echo "<br>";
        echo $description;
        echo "<br>";
    }

    mysqli_close($con);
  }

  if ($_SERVER['REQUEST_METHOD'] === 'POST'){ 
      display(); 
  }                    
        
  ?>

</body>
</html>

<?php
$pagecode = ob_get_clean();
ob_flush();

fwrite($recipefile, $pagecode);
fclose($recipefile);
?>

I know that $product = "pizza"; is not dynamic, it's just a placeholder. I want to solve this problem first. This is what my "pizza.php" file looks like:

// pizza.php
<!doctype html>
<html>
<head>
</head>
<body>
  pizza<br>This is a very good pizza<br>
</body>
</html>

The output should have the whole PHP code inside the body (display() function), not just the text output. I hope that everything is easy to understand.

How can I make this work?

CodePudding user response:

The output buffer catches all output (echo, print, writes to stdout) after it. It doesn't disable the PHP's interpreter.

You have multiple options. For example:

1. Wrap the <?php tag.

<body>
  
  <?php echo '<?php'; ?>
  function display(){
  ...
  }
  <?php echo '?>'; ?>

</body>
</html>

This will run some PHP code that writes the string <?php. As you've noticed, you can run <?php ... ?> so that echo statement will work.

What follows—function display(){—is just plain text as it's not actually between <?php ... ?> tags at the moment, so PHP's engine ignores it.

Putting those values in variables and using short tags might make it easier to read:

$open = '<?php';
$close = '?>';

...

<?=$open?>
  function display(){
  ...
  }
<?=$close?>

2. Put the template in a separate file.

No need for an output buffer here.

$pagecode = file_get_contents('my-template-file.php');
fwrite($recipefile, $pagecode);

file_get_contents returns a plain string, as opposed to include.

3. Stop the PHP engine.

Note: Just because you can, doesn't mean you should (see below).

If you:

  • don't want to obscure the <?php tags (for example because you want your your editor to check or color highlight the syntax) and
  • you want to keep the code in one single file

then you can have PHP stop interpreting the rest of a file by calling __halt_compiler(), but you can't re-start the engine afterwards.

You could solve that problem by:

  1. putting the template at the end of the file,
  2. reading the entire file
  3. then splitting the code from the template.
// Just like the second example, read a PHP file (the current file) as a string.
$contentsOfCurrentFile = file_get_contents(__FILE__);

// Cut at this point.
$pagecode = substr($contentsOfCurrentFile, __COMPILER_HALT_OFFSET__   strlen("?>\n"));

fwrite($recipefile, $pagecode);
fclose($recipefile);

// Below this point will be cut by the code above 
// and then put into variable $pagecode.
// The ?> is not needed here, but we add it here
// (and stripped it) to keep syntax highlighting
// correct.
__halt_compiler();?>
This code is "not seen" by PHP
<?php echo 'Shows up as code in the variable'; ?>

Because __halt_compiler()'s use is rather rare and it can be confusing for other people, I would not recommend you use this.

Putting the code in a separate file like option 2, to me, seems the neatest way to go. You'll keep syntax highlighting in your text editor.

Option 1 leaves you with the option that if you need to, you can still write <?php ... ?> tags to execute code to make parts of the string dynamic.


Perhaps better still is a solution that doesn't need you to write separate files for every page. Why not make 1 file that gets a value (for example, from the URL with $_GET['page']) and loads the relevant content? Look into "rewrites" or "pretty URLs" to transform eg example.com/recipe-1 to example.com/index.php?page=recipe-1.

  • Related