php: simple template engine - php

I have a function called load_template()
this function has two parameters
$name => the name of the template
$vars => array of key => value variables to be replaced in the template.
the way I want this to work is.
in the template ('test') I want to be able to write
<?php echo $title; ?>
then call
load_template('test', array('title' => 'My Title'));
and have it fill it out.
how can I do this?
Output buffering method.
I have come up with the code below.
I am sure it can be improved.
public static function template($name, $vars = array()) {
if (is_file(TEMPLATE_DIR . $name . '.php')) {
ob_start();
extract($vars);
require(TEMPLATE_DIR . $name . '.php');
$contents = ob_get_contents();
ob_end_clean();
return $contents;
}
throw new exception('Could not load template file \'' . $name . '\'');
return false;
}

function load_template($name, $vars)
{
extract($vars);
include $name;
}
Wrap with ob_start and ob_get_clean if you want to capture the output in a variable.

Something like this?
function load_template($name, $vars)
{
include('template/'.$name.'.tpl'); //.tpl, .inc, .php, whatever floats your boat
}
and in template/whatever.tpl you'd have:
...
<title><?php echo $vars['title'] ?></title>
...
...
<?php if (!empty($vars['content'])): //template still needs to know if the content is empty to display the div ?>
<div id="content">
<?php echo $vars['content']; ?>
</div>
<?php endif; ?>
...
Of course, that assumes the output being printed directly.
You could have the tpl file print directly, or produce a string, or buffer the output from the tpl file and return it from load_template

Related

Get a variable from another file in wordpress

I'm kind of new to wordpress coding and I've been trying to get a variable from another file.
I have this variable $final_cat_url in /custom/last-category.php that I want to reuse in customtemplate.php.
I've read lots of explanations and the codex, but it's still not working.
I've tried to use the following code in customtemplate.php
get_template_part( 'custom/last-category', null, array('my_final_cat_url'=> $final_cat_url));
echo $args['my_final_cat_url'];
Can you help me with that? Thanks a lot.
Add this function to your functions.php file:
function includeWithVariables($filePath, $variables = array(), $print = true){
$output = NULL;
if(file_exists($filePath)){
// Extract the variables to a local namespace
extract($variables);
// Start output buffering
ob_start();
// Include the template file
include $filePath;
// End buffering and return its contents
$output = ob_get_clean();
}
if ($print) {
print $output;
}
return $output;
}
Instead of using get_template_part(), use this:
<?php includeWithVariables('file_to_include.php', array('final_cat_url' => $final_cat_url)); ?>
In the file you included:
<?php echo $final_cat_url; ?>

PHP automatically pre- and append dynamic content to output

Is there a way to automatically include content before and after the actual output of a file?
Why? For example to use this to include everything up to the main content (dynamcally generated HTML, head, opening tags...) and after the file runs, automatically close everything up again.
I know of the ob_start approach, but I'm not sure if dynamically generated content is easy to include that way:
<?php
function bootstrap_page($content) {
return "text before" . $content . "text after";
}
ob_start(bootstrap_page);
?>
But then, ob cannot be used to capture the output of an include within the callback, AFAIK. So that makes it hard to easily pre- and append something dynamically generated. I could use long strings in the callback function to get a static version working - but is there a way to do this more seamlessly?
In other words I'm basically trying to include a php file before and one after any (other) file I need and that - if possible reduced to a function call at the start of a given file.
The functionality I'm looking for would transform this:
<?php
bootstrap_this();
?>
<p>Lorem ipsum</p>
before.php:
<!DOCTYPE html>
<html>
<?php include('head.php'); ?>
<body>
<?php if(somecondition) { ?>
<h1>Hello, World!</h1>
<?php } ?>
after.php:
</body>
</html>
Into something like this:
<?php
include 'before.php';
?>
<p>Lorem ipsum</p>
<?php
include 'after.php';
?>
And in the end into:
<!DOCTYPE html>
<html>
<?php include('head.php'); ?>
<body>
<?php if(somecondition) { ?>
<h1>Hello, World!</h1>
<?php } ?>
<p>Lorem ipsum</p>
</body>
</html>
Isn't that what output buffering is for?
<?php
// Start Buffer
ob_start();
// Include before
include 'before.php';
?>
<p>Lorem ipsum</p>
<?php
// Include after
include 'after.php';
// Get buffered output
$page = ob_get_clean();
echo $page;
?>
But then, ob cannot be used to capture the output of an include within the callback, AFAIK
AFAYK ? Would it be hard to test? As long as the include is after ob_start() and the code does not explicitly call ob_flush() before you choose to do so, then it will capture the output.
I'm basically trying to include a php file before and one after any (other) file I need
That implies some set sort of controlling script which calls the pre-oinclude, the main content and the post-include.
That would be OK if HTML (not true, I'll come back to that) did not have a defined root which should be explicitly declared. And you have the issue HTTP also has a structure which you risk subverting here - headers come before content. But leaving those aside for now, HTML requires a nested structure. All tags should be closed. Opening and closing tags in different files is messy and bad practice.
There are a whole lot technologies which provide the end result you appear to be looking for - ESI, templating and front-controller patterns all provide this in a much more structured way.
I'm not sure I see the usage of this or if I understood this correct, but if I understood it correctly you're looking for something like this:
<?php
function dynamice_include($before, $content, $after) {
$dynamic_content = '';
$dynamic_content .= include $before . '.php';
$dynamic_content .= $content;
$dynamic_content .= include $after . '.php';
return $dynamic_content;
}
Usage:
$content = dynamice_include('before', 'Hello I am really cool','after');
echo $content;
In before.php and after.php a return would be required, e.g.
before.php
<?php
return "wow before";
after.php
<?php
return "wow after";
and the result would be:
wow beforeHello I am really coolwow after
UPDATE:
It seems it more something like this you're looking for. output-buffers are the only way AFAIK to achieve this.
This code is not optimized at all... (I just show the concept here)
<?php
function dynamice_include($before, $content, $after) {
$dynamic_content = '';
ob_start();
include $before . '.php';
$dynamic_content .= ob_get_contents();
ob_end_clean();
ob_start();
include $content . '.php';
$dynamic_content .= ob_get_contents();
ob_end_clean();
ob_start();
include $after . '.php';
$dynamic_content .= ob_get_contents();
ob_end_clean();
return $dynamic_content;
}
$content = dynamice_include('before', 'dytest','after');
echo $content;
As other stated though - it's a lot of platforms, frameworks, template engines out there that could solve this issue. You will have do ob_start() and ob_clean within the current files content for this to work.
UPDATE2:
In this case I fetch current files output buffer as content.
<?php
function dynamice_include($before, $content, $after) {
$dynamic_content = '';
ob_start();
include $before . '.php';
$dynamic_content .= ob_get_contents();
ob_end_clean();
$dynamic_content .= $content;
ob_start();
include $after . '.php';
$dynamic_content .= ob_get_contents();
ob_end_clean();
return $dynamic_content;
}
ob_start();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
feelings
</body>
</html>
<?php
$content = ob_get_contents();
ob_end_clean();
$content = dynamice_include('before', $content, 'after');
echo $content;
?>
Thanks to the help of #bestprogrammerintheworld, I came up with this:
function use_template($before = 'pre', $after = 'post') {
ob_start();
include $before . '.php';
$pre = ob_get_contents();
ob_end_clean();
ob_start();
include $after . '.php';
$post = ob_get_contents();
ob_end_clean();
$bootstrap_page = function ($content) use ($pre, $post) {
return $pre . $content . $post;
};
ob_start($bootstrap_page);
}
If this function is called a the beginning of a php file, the outputs of before.php and after.php get stored and bound to the callback. Then, after all the main output is read, everything is pieced together. No code at the end of the file required.
Since ob cannot be run within the callback, bootstrap_page, it must be run beforehand to capture the other files first.

PHP - Inject script into the <head>

Run into a bit of a sticky situation which I can't seem to wrap my finger around. Basically what I am trying to achieve is having the ability to inject different Javascript files on different page.
Some simple, random example:
Page 1: import jquery.js
Page 2: import mootools.js
So what I have done is, I've created a function called addScript() like so:
function addScript($file) {
$script = '';
$script .= '<script src="'. REL_PATH . '/path/to/file/' . $file . '">';
$script .= '</script>';
return $script;
}
so if I call addScript('jquery.min'); it, outputs correctly.
What I now want to do is replace the closing </head> tag with the output from the above function. If I do the following then it works fine:
ob_start();
require_once("models/header.php");
$contents = ob_get_contents();
ob_end_clean();
echo str_replace('</head>', addScript('jquery.js') . '</head>', $contents);
However I would like this to be a little more dynamic as there may be multiple script that I need to inject on each page like so:
addScript('script.js');
addScript('script2.js');
addScript('script3.js');
I then thought of creating a getHead() function with a foreach loop inside and returning str_replace there instead but this did not work.
Can anyone guide my in the direction to dynamically inject as many script as required and output the last bit of the head?
Why not do something like this:
class Assets {
private static $css = array();
private static $js = array();
static function add_style($path) {
self::$css[] = $path;
}
static function add_script($path) {
self::$js[] = $path;
}
static function get_styles() {
$output = '';
foreach(self::$css as $path) {
$ouput .= '<link rel="stylesheet" href="'. $path .'" />' . "\n";
}
return $ouput;
}
static function get_scripts() {
$output = '';
foreach(self::$js as $path) {
$ouput .= '<script type="text/javascript" src="'. $path .'"></script>' . "\n";
}
return $ouput;
}
}
Then anywhere in your project:
Assets::add_style('path/to/style.css');
Assets::add_script('path/to/jquery.js');
And in header.php:
<head>
<!-- other header stuff -->
<?php echo Assets::get_styles(); ?>
<?php echo Assets::get_scripts(); ?>
</head>
Is much more convenient, and you can can extend the class to do more fancy stuff.
Disclaimer: there is much debate about using static vars, as they look like globals. I agree, but this is quick-and-dirty and works no matter what kind of framework you use. You can also make the variables oldschool instance vars, but then you'll have to pass the assets object to the header.php as well.
What's wrong with the following??
echo str_replace('</head>',
addScript('jquery.js').
addScript('jquer1.js').
addScript('jquer2.js').
addScript('jquer3.js').
'</head>', $contents);
How about you put the ob_start(); in header.php. Then your function is:
function addScript($file) {
$script = '<script src="'. REL_PATH . '/path/to/file/' . $file . '"></script>';
echo str_replace('</head>', addScript('jquery.js') . '</head>', ob_get_clean());
}
Then:
addScript('script.js');
This method keeps the output buffer going and you can manipulate it later in the script whenever you want. just as you do with the addScript().

Using fetch() without Smarty?

Smarty 3 has an option to set (assign) a variable and then include (fetch) a file to a new variable.
How can I do this without the Smarty class? file_get_contents would not work, is there something else?
For example, this is the Smarty code:
<?php
$variable = 'Hello World';
$smarty->assign('variable', $variable);
$content = $smarty->fetch('content.tpl'); // content.tpl have "{$variable}" inside
echo '<script>document.write("' . $content . '")</script>'; // this will output <script>document.write("Hello World")</script>
?>
I want to do it without Smarty:
<?php
$variable = 'Hello World';
$content = file_get_contents('content.php'); // content.php have "echo $variable;" inside
echo '<script>document.write("' . $content . '")</script>';// this needs to output <script>document.write("Hello World")</script>, but it's outputing echo $variable;
?>
You can take advantage of buffering tricks.
function fetch($filename, array $vars) {
ob_start(); // Start output buffering
extract($vars); // Extract variables
require($filename); // Include a file
return ob_get_clean(); // Pass variables to included filename and return output as a string
}
And then you can use it like this:
$content = fetch('content.php', array(
'variable' => 'Hello World',
'name' => 'John Doe',
));
echo $content;
My content.php looks like as follows:
<div>
<b><?php echo $variable; ?></b>, you're logged in as <?php echo $name; ?>
</div>
It outputs Hello World, you're logged in as John Doe

How do I populate a variable using a function?

I have the code below on a page basically what I'm trying to do is fill $content variable using the function pagecontent. Anything inside pagecontent function should be added to the $content variable and then my theme system will take that $content and put it in theme. From the answers below it seems you guys think I want the html and php inside the actual function I don't.
This function below is for pagecontent and is what I'm currently trying to use to populate $content.
function pagecontent()
{
return $pagecontent;
}
<?php
//starts the pagecontent and anything inside should be inside the variable is what I want
$content = pagecontent() {
?>
I want anything is this area whether it be PHP or HTML added to $content using pagecontent() function above.
<?php
}///this ends pagecontent
echo functional($content, 'Home');
?>
I think you're looking for output buffering.
<?
// Start output buffering
ob_start();
?> Do all your text here
<? echo 'Or even PHP output ?>
And some more, including <b>HTML</b>
<?
// Get the buffered content into your variable
$content = ob_get_contents();
// Clear the buffer.
ob_get_clean();
// Feed $content to whatever template engine.
echo functional($content, 'Home');
As you are obviously a beginner here's a much simplified, working version to get you started.
function pageContent()
{
$html = '<h1>Added from pageContent function</h1>';
$html .= '<p>Funky eh?</p>';
return $html;
}
$content = pageContent();
echo $content;
The rest of the code you post is superfluous to your problem. Get the bare minimum working first then move on from there.
Way 1:
function page_content(){
ob_start(); ?>
<h1>Hello World!</h1>
<?php
$buffer = ob_get_contents();
ob_end_clean();
return $buffer;
}
$content .= page_content();
Way 2:
function page_content( & $content ){
ob_start(); ?>
<h1>Hello World!</h1>
<?php
$buffer = ob_get_contents();
ob_end_clean();
$content .= $buffer;
}
$content = '';
page_content( $content );
Way 3:
function echo_page_content( $name = 'John Doe' ){
return <<<END
<h1>Hello $name!</h1>
END;
}
echo_page_content( );

Categories