I'm trying to create a basic short code in Wordpress that will allow me to run PHP on pages. This is what I have so far, but it isn't working. Advice?
The idea is it will be [php] Insert PHP here [/php']
<?php
function php_shortcode( $attr, $content = null ) {
return '<?php' . $content . '?>';
}
add_shortcode('php', 'php_shortcode');
?>
Thank you.
Sorry to say you are exploring a concept that simply cannot yield success. The PHP that renders the shortcode, cannot "also" render code within itself.
Short codes as standard will filter PHP tags. You can however write php directly into the content editor. Without giving you all the advisories why it's not recommended, you can do something like the following which will allow you to write php into the content editor:
// write '<?php ... ?>' into the editor
add_filter('the_content', 'allow_php', 9);
function allow_php($content) {
if (strpos($content, '<' . '?') !== false) {
ob_start();
eval('?' . '>' . $content);
$content = ob_get_clean();
}
return $content;
}
After thinking about this for a little while I realized there is an obvious solution. So, someone probably has written a plugin to do it and someone has - https://wordpress.org/plugins/inline-php/.
It consists of about 40 lines of PHP. The critical implementation trick is it is not done as a shortcode but as a 'the_content' filter.
add_filter('the_content', 'inline_php', 0);
This is done before other 'the_content' filter processing and avoids all the problems that I encountered trying to use it as a shortcode. Of course, there is still a significant security risk.
My users want to be able to have a contact form on their website. Understandable. But it's not really working out.
<?php
function ubbreplace($text){
$text = str_replace("[contact-form]",'<?php include("contactform.php"); ?>',$text);
return $text;
}
?>
The include is not including the contact form. Why is that?
The str_replace function that you're using is working as expected. If you don't see anything in your browser, view the source code and you'll see a <?php tag within your HTML code.
The output is the stuff that normally goes to your browser. A buffer is a cache of data. Output buffer is a cache of data that would have normally gone to your browser, but didn't because you buffered it instead.
To get your desired results, we need to grab the contents of the contactform.php file and replace [contact-form] with those contents. We can do this by capturing the output from the contactform.php into a variable and using that variable as the replacement.
<?php
function ubbreplace($text){
if(strpos($text, '[contact-form]') !== false) {
ob_start();
require 'contactform.php';
$replace = ob_get_contents();
ob_end_clean();
$text = str_replace('[contact-form]', $replace, $text);
}
return $text;
}
$content = ubbreplace('Hello world! [contact-form]');
echo $content;
?>
You are approaching the concept entirely from the wrong end, what you are doing is working with strings, and these strings will not be processed by PHP as functions, or includes or other core markup.
you can insert variables into a string but this happens at execution time, and the string will not then be re-executed (and also ignores the fact the include is not a variable at all but is a language construct).
So, what can you do about this? Well - rearrange your code with the logic that:
You have a string you want to find, and then act once it's been found.
So, to do this try this code logic (customise, obviously). You want to find the "flag" you have set and then replace it with a correct marker,
<?php
if( stripos($text,"[contact-form]") !== false){
include("contactform.php");
}
?>
The above will maybe not do exactly as you intend, because its behaviour depends heavily on what is inside the included PHP file.
You will maybe have to rearrange your include contents (you can return data from an include if you really need to, but I don't really recommend that).
As a small improvement I would also recommend using mb_stripos() function instead of the standard stripos();.
So to get a cleaner more usable result, set the contents of the include to a variable such as $contactForm = "HTML contact form data"; and then always run the include, but only output the contents if the flag is found:
include contains:
$contactForm = "Some HTML contact data";
parent file contains:
<?php
include("contactform.php");
if( stripos($text,"[contact-form]") !== false){
print $contactForm;
}
?>
Or what is very probably easier for you to implement is:
<?php
include("contactform.php");
function ubbreplace($text){
$text = str_replace("[contact-form]",$contactForm,$text);
return $text;
}
?>
Include in the PHP manual, Please note references to return values
Splash58's Answer (and Brogans Answer) of using output buffering is also a perfectly
good solution and saves a lot of the effort of quantifying included output into
varaibles in my answer, although my answer is primarily to explain the
purpose and the failings of your original question.
Given a completely open option I would choose to use Output buffering
to solve this issue but you do need to know what's going on, so if
output buffering is new to you definitely read up on it first.
function ubbreplace($text){
if (strpos($text, "[contact-form]") !== false) {
ob_start();
include("contactform.php");
$replace = ob_get_contents();
ob_end_clean();
$text = str_replace("[contact-form]", $replace, $text);
}
return $text;
}
Not the best name for a thread but still...
I got
<?php include('inc/nav_bar.php'); ?>
...
<?php
main code block
?>
I need to print one variable from "main code block" to "nav_bar" block,
is there is any good way to do this ?
The only solution I've found so far is to use javascript.
If I understand you correctly your nav_bar.php prints out something which should contain the value of a variable in the main code block.
Then you could try to "catch" the output of the nav_bar.php:
ob_start();
include('inc/nav_bar.php');
$navBarContent = ob_get_contents();
ob_end_clean();
// main code block: replace some placeholders in $navBarContent with variables content
Edit: But I agree with the others. A better solution is to change your code-design and use classes/functions.
You may use different ways - rearrange code blocks or use output buffering.
Is 'nav_bar.php' echo any content? Try this:
{nav_bar.php}
...
echo "some text %VAR% some text";
...
{main.php}
ob_start();
include 'inc/nav_bar.php';
$content = ob_get_contents();
ob_end_clean();
$var = doSomeCalc();
$content = str_replace('%VAR%', $var, $content);
echo $content;
OR you may use this way:
{main.php}
$main_var = doSomeCalc();
...
include 'inc/nav_bar.php';
...
echo "something else";
{nav_bar.php}
...
echo "some text $main_var some text"; // use $main_var defined earlier
...
I think it's time for you to start using the MVC pattern in your applications :)
This will solve all your output priority problems.
Read more here :
"What is MVC ?"
I'd go for this pattern:
<?php
// main code block
include('inc/nav_bar.php');
But if you want to go steps forward with your own skill and make your life easier, use templating (which takes an approach from the inside out, instead of the other way around).
Look up Twig or Smarty if you want to make use of some existing templating engine. I'd also highly recommend Zend Framework, which uses mainly purely PHP based templates (you could use other engines too) and Symfony (uses mainly Twig).
Update- Thanks for all the responses. This Q is getting kind of messy, so I started a sequel if anyone's interested.
I was throwing together a quick script for a friend and stumbled across a really simple way of doing templating in PHP.
Basically, the idea is to parse the html document as a heredoc string, so variables inside of it will be expanded by PHP.
A passthrough function allows for expression evaluation and function and static method calls within the string:
function passthrough($s){return $s;}
$_="passthrough";
The code to parse the document inside a heredoc string is ridiculously simple:
$t=file_get_contents('my_template.html');
eval("\$r=<<<_END_OF_FILE_\n$t\_END_OF_FILE_;\n");
echo $r;
The only problem is, it uses eval.
Questions
Can anyone think of a way to do this sort of templating without using eval, but without adding a parser or a ton of regex madness?
Any suggestions for escaping stray dollar signs that don't belong to PHP variables without writing a full-on parser? Does the stray dollar sign problem render this approach not viable for 'serious' use?
Here's some sample templated HTML code.
<script>var _lang = {$_(json_encode($lang))};</script>
<script src='/blah.js'></script>
<link href='/blah.css' type='text/css' rel='stylesheet'>
<form class="inquiry" method="post" action="process.php" onsubmit="return validate(this)">
<div class="filter">
<h2>
{$lang['T_FILTER_TITLE']}
</h2>
<a href='#{$lang['T_FILTER_ALL']}' onclick='applyFilter();'>
{$lang['T_FILTER_ALL']}
</a>
{$filter_html}
</div>
<table class="inventory" id="inventory_table">
{$table_rows}
<tr class="static"><th colspan="{$_($cols+1)}">
{$lang['T_FORM_HELP']}
</th></tr>
{$form_fields}
<tr class="static">
<td id="validation" class="send" colspan="{$cols}"> </td>
<td colspan="1" class="send"><input type="submit" value="{$lang['T_SEND']}" /></td>
</tr>
</table>
</form>
Why use templating?
There's been some discussion of whether creating a templating layer is necessary in PHP, which, admittedly, is already pretty good at templating.
Some quick reasons templating is useful:
You can control it
If you preprocess the file before it goes to the interpreter, you have more control over it. You can inject stuff, lock down permissions, scrape for malicious php / javascript, cache it, run it through an xsl template, whatever.
Good MVC design
Templating promotes separation of view from model and controller.
When jumping in and out of <?php ?> tags in your view, it's easy to get lazy and do some database queries or perform some other server action. Using a method like the above, only one statement may be used per 'block' (no semicolons), so it's much more difficult to get caught in that trap. <?= ... ?> have pretty much the same benefit, but...
Short tags aren't always enabled
...and we want our app to run on various configurations.
When I initially hack a concept together it starts out as one php file. But before it grows I'm not happy unless all php files have only one <?php at the beginning, and one ?> at the end, and preferably all are classes except stuff like the controller, settings, image server, etc.
I don't want much PHP in my views at all, because designers become confused when dreamweaver or whatever poops the bed when it sees something like this:
<a href="<?php $img="$img_server/$row['pic'].png"; echo $img; ?>">
<img src="<?php echo $img; ?>" /></a>
This is hard enough for a programmer to look at. The average graphic designer won't go anywhere near it. Something like this is a much easier to cope with:
<img src="{$img}" />
The programmer kept his nasty code out of the html, and now the designer can work his design magic. Yay!
Quick update
Taking everyone's advice into consideration, I think preprocessing the files is the way to go, and the intermediate files should be as close as normal "php templating" as possible, with the templates being syntactic sugar. Eval still in place for now while I play with it. The heredoc thing has sort of changed its role. I'll write more later and try to respond to some of the answers, but for now...
<?php
class HereTemplate {
static $loops;
public function __construct () {
$loops=array();
}
public function passthrough ($v) { return $v; }
public function parse_markup ($markup, $no_escape=null, $vars=array()) {
extract($vars);
$eot='_EOT_'.rand(1,999999).'_EOT_';
$do='passthrough';
if (!$no_escape) $markup=preg_replace(
array(
'#{?{each.*(\$\w*).*(\$\w*).*(\$\w*).*}}?#',
'#{?{each.*(\$\w*).*(\$\w*).*}}?#',
'#{?{each}}?#',
'#{{#', '#}}#',
'#{_#', '#_}#',
),
array(
"<?php foreach (\\1 as \\2=>\\3) { ?>",
"<?php foreach (\\1 as \\2) { ?>",
"<?php } ?>",
"<?php echo <<<$eot\n{\$this->passthrough(", ")}\n$eot\n ?>",
"<?php ", " ?>",
),
$markup);
ob_start();
eval(" ?>$markup<?php ");
echo $markup;
return ob_get_clean();
}
public function parse_file ($file) {
// include $file;
return $this->parse_markup(file_get_contents($file));
}
}
// test stuff
$ht = new HereTemplate();
echo $ht->parse_file($argv[1]);
?>
...
<html>
{{each $_SERVER $key $value}
<div id="{{$key}}">
{{!print_r($value)}}
</div>
{each}}
</html>
PHP was itself originally intended as a templating language (ie a simple method of allowing you to embed code inside HTML).
As you see from your own examples, it got too complicated to justify being used in this way most of the time, so good practice moved away from that to using it more as a traditional language, and only breaking out of the <?php ?> tags as little as possible.
The trouble was that people still wanted a templating language, so platforms like Smarty were invented. But if you look at them now, Smarty supports stuff like its own variables and foreach loops... and before long, Smarty templates start to have the same issues as PHP templates used to have; you may as well just have used native PHP in the first place.
What I'm trying to say here is that the ideals of a simple templating language aren't actually that easy to get right. It's virtually impossible to make it both simple enough not to scare off the designers and at the same time give it enough flexibility to actually do what you need it to do.
If you don't wont to use a big template engines like Twig (which I sincerely recommend) you can still get good results with little code.
The basic idea that all the template engines share is to compile a template with friendly, easy-to-understand syntax to fast and cacheable PHP code. Normally they would accomplish this by parsing your source code and then compiling it. But even if you don't want to use something that complicated you can achieve good results using regular expressions.
So, basic idea:
function renderTemplate($templateName, $templateVars) {
$templateLocation = 'tpl/' . $templateName . '.php';
$cacheLocation = 'tplCache/' . $templateName . '.php';
if (!file_exists($cacheLocation) || filemtime($cacheLocation) < filemtime($templateLocation)) {
// compile template and save to cache location
}
// extract template variables ($templateVars['a'] => $a)
extract($templateVars);
// run template
include 'tplCache/' . $templateName . '.php';
}
So basically we first compile the template and then execute it. Compilation is only done if either the cached template doesn't yet exist or there is a newer version of the template than the one in the cache.
So, let's talk about compiling. We will define two syntaxes: For output and for control structures. Output is always escaped by default. If you don't want to escape it you must mark it as "safe". This gives additional security. So, here an example of our syntax:
{% foreach ($posts as $post): }
<h1>{ $post->name }</h1>
<p>{ $post->body }</p>
{!! $post->link }
{% endforeach; }
So, you use { something } to escape and echo something. You use {!! something} to directly echo something, without escaping it. And you use {% command } to execute some bit of PHP code without echoing it (for example for control structures).
So, here's the compilation code for that:
$code = file_get_contents($templateLocation);
$code = preg_replace('~\{\s*(.+?)\s*\}~', '<?php echo htmlspecialchars($1, ENT_QUOTES) ?>', $code);
$code = preg_replace('~\{!!\s*(.+?)\s*\}~', '<?php echo $1 ?>', $code);
$code = preg_replace('~\{%\s*(.+?)\s*\}~', '<?php $1 ?>', $code);
file_put_contents($cacheLocation, $code);
And that's it. You though have to note, that this is more error prone than a real template engine. But it will work for most cases. Furthermore note that this allows the writer of the template to execute arbitrary code. That's both a pro and a con.
So, here's the whole code:
function renderTemplate($templateName, $templateVars) {
$templateLocation = 'tpl/' . $templateName . '.php';
$cacheLocation = 'tplCache/' . $templateName . '.php';
if (!file_exists($cacheLocation) || filemtime($cacheLocation) < filemtime($templateLocation)) {
$code = file_get_contents($templateLocation);
$code = preg_replace('~\{\s*(.+?)\s*\}~', '<?php echo htmlspecialchars($1, ENT_QUOTES) ?>', $code);
$code = preg_replace('~\{!!\s*(.+?)\s*\}~', '<?php echo $1 ?>', $code);
$code = preg_replace('~\{%\s*(.+?)\s*\}~', '<?php $1 ?>', $code);
file_put_contents($cacheLocation, $code);
}
// extract template variables ($templateVars['a'] => $a)
extract($templateVars, EXTR_SKIP);
// run template
include 'tplCache/' . $templateName . '.php';
}
I haven't tested the above code ;) It's only the basic idea.
I'm gonna do something silly and suggest something that requires no templating engine at all and requires only at most 5 characters more per variable/call than what you have there - replace {$foo} with <?=$foo?> and then you can use include for all your templating needs
If all you need is variable replacement though this is a templating function i actually use:
function fillTemplate($tplName,$tplVars){
$tpl=file_get_contents("tplDir/".$tplName);
foreach($tplVars as $k=>$v){
$tpl = preg_replace('/{'.preg_quote($k).'}/',$v,$tpl);
}
return $tpl;
}
if you want to be able to call functions or have loops, there is basicly no way around calling eval short of pre-processing.
There is no ultimate solution. Each has pros and cons. But you already concluded what you want. And it seems a very sensible direction. So I suggest you just find the most efficient way to achieve it.
You basically only need to enclose your documents in some heredoc syntactic sugar. At the start of each file:
<?=<<<EOF
And at the end of each template file:
EOF;
?>
Achievement award. But obviously this confuses most syntax highlighting engines. I could fix my text editor, it's open source. But Dreamweaver is a different thing. So the only useful option is to use a small pre-compiler script that can convert between templates with raw $varnames-HTML and Heredoc-enclosed Templates. It's a very basic regex and file rewriting approach:
#!/usr/bin/php -Cq
<?php
foreach (glob("*.tpl") as $fn) {
$file = file_get_contents($fn);
if (preg_match("/<\?.+<<</m")) { // remove
$file = preg_replace("/<\?(=|php\s+print)\s*<<<\s*EOF\s*|\s+EOF;\s*\?>\s*/m", "", $file);
}
else { // add heredoc wrapper
$file = "<?php print <<<EOF\n" . trim($file) . "\nEOF;\n?>";
}
file_put_contents($fn, $file);
}
?>
This is a given - somewhere you will need templates with a slight amount of if-else logic. For coherent handling you should therefore have all templates behave as proper PHP without special eval/regex handling wrapper. This allows you to easily switch between heredoc templates, but also have a few with normal <?php print output. Mix and match as appropriate, and the designers can work on the majority of files but avoid the few complex cases. For exampe for my templates I'm often using just:
include(template("index")); // works for heredoc & normal php templ
No extra handler, and works for both common template types (raw php and smartyish html files). The only downside is the occasional use of said converter script.
I'd also add a extract(array_map("htmlspecialchars",get_defined_vars())); on top of each template for security.
Anyway, your passthrough method is exceptionally clever I have to say. I'd call the heredoc alias $php however, so $_ is still available for gettext.
{$php(1+5+7*3)} is more readable than Smarty
I think I'm going to adopt this trick myself.
<div>{$php(include(template($ifelse ? "if.tpl" : "else.tpl")))}</div>
Is stretching it a bit, but it seems after all possible to have simple logic in heredoc templates. Might lead to template-fileritis, yet helps enforcing a most simple template logic.
Offtopic: If the three <<<heredoc&EOF; syntax lines still appear too dirty, then the best no-eval option is using a regular expression based parser. I do not agree with the common myth that that's slower than native PHP. In fact I believe the PHP tokenizer and parser lag behind PCRE. Especially if it's solely about interpolating variables. It's just that the latter isn't APC/Zend-cached, you'd be on your own there.
Personally, I wouldn't touch with a stick any templating system where forgetting to escape a variable creates a remote code execution vulnerability.
Personally i'm using this template engine: http://articles.sitepoint.com/article/beyond-template-engine/5
I really like it a lot, especially because of it's simplicity. It's kinda similar to your latest incarnation, but IMHO a better approach than using heredoc and putting yet another layer of parsing above the PHP one. No eval() either, but output buffering, and scoped template variables, too. Use like this:
<?php
require_once('template.php');
// Create a template object for the outer template and set its variables.
$tpl = new Template('./templates/');
$tpl->set('title', 'User List');
// Create a template object for the inner template and set its variables.
// The fetch_user_list() function simply returns an array of users.
$body = new Template('./templates/');
$body->set('user_list', fetch_user_list());
// Set the fetched template of the inner template to the 'body' variable
// in the outer template.
$tpl->set('body', $body->fetch('user_list.tpl.php'));
// Echo the results.
echo $tpl->fetch('index.tpl.php');
?>
The outter template would look like this:
<html>
<head>
<title><?=$title;?></title>
</head>
<body>
<h2><?=$title;?></h2>
<?=$body;?>
</body>
</html>
and the inner one (goes inside the outter template's $body variable) like this:
<table>
<tr>
<th>Id</th>
<th>Name</th>
<th>Email</th>
<th>Banned</th>
</tr>
<? foreach($user_list as $user): ?>
<tr>
<td align="center"><?=$user['id'];?></td>
<td><?=$user['name'];?></td>
<td><?=$user['email'];?></td>
<td align="center"><?=($user['banned'] ? 'X' : ' ');?></td>
</tr>
<? endforeach; ?>
</table>
If you don't like / can't use short-tags then replace them with echos. That's as close to dirt-simple as you can get, while still having all the features you'll need IMHO.
Dead-simple templating using a function:
<?php
function template($color) {
$template = <<< ENDTEMPLATE
The colors I like are {$color} and purple.
ENDTEMPLATE;
return $template . "\n";
}
$color = 'blue';
echo template($color);
$color = 'turquoise';
echo template($color);
This outputs:
The colors I like are blue and purple.
The colors I like are turquoise and purple.
Nothing fancy, but it does work using standard PHP without extensions. Additionally, the use of functions to encapsulate the templates should help with proper MVC separation. Also (and this is what I needed for my coding today) I can save the filled-out template away for output to a file (later on in my program).
This is a minimal implementation of mustache to just substitute variables.
// Example:
// miniMustache(
// "{{documentName }} - pag {{ page.current }} / {{ page.total }}",
// array(
// 'documentName' => 'YourCompany Homepage',
// 'page' => array('current' => 1, 'total' => 10)
// )
// )
//
// Render: "YourCompany Homepage - pag 1 / 10"
function miniMustache($tmpl, $vars){
return preg_replace_callback( '/\{\{([A-z0-9_\.\s]+)\}\}/',
function ($matches) use ($vars) {
//Remove white spaces and split by "."
$var = explode('.',preg_replace('/[\s]/', '', $matches[1]));
$value = $vars;
foreach($var as $el){
$value = $value[$el];
}
return $value;
},
$tmpl);
}
In some cases, it is more than enough. In case you need full power: https://github.com/bobthecow/mustache.php
I have the following dilemma. I have a complex CMS, and this CMS is to be themed by a graphic designer. The templates are plain HTML, with several nested inclusions. I'd like to make it easier for the designer to locate the file to be modified, by looking at the HTML of the page.
What I thought in the first place was to build something stupid like this:
function customInclude($what) {
print("<!-- Including $what -->");
include($what);
print("<!-- End of $what -->");
}
but, guess what? Variables obviously come out of scope in the included file :-) I can't declare them as global or as parameters, as I don't know how they are called and how many are there.
Is there any possibility to implement some kind of "macro expansion" in PHP? An alternative way to call it: I'd like to modify each call of the modify function, in an aspect-oriented style.
I have thought about eval(), is it the only way? Will it have a big impact on performance?
I know this is an old question, but I stumbled upon it and it reminds me of something I used to do it too.
how about if you create the function using a very weird variable?
<?php
function customInclude($___what___) {
echo '<!-- Including '.$___what___.' -->';
include($what);
echo '<!-- End of '.$___what___.' -->';
}
?>
I usually suggest to add a possible variable to display those tags only when necessary, you do not want other people to know...
<?php
function __printIncludeInfo($info, $dump = false){
//print only if the URL contains the parameter ?pii
//You can modify it to print only if coming from a certain IP
if(isset($_GET['pii'])){
if($dump){
var_dump($info);
} else {
echo $info;
}
}
}
function customInclude($___what___) {
__printIncludeInfo('<!-- Including '.$___what___.' -->');
include($what);
__printIncludeInfo('<!-- End of '.$___what___.' -->');
}
?>
in this way you can use the function to print any other information that you need
Not sure if I entirely understand the question, but if you're just trying to make life easier for the designer by showing them the underlying filename of the included file, then you can probably just use this within the template files:
echo '<!-- Start of '.__FILE__.' -->';
....content...
echo '<!-- End of '.__FILE__.' -->';
__FILE__ is just one of several Magic Constants.
Also there's the get_included_files() function that returns an array of all the included files, which might be of use (you could output a list of all the included files with 'tpl' in their name for example).
This is my 100% harcoded solution to custom include problem. It's about using a global var to point the next include filename and then include my custom proxy-include-file (wich replace your custom proxy-include-function)
1 - Add this code to a global include (wherever your customInclude function is defined)
$GLOBALS['next_include'] = "";
$GLOBALS['next_include_is_once'] = false;
function next_include($include_file) {
$GLOBALS['next_include_is_once'] = false;
$GLOBALS['next_include'] = $include_file;
}
function next_include_once($include_file) {
$GLOBALS['next_include_is_once'] = true;
$GLOBALS['next_include'] = $include_file;
}
2 - Create some include proxy-include-file, by example "debug_include.php"
<?php
if(empty($GLOBALS['next_include'])) die("Includes Problem");
// Pre-include code
// ....
if($GLOBALS['next_include_is_once']) {
include_once($GLOBALS['next_include']);
} else {
include($GLOBALS['next_include']);
}
// Post-include code
// ....
$GLOBALS['next_include'] = "";
3 - Perform a search and replace in all your files: (except debug_include.php)
search: 'include((.*));' as a reg.exp
replace with: '{next_include($1);include('debug_include.php');}'
and
search: 'include_once((.*)); as a reg.exp
replace with: '{next_include_once($1);include('debug_include.php');}'
Maybe you should need another search-and-replaces if you have some non-standard includes like
include (.... include (.... include (....
I think you can find some better search-and-replace patterns, but I'm not a regular expression user so I did it the hard way.
You should definitely use objects, namespaces and MVC model. Otherwise there is no pure and clean solution to your problem. And please, don't use eval, it's evil.