Last active
May 17, 2023 19:16
-
-
Save daggerhart/730e8a9d79f37a461d985b158d0108ab to your computer and use it in GitHub Desktop.
A simple PHP template class.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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 | |
) ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div class="user-profile"> | |
<h3 class="title"><?php echo $user_name; ?></h3> | |
<div class="content"><?php echo $user_bio; ?></div> | |
</div> |
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;
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@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.