I have a file like this
**buffer.php**
ob_start();
<h1>Welcome</h1>
{replace_me_with_working_php_include}
<h2>I got a problem..</h2>
ob_end_flush();
Everything inside the buffer is dynamically made with data from the database.
And inserting php into the database is not an option.
The issue is, I got my output buffer and i want to replace '{replace}' with a working php include, which includes a file that also has some html/php.
So my actual question is: How do i replace a string with working php-code in a output-buffer?
I hope you can help, have used way to much time on this.
Best regards - user2453885
EDIT - 25/11/14
I know wordpress or joomla is using some similar functions, you can write {rate} in your post, and it replaces it with a rating system(some rate-plugin). This is the secret knowledge I desire.
You can use preg_replace_callback and let the callback include the file you want to include and return the output. Or you could replace the placeholders with textual includes, save that as a file and include that file (sort of compile the thing)
For simple text you could do explode (though it's probably not the most efficient for large blocks of text):
function StringSwap($text ="", $rootdir ="", $begin = "{", $end = "}") {
// Explode beginning
$go = explode($begin,$text);
// Loop through the array
if(is_array($go)) {
foreach($go as $value) {
// Split ends if available
$value = explode($end,$value);
// If there is an end, key 0 should be the replacement
if(count($value) > 1) {
// Check if the file exists based on your root
if(is_file($rootdir . $value[0])) {
// If it is a real file, mark it and remove it
$new[]['file'] = $rootdir . $value[0];
unset($value[0]);
}
// All others set as text
$new[]['txt'] = implode($value);
}
else
// If not an array, not a file, just assign as text
$new[]['txt'] = $value;
}
}
// Loop through new array and handle each block as text or include
foreach($new as $block) {
if(isset($block['txt'])) {
echo (is_array($block['txt']))? implode(" ",$block['txt']): $block['txt']." ";
}
elseif(isset($block['file'])) {
include_once($block['file']);
}
}
}
// To use, drop your text in here as a string
// You need to set a root directory so it can map properly
StringSwap($text);
I might be misunderstanding something here, but something simple like this might work?
<?php
# Main page (retrieved from the database or wherever into a variable - output buffer example shown)
ob_start();
<h1>Welcome</h1>
{replace_me_with_working_php_include}
<h2>I got a problem..</h2>
$main = ob_get_clean();
# Replacement
ob_start();
include 'whatever.php';
$replacement = ob_get_clean();
echo str_replace('{replace_me_with_working_php_include}', $replacement, $main);
You can also use a return statement from within an include file if you wish to remove the output buffer from that task too.
Good luck!
Ty all for some lovely input.
I will try and anwser my own question as clear as I can.
problem: I first thought that I wanted to implement a php-function or include inside a buffer. This however is not what I wanted, and is not intended.
Solution: Callback function with my desired content. By using the function preg_replace_callback(), I could find the text I wanted to replace in my buffer and then replace it with whatever the callback(function) would return.
The callback then included the necessary files/.classes and used the functions with written content in it.
Tell me if you did not understand, or want to elaborate/tell more about my solution.
Related
I am trying to loop through all the php files listed in an array called $articleContents and extract the variables $articleTitle and $heroImage from each.
So far I have the following code:
$articleContents = array("article1.php", "article2.php"); // array of all file names
$articleInfo = [];
$size = count($articleContents);
for ($x = 0; $x <= $size; $x++) {
ob_start();
if (require_once('../articles/'.$articleContents[$x])) {
ob_end_clean();
$entry = array($articleContents[$x],$articleTitle,$heroImage);
array_push($articlesInfo, $entry);
}
The problem is, the php files visited in the loop have html, and I can't keep it from executing. I would like to get variables from each of these files without executing the html inside each one.
Also, the variables $articleTitle and $heroImage also exist at the top of the php file I'm working in, so I need to make sure the script knows I'm calling the variables in the external file and not the current one.
If this is not possible, can you please recommend an alternative method?
Thanks!
Don't do this.
Your PHP scripts should be for your application, not for your data. For your data, if you want to keep it file-based, use a separate file.
There are plenty of formats to choose from. JSON is quite popular. You can use PHP's built-in serialization as well, which has support for more PHP-native types but is not as portable to other frameworks.
A little hacky but seems to works:
$result = eval(
'return (function() {?>' .
file_get_contents('your_article.php') .
'return [\'articleTitle\' => $articleTitle, \'heroImage\' => $heroImage];})();'
);
Where your_article.php is something like:
<?php
$articleTitle = 'hola';
$heroImage = 'como te va';
The values are returned in the $result array.
Explanation:
Build a string of php code where the code in your article scripts are wrapped inside a function that returns an array with the values you want.
function() {
//code of your article.php
return ['articleTitle' => $articleTitle, 'heroImage' => $heroImage];
}
Maybe you must do some adaptations to the strings due <?php ?> tags placements.
Anyway, this stuff is ugly. I'm very sure that it can be refactored in some way.
Your problem (probably) comes down to using parentheses with require. See the example and note here.
Instead, format your code like this
$articlesInfo = []; // watch your spelling here
foreach ($articleContents as $file) {
ob_start();
if (require '../articles/' . $file) { // note, no parentheses around the path
$articlesInfo[] = [
$file,
$articleTitle,
$heroImage
];
}
ob_end_clean();
}
Update: I've tested this and it works just fine.
In my view I have this code:
{{L::getSomeContent('content')}}
This method returns content from the database. My question is, is it possible to return and render Blade straight from the database? For example, I have stored in the database:
<img src"{{asset('somepath')}}">
But when rendering this data straight from the database, it will just show like '%7%7'
I have tried Blade::compileString
I hate to suggest this, but eval would work in this case. Before you use this, you have to make sure that the content you pass to it isn't user input. And if it is you have to sanitize it (or trust the user, if the content can be changed in some kind of admin tool)
Instead of using this method you should maybe thinking of some other way to organize your content. For paths you could use a placeholder and just do a string replace before outputting.
Anyhow, be warned: eval() will execute any PHP code that's passed.
Here's a working example. Of course you put that in some kind of helper function to not clutter your view code, but I'll leave that to you.
<?php
$blade = L::getSomeContent('content');
$php = Blade::compileString($blade);
// remove php brackets because eval() doesn't like them
$php = str_replace(['<?php', '?>'], '', $php);
echo eval($php);
?>
As I already mentioned for this particular case (a path to an asset) you could use a placeholder in your content. For example:
Stored in the database
<img src"%ASSET%some/path">
And then inside a helper function and before output, just replace it with the real path:
$content = L::getSomeContent('content');
$html = str_replace('%ASSET%', asset(''), $content);
I found the answer in the comments #blablabla :
protected function blader($str, $data = array())
{
$empty_filesystem_instance = new Filesystem;
$blade = new BladeCompiler($empty_filesystem_instance, 'datatables');
$parsed_string = $blade->compileString($str);
ob_start() and extract($data, EXTR_SKIP);
try {
eval('?>' . $parsed_string);
}
catch (\Exception $e) {
ob_end_clean();
throw $e;
}
$str = ob_get_contents();
ob_end_clean();
return $str;
}
This part seems to be working fine:
Blade::compileString($yourstring);
eval('?>' . $yourstring);
I am trying to keep my code clean break up some of it into files (kind of like libraries). But some of those files are going to need to run PHP.
So what I want to do is something like:
$include = include("file/path/include.php");
$array[] = array(key => $include);
include("template.php");
Than in template.php I would have:
foreach($array as $a){
echo $a['key'];
}
So I want to store what happens after the php runs in a variable to pass on later.
Using file_get_contents doesn't run the php it stores it as a string so are there any options for this or am I out of luck?
UPDATE:
So like:
function CreateOutput($filename) {
if(is_file($filename)){
file_get_contents($filename);
}
return $output;
}
Or did you mean create a function for each file?
It seems you need to use Output Buffering Control -- see especially the ob_start() and ob_get_clean() functions.
Using output buffering will allow you to redirect standard output to memory, instead of sending it to the browser.
Here's a quick example :
// Activate output buffering => all that's echoed after goes to memory
ob_start();
// do some echoing -- that will go to the buffer
echo "hello %MARKER% !!!";
// get what was echoed to memory, and disables output buffering
$str = ob_get_clean();
// $str now contains what whas previously echoed
// you can work on $str
$new_str = str_replace('%MARKER%', 'World', $str);
// echo to the standard output (browser)
echo $new_str;
And the output you'll get is :
hello World !!!
How does your file/path/include.php look like?
You would have to call file_get_contents over http to get the output of it, e.g.
$str = file_get_contents('http://server.tld/file/path/include.php');
It would be better to modify your file to output some text via a function:
<?php
function CreateOutput() {
// ...
return $output;
}
?>
Than after including it, call the function to get the output.
include("file/path/include.php");
$array[] = array(key => CreateOutput());
Quite simple question i belive. How to print the whole page into variable and then use where i need.
For instance if the code is:
<?php
$arr = array('hello','mate','world');
foreach ($arr as $a) {print "<p>".$a."</p>"; }
?>
Now if we go to that page, we can see an array output, but i would prefer to print the whole page into variable and then generate static page for instance out of that.
Maybe file_get_content or <<<EOT, but the page will get more complicated later so not sure what is the best option.
Not sure about your exact needs but:
ob_start();
require('/path/to/templates/foo.php');
$template = ob_get_contents();
ob_get_clean();
ob_start();
// your code
$var = ob_get_clean();
print $var;
Why don't you use smarty ,
put all HTML in a template , and insert PHP code or variables into it . in the end , using $x=$smarty->fetch('template_name'); you put all the page in the $x variable ...
I have this code:
$layout_template = template_get("Layout");
$output_template = template_get("Homepage");
$box = box("Test","Test","Test");
eval("\$output = \"$layout_template\";");
echo $output;
In the $template_layout variable is a call for the
variable $output_template, so then the script moves onto the $output_template variable
But it doesn't go any further, inside the $output_template is a call to the variable $box, but it doesn't go any further than one level
I would never want nested eval(), and especially not in any recursive logic. Bad news. Use PHP's Include instead. IIRC eval() creates a new execution context, with overhead whereas include() doesn't.
If you have buffers such as:
<h1><?php echo $myCMS['title']; ?></h1>
I sometimes have files like Index.tpl such as above that access an associative array like this, then you just do in your class:
<?php
class TemplateEngine {
...
public function setvar($name, $val)
{
$this->varTable[$name]=make_safe($val);
}
....
/* Get contents of file through include() into a variable */
public function render( $moreVars )
{
flush();
ob_start();
include('file.php');
$contents = ob_get_clean();
/* $contents contains an eval()-like processed string */
...
Checkout ob_start() and other output buffer controls
If you do use eval() or any kind of user data inclusion, be super safe about sanitizing inputs for bad code.
It looks like you are writing a combined widget/template system of some kind. Write your widgets (views) as classes and allow them to be used in existing template systems. Keep things generic with $myWidget->render($model) and so on.
I saw this on the PHP doc-user-comments-thingy and it seems like a bad idea:
<?php
$var = 'dynamic content';
echo eval('?>' . file_get_contents('template.phtml') . '<?');
?>
Perhaps someone can enlighten me on that one :P