Skip to content

Instantly share code, notes, and snippets.

@rogden
Last active April 8, 2018 10:12
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rogden/6ca5062d4512a1b11dafa6747348735e to your computer and use it in GitHub Desktop.
Save rogden/6ca5062d4512a1b11dafa6747348735e to your computer and use it in GitHub Desktop.
Using Fractal with Handlebars PHP
<?php
use Handlebars\Loader;
class FractalMapLoader implements Loader {
/**
* An array of @handle => component path mappings
* @var array
*/
private $componentMap;
/**
* The path to the component library directory
* @var string
*/
private $componentLibPath;
public function __construct($componentLibPath, $componentMapFileName = 'components-map.json') {
$this->componentLibPath = $componentLibPath;
$this->componentMap = $this->loadMap($componentLibPath . '/' . $componentMapFileName);
}
private function loadMap($componentMapFile) {
$fileContents = file_get_contents($componentMapFile);
return json_decode($fileContents, true);
}
public function load($name) {
if (isset($this->componentMap[$name])) {
return file_get_contents($this->componentLibPath . '/' . $this->componentMap[$name]);
}
throw new \RuntimeException(
"Can not find the $name template"
);
}
}
<?php
use Handlebars\Context;
use Handlebars\Helper;
use Handlebars\Template;
class PathHelper implements Helper {
private $asset_path;
public function __construct( $asset_path ) {
$this->asset_path = $asset_path;
}
public function execute( Template $template, Context $context, $args, $source ) {
return $this->asset_path . preg_replace( '/[\'\"]/', '', $args );
}
}
<?php
use Handlebars\Handlebars;
/**
* A template renderer for Handlebars templates created in the Fractal Component
* Library site.
*
* @package Affectiva\Template_Engine
*/
class Renderer {
private $engine;
/**
* Renderer constructor.
* @param string $component_lib_path The path to the component library project root.
* @param string $asset_path The absolute path to the assets directory.
*/
public function __construct( $component_lib_path, $asset_path ) {
$this->engine = new Handlebars([
'loader' => new FractalMapLoader( $component_lib_path ),
'partials_loader' => new FractalMapLoader( $component_lib_path )
]);
// add asset path helper
$this->engine->addHelper( 'path', new Path_Helper( $asset_path ) );
}
/**
* @return Handlebars The underlying Handlebars engine.
*/
public function get_engine() {
return $this->engine;
}
/**
* @param string $handle The template handle. This is typically '@component-name', where component-name matches the name
* of your component file in Fractal.
* @param array $data The data to provided to the template
* @param bool $echo Whether to echo the template, true or return it, false
*
* @return string The rendered template if $echo is false
*/
public function render( $handle, $data = [], $echo = true ) {
$html = $this->engine->render( $handle, $data );
if ( $echo ) {
echo $html;
} else {
return $html;
}
}
}

To use, create an instance of Renderer and provide it the file path to the Fractal component library directory (the root of the Fractal project) and the URL to the assets directory (for the PathHelper to work correctly). Make sure you are using an Autoloader or are explicitly including the PHP files.

In WordPress you would want to create $view_engine in your functions.php file.

$view_engine = new Renderer(
    get_template_directory() . '/component-library/',
    get_template_directory_uri() . '/component-library/assets'
);

// In some template file
$view_engine->render('@fractal-component-handle', ['data_prop' => 'value']);

If in another environment, just don't use the WP directory functions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment