When I call a function of another class (in a included file), some text is being output with echo. I need to store this in a variable.
Here is the code:
require_once('../restapis/api.php');
class ApiTest
{
public function testapis(){
$api = new Api();
$api->validate_request();
}
}
$obj = new ApiTest();
$obj->testapis();
And I am getting a JSON string echoed in browser:
{"ERRORCODE":"E032","ERRORMESSAGE":"Invalid URL."}
I don't have permission to change anything in the api.php file, that's why I can't change echo to return.
Is there any way I can do this?
You could use output buffering.
ob_start(); // Activate output buffering
$obj->testapis(); // Whatever code whose output you want to capture
$contents = ob_get_contents(); // Store buffered contents
ob_end_clean(); // Deactivate output buffering
After that, $contents will contain the echoed output.
Related
So I have a case were I need to interpret a PHP file and then put it in a variable as a string.
I have this some what common helper function to do this:
function ob ($path) {
ob_start();
include($path);
$string = ob_get_contents();
ob_end_clean();
return $string;
}
Just give it the path and it will give you the string after it has been interpreted. Works great.
However I also need to send it a variable. I tried just appending a GET request string to the path, but it appeared not to work. The function prototype would look like this:
// how would I implement this?
function ob ($path, $variable_to_send) {
}
How should I do this?
Simply use a global variable.
Set it in one file like this:
$GLOBALS['arg'] = 'test';
Access it in another file similarly:
$arg_passed = $GLOBALS['arg'];
If you wanted to architect this a bit more use the registry pattern.
Note this assumes that this is the same HTTP request. If you need persistence across HTTP requests use session variables.
Let the external script is external.php:
<?php
echo $argument;
?>
and the caller scrip is caller.php (on the same folder of external.php):
<?php
function ob ($path, $argument) {
ob_start();
include($path);
$string = ob_get_contents();
ob_end_clean();
return $string;
}
$out = ob("external.php","Ciao");
echo "$out Cade";
?>
The result will be:
Ciao Cade
http://tinypic.com/r/2mn0pph/8
This happens when I do
<?php
require('page.inc');
$homepage = new Page();
$homepage->content = include 'project.php';
$homepage->Display();
?>
But if I do this:
<?php
require('page.inc');
$homepage = new Page();
$homepage->content = "Hello, stackoverflow!";
$homepage->Display();
?>
It does what is intend here
http://tinypic.com/r/1214vbt/8
Is there something special I should do to the include statement to get all the content between the lines?
Use output buffering to catch the generated HTML:
<?php
require('page.inc');
$homepage = new Page();
ob_start();
require 'project.php';
$homepage->content = ob_get_clean();
$homepage->Display();
?>
This way, the PHP is executed, but there's no output to the browser. Instead you'll catch the buffered content in $homepage->content.
From the PHP documentation:
The include statement includes and evaluates the specified file.
Include doesn't not return the text it outputs:
Handling Returns: include returns FALSE on failure and raises a warning. Successful includes, unless overridden by the included file, return 1. It is possible to execute a return statement inside an included file in order to terminate processing in that file and return to the script which called it.
This is what you want:
<?php
require('page.inc');
$homepage = new Page();
$homepage->content = file_get_contents('project.html');
$homepage->Display();
?>
From the PHP documentation
file_get_contents() returns the file in a string
As it was mentioned by #lxg:
"I would assume that project.php contains PHP code to be executed. In this case, file_get_contents('project.php'); would be a bad idea."
I am trying to dynamically echo some predefined template ('template-file-for-output.php') filled with some data (from the $var array) on a specific place in a number of pages (as an example, the page 'page.php').
Basically my goal is to have a system, in which
I set up the logic (in the 'logic.php' file), the functions needed (in 'functions.php'), the template (in 'template-file-for-output.php')
with which my colleagues can create whatever page (just as in 'page.php' for the sake of the example) they want with their content and their HTML as they wish and only need to include the functions.php and logic.php files at the beginning of their file, and the echo statement to have the dynamic content where they want it to appear.
The problem I'm having is that when I test this example and try to achieve this in 'page.php', I always get the content before the custom HTML from the page. I suppose it has to do with output buffering and this include in the outputContent function, I tried other things but without success.
Here the contents of the files:
logic.php:
$submitOK = false;
if ($submitOK === true) {
/** No errors, output the error free content */
$output = outputContent($var);
} else {
/** Errors, output the content with errors */
$output = outputContent($var, $errors);
}
functions.php:
function outputContent($var, $errors = null)
{
extract($var);
ob_start();
include 'template-file-for-output.php';
$output = ob_get_contents();
ob_get_clean();
return $output;
}
template-file-for-output.php:
<p>Some content with tags and so on, filled in by some values of the $var array.</p>
<p>Example with the $example variable extracted from $var <?php echo $example; ?></p>
<p>Another variable also from $var <?php echo $anotherVariable; ?>
page.php:
<?php
include 'logic.php';
include 'functions.php';
?>
<!DOCTYPE html>
<html>
<head><title>A page of the site</title></head>
<body>
<p>Something interesting (hopefully).</p>
<?php echo $output; ?>
</body>
</html>
Change ob_get_contents to ob_get_clean, ob_get_contents gets the contents of the buffer but leaves it intact. Your Previous code got the buffer assigned it a variable then, flushed the buffer to output.
function outputContent($var, $errors = null)
{
extract($var);
ob_start();
include 'template-file-for-output.php';
$output = ob_get_clean();
return $output;
}
Setting aside the point that there are currently templating systems that have already solved this problem quite effectively ...
I would try not include the template file, but rather read the file with file_get_contents and then echo it out inside the output buffering section.
function outputContent($var, $errors = null)
{
extract($var);
ob_start();
echo file_get_contents('template-file-for-output.php');
$output = ob_get_clean();
return $output;
}
I have an output buffer with callback function. When cleaning the buffer the callback function is executed, however, the string returned isn't being altered.
I'm using following code:
<?php
ob_start('callback');
print 'some text';
error_log(ob_get_clean());
function callback($content) {
error_log('callback');
return $content . ' altered';
}
Output:
callback
some text
What I want:
callback
some text altered
What am I missing? I'm using PHP 5.3.10 in CLI.
Edit: the callback is being executed.
From the PHP manual:
The function will be called when the output buffer is flushed (sent)
or cleaned (with ob_flush(), ob_clean() or similar function) or when
the output buffer is flushed to the browser at the end of the request.
I'm not sure if this is a bug or a feature. Looking at the PHP source code, I found that the return value of ob_get_clean is filled before the callback is invoked.
I see at least two workarounds. The first is to manually invoke the callback on the output string yourself. I think this needs no example.
The second is to exploit the possibility to stack output buffering. Since flushing successfully uses the callback, you can wrap the output code inside an additional output buffer and get the modified contents.
ob_start();
function callback($input) { return $input . " altered"; }
ob_start('callback');
echo "foo";
ob_end_flush();
$content = ob_get_clean();
ob_end_clean();
echo $content . "\n"; // prints "foo altered\n"
See the source code for ob_get_clean (main/output.c) if you're curious. You can get the source code at the PHP website. Here are some pointers.
/* {{{ proto bool ob_get_clean(void)
Get current buffer contents and delete current output buffer */
PHP_FUNCTION(ob_get_clean)
{
if (zend_parse_parameters_none() == FAILURE) {
return;
}
// THIS CALL FILLS THE RETURN VALUE
if (php_ob_get_buffer(return_value TSRMLS_CC) == FAILURE) {
RETURN_FALSE;
}
if (!OG(ob_nesting_level)) {
php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer. No buffer to delete");
zval_dtor(return_value);
RETURN_FALSE;
}
if (OG(ob_nesting_level) && !OG(active_ob_buffer).status && !OG(active_ob_buffer).erase) {
php_error_docref("ref.outcontrol" TSRMLS_CC, E_NOTICE, "failed to delete buffer %s", OG(active_ob_buffer).handler_name);
zval_dtor(return_value);
RETURN_FALSE;
}
// THIS CALL KILLS THE CURRENT BUFFER AND EXECUTES THE CALLBACK
php_end_ob_buffer(0, 0 TSRMLS_CC);
}
/* }}} */
php_end_ob_buffer takes the contents of the OB buffer and applies the callback to it. If the first parameter is true, it passes the contents to the next output buffering handler. In this case it's false, so the content is lost even though it executed the callback.
If i had a guess it would be this.
ob_get_clean() is returning the result of the buffer, and THEN cleaning it, triggering the callback which modifies the content.
IE
'some text' is extracted from the buffer and prepared to be returned as per the requirement of the 'get' functionality.
Next, the buffer is cleaned, but before cleaning the callback is triggered against the content, as per the requirement for various ob functions when a callback is present.
The result is that the buffer is returned (as requested) but it is modified after, since the get happens before the clean.
It will be called when buffer is flushed:
ob_start('callback');
print 'some text';
ob_end_flush();
function callback($content) {
return $content . ' altered';
}
P.S.
it works in CLI too.
The CLI for PHP does not use output buffering (or more specifically the buffing is not related to the ob_ functions). So your callback is being skipped.
EDIT: Actually I'm having trouble confirming whether standard output buffering is available at the CLI. I would try ob_end_flush(), ob_flush(), and flush().
I remove ob_get_clean and your code does work.
ob_start('callback');
print 'some text';
//error_log(ob_get_clean());
$buffer = ob_get_flush();
function callback($content) {
return $content . ' altered';
}
I've check the output and it was some text alerted.
why you use ob_get_clean() method? it cleans the buffer.
<?php ob_start('callback'); ?>
Foo Bar Baz
<?php
ob_end_flush();
function callback($content) {
$find = "Baz";
$replace_with = "Foo";
return (
str_replace($find, $replace_with, $content)
);
}
?>
I've got a script that runs a custom email obfuscation class's Obfuscate() function on the content before displaying it, as follows:
ob_start(array($obfuscator, "Obfuscate"));
include('header.php');
print($html);
include('footer.php');
ob_end_flush();
That all works great. However, I've completely rewritten my view architecture, so I need to run the email obfuscation from within a class function and return that string (which then gets echoed). I initially rewrote the above as:
ob_start(array($this->obfuscator, "Obfuscate"));
include('header.php');
echo($this->content);
include('footer.php');
$wrappedContent = ob_get_contents();
ob_end_clean();
Unfortunately, the $this->obfuscator->Obfuscate() callback is not being fired. I have since learned that ob_get_contents() does not fire the callback, but have tried ob_get_clean() & ob_get_flush() to no avail as well.
So, how can I get the contents of the buffer after the callback has been fired?
Of course, I was overlooking the fact that the only reason to use the callback on ob_start() was because I wanted to run Obfuscate() on the content before it was flushed, but if I'm getting that content back I don't need to run a callback! So, not using a callback and just running ob_get_clean()'s results through Obfuscate() does what I wanted. Doh!
ob_start();
include('header.php');
echo($this->content);
include('footer.php');
return $this->obfuscator->Obfuscate(ob_get_clean());
Change
ob_end_clean();
with
ob_clean()
Will trigger .
This is the code eg I tried
<?php
class Obfuscate {
public function __construct()
{
}
public function getObfuscate()
{
return "obfuscate";
}
}
class Example
{
public function hello( $obfuscator )
{
ob_start(array( $obfuscator, 'getObfuscate' ));
include('header.php');
echo "Thi is a content ";
include('footer.php');
$wrappedContent = ob_get_contents();
ob_clean();
}
}
$obfuscator = new Obfuscate();
$example = new Example;
$example->hello($obfuscator);
ob_clean();