-
-
Save daggerhart/730e8a9d79f37a461d985b158d0108ab to your computer and use it in GitHub Desktop.
<?php | |
/** | |
* Class Template - a very simple PHP class for rendering PHP templates | |
*/ | |
class Template { | |
/** | |
* Location of expected template | |
* | |
* @var string | |
*/ | |
public $folder; | |
/** | |
* Template constructor. | |
* | |
* @param $folder | |
*/ | |
function __construct( $folder = null ){ | |
if ( $folder ) { | |
$this->set_folder( $folder ); | |
} | |
} | |
/** | |
* Simple method for updating the base folder where templates are located. | |
* | |
* @param $folder | |
*/ | |
function set_folder( $folder ){ | |
// normalize the internal folder value by removing any final slashes | |
$this->folder = rtrim( $folder, '/' ); | |
} | |
/** | |
* Find and attempt to render a template with variables | |
* | |
* @param $suggestions | |
* @param $variables | |
* | |
* @return string | |
*/ | |
function render( $suggestions, $variables = array() ){ | |
$template = $this->find_template( $suggestions ); | |
$output = ''; | |
if ( $template ){ | |
$output = $this->render_template( $template, $variables ); | |
} | |
return $output; | |
} | |
/** | |
* Look for the first template suggestion | |
* | |
* @param $suggestions | |
* | |
* @return bool|string | |
*/ | |
function find_template( $suggestions ){ | |
if ( !is_array( $suggestions ) ) { | |
$suggestions = array( $suggestions ); | |
} | |
$suggestions = array_reverse( $suggestions ); | |
$found = false; | |
foreach( $suggestions as $suggestion ){ | |
$file = "{$this->folder}/{$suggestion}.php"; | |
if ( file_exists( $file ) ){ | |
$found = $file; | |
break; | |
} | |
} | |
return $found; | |
} | |
/** | |
* Execute the template by extracting the variables into scope, and including | |
* the template file. | |
* | |
* @internal param $template | |
* @internal param $variables | |
* | |
* @return string | |
*/ | |
function render_template( /*$template, $variables*/ ){ | |
ob_start(); | |
foreach ( func_get_args()[1] as $key => $value) { | |
${$key} = $value; | |
} | |
include func_get_args()[0]; | |
return ob_get_clean(); | |
} | |
} |
<?php | |
$suggestions = array( 'user-profile-example-template' ); | |
// provide more-specific template suggestions for logged in users | |
if ( user_is_logged_in() ) { | |
// provide a generic template suggestion for all users of a given type | |
if ( user_is_of_special_type() ) { | |
$suggestions[] = 'user-profile-' . $user->type; | |
} | |
// provide the most-specific template suggestion possible for this user. | |
$suggestions[] = 'user-profile-' . $user->id; | |
} | |
$tpl = new Template( 'path/to/templates/folder' ); | |
$tpl->render( $suggestions, array( | |
'user_name' => $user->name, | |
'user_bio' => $user->bio | |
) ); |
<div class="user-profile"> | |
<h3 class="title"><?php echo $user_name; ?></h3> | |
<div class="content"><?php echo $user_bio; ?></div> | |
</div> |
@Cyclonecode, good catch on the doulbe $this->folder = $this->folder = ...
, that was a typo I had obviously missed for years.
The $folder
constructor parameter is optional. You shouldn't have to provide a folder path during construction of the object.
Ah, but if you don't supply a folder path the following will never work right:
https://gist.github.com/daggerhart/730e8a9d79f37a461d985b158d0108ab#file-simple-template-class-php-L72
@Cyclonecode, that's true. I made it optional in the constructor, but when not provided a user would need to make use of the set_folder()
method themselves. What would you recommend as an improvement to the class? I'm open to any ideas that make it more reliable and easy to use.
First of all I think I would set visibility for the different methods,. For instance I guess the render_template()
, find_template()
and so on really should not be used by a user directly? If this is the case I really think they should be declared as private
or protected
. Of course the folder
property also should be set to private
or protected
in this case. After that I think changing the render()
method to something like this might be a good idea:
public function render( $suggestions, $variables = array() ){
// Make sure we have a folder path, perhaps we should also check so the folder is readable?
if ( !$this->folder || !is_dir($this->folder)) {
throw new Exception('You need to set the base folder for all templates using set_folder().');
}
$template = $this->find_template( $suggestions );
$output = '';
if ( $template ){
$output = $this->render_template( $template, $variables );
}
return $output;
}
Hm what's up with this:
https://gist.github.com/daggerhart/730e8a9d79f37a461d985b158d0108ab#file-simple-template-class-php-L33
Also, should not this be mandatory:
https://gist.github.com/daggerhart/730e8a9d79f37a461d985b158d0108ab#file-simple-template-class-php-L22