Blade render from database - php

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);

Related

PHP replace {replace_me} with <?php include ?> in output buffer

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.

PHP to text function

I am trying to create a function that would parse php code and return the result in pure text, as if it was being read in a browser. Like this one:
public function PHPToText($data, $php_text) {
//TODO code
return $text;
}
I would call the function like this, with the params that you see below:
$data = array('email' => 'test#so.com');
$string = "<?= " . '$data' . "['email']" . "?>";
$text = $this->PHPToText($data, $string);
Now echo $text should give: test#so.com
Any ideas or a function that can achieve this nicely?
Thanks!
It's a bad bad bad bad bad idea, but basically:
function PHPToText($data, $string) {
ob_start();
eval($string);
return ob_get_clean();
}
You really should reconsider this sort of design. Executing dynamically generated code is essentially NEVER a good idea.
in this case it should be done with eval()
But always remember: eval is evil!
You will need to use the eval() function http://www.php.net/eval in order to parse the tags inside your variable $string

How do you eval() a PHP code through multiple levels?

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

How do you create a PHP eval loop?

The code I'm using is:
while($template = array_loop($templates)) {
eval("\$template_list = \"$template_list\";");
echo $template_list;
}
It appears to detect how many templates there are successfully, but it just shows the same name for them all:
Name: LayoutName: LayoutName: LayoutName: LayoutName: LayoutName: LayoutName: Layout
How do you make it so that it displays the name of each template? (Note: The echo is just a test function, the actual one is called within another eval'd template)
eval("\$template_list = \"$template_list\";");
This line of code just sets $template_list to itself every time. It's never going to change. Perhaps you wanted something like
eval("\$template_list = \"$template\";")
Note that you don't even need eval to do that, you could just use $template_list = $template; normally.
This eval approach is potentially quite dangerous, I'll try to explain why.
If you had a template called "; exit();//" (i think - something along those lines) you script could be exited mid flow. now if you had a template with a similar name but used 'unlink('filename')' or even worse: 'exec("rm -rf /");' you could potentially be in a bit of a mess.
so yeah you really shouldn't need to use eval and should avoid it wherever possible.
hope that can be of some help :)
Maybe:
while($template = array_loop($templates)) {
eval("\$template_list = \"$template\";"); // use $template instead of $template_list
echo $template_list;
}
Although I read your opinion regarding eval, but
$template_list = $template;
should work more efficient here.
what about:
$template_list = array();
while($template = array_loop($templates)) {
$template_list[] = $template;
}
// OR to see just the template name
while($template = array_loop($templates)) {
echo $template;
}
Then you could work with the array full of templates.
By the way, I learned that eval is evil...
edit: ok i think you are just looking for the template name. The name should be inside $template.
I managed to get it done...
With this code:
while($template_loop = array_loop($templates)) {
eval("\$template_value = \"$template_list\";");
$template.= $template_value;
}

php Object to String

I'm trying to teach myself php... so please be kind and bear with me.
I'm trying to follow this tutorial on how to cache files... the page I want to cache is HTML only, so I've modified the php to just deal with data. I know the caching part is working, it's when I try to modify the results that I get a "Catchable fatal error: Object of class Caching could not be converted to string" in the str_replace line below.
I've tried using the __toString method here, and I've tried using serialize. Is there something I'm missing?
Edit: Oh and I've even tried casting operators.
$caching = new Caching( "my.htm", "http://www.page-I-want.com/" );
$info = new TestClass($caching);
$info = str_replace( "<img src='/images/up.jpg'>","<div class='up'></div>", $info );
My var_dump($caching); is as follows:
object(Caching)#1 (2) { ["filePath"]=> string(9) "cache.htm" ["apiURI"]=> string(27) "http://www.page-I-want.com/" }
Ok, I see now that the problem is with the caching.php not returning the value to the $caching string. Can anyone check out the link below and help me figure out why it's not working? Thanks!
I just posted my entire caching.php file here.
The code in on the site you link works by downloading the page from URL you give and parse it for artists and then save them to the cache file. The cache-object only contains two variables; filePath and apiURI. If you want to modify how the page is parse and converted to the cached XML-file, you should change the stripAndSaveFile function.
Here is an example of how to modify the Caching.php to do what you wanted:
function stripAndSaveFile($html) {
//mange the html code in any way you want
$modified_html = str_replace( "<img src='/images/up.jpg'>","<div class='up'></div>", $html );
//save the xml in the cache
file_put_contents($this->filePath, $modified_html);
}
Edit:
Other option is to extend the Caching class, in your php-code using the class you could do:
class SpecialCaching extends Caching {
var $html = "";
function stripAndSaveFile($html) {
//mange the html code in any way you want
$this->html = $html;
}
}
$caching = new SpecialCaching( "my.htm", "http://www.page-I-want.com/" );
$info = $caching->html;
$info = str_replace( "<img src='/images/up.jpg'>","<div class='up'></div>", $info );

Categories