Trying to understand PHP template, Plates - php

I am new to PHP, trying to understand how to use a simple template system with PHP, I like "Plates", mainly because it claims to be a template system, not a template language, but the documentation is kind of confusing.
As an example where this code "controller" leaves? Is it a another PHP file?
// Create new Plates instance
$templates = new League\Plates\Engine('/path/to/templates');
// Render a template
echo $templates->render('profile', ['name' => 'Jonathan']);
Shouldn't this code "profile.php" call the controller file somewhere?
profile.php
<?php $this->layout('template', ['title' => 'User Profile']) ?>
<h1>User Profile</h1>
<p>Hello, <?=$this->e($name)?></p>
The template file:
template.php
<html>
<head>
<title><?=$this->e($title)?></title>
</head>
<body>
<?=$this->section('content')?>
</body>
</html>
Does anyone have a better code sample using "Plates" in PHP where I can see how this template system works?
Thank you!

The example in the Plates doc is pretty good and simple. The way I see it - you might have an MVC controller or you might not; the code in question may reside in a simple script (lets say index.php for the sake of clarity). Lets imagine the site structure looks like:
/index.php
/templates/ folder
/templates/profile.php
/templates/template.php
The code in index.php becomes:
// Create new Plates instance
$templates = new League\Plates\Engine('/templates');
// Render a template
echo $templates->render('profile', ['name' => 'Jonathan']);
You might have it in an MVC controller, but that is totally different topic.

I wanted to try a pure php templating engine too so I tried out Plates as well. It is simple. I like simple solutions for simple problems. They are faster to implement.
If you are new to php using Plates can be a great way to start to write 'cleaner' code with very little additional investment of your time.
Because you are new to PHP there is a bit of background detail you need to understand first. Then I think it will be clear.
The example here is not so great in that the paths are not that useful. Assume they intend to show that the fully qualified path is required. A better example would have used something like:
$templates = new Engine(__DIR__ . '/templates');
where the templates directory is a sub-directory of the current folder that the presenter or controller may be in.
Since templates are central to presentation, it is my opinion that presenter is a better name for the class that will be using the templates but a lot of people use controller because of the popularity of mvc.
"\League\Plates\Engine" is a namespace, not a path. You can include a "use" statement in your class for every imported class you want to use from that namespace if you want.
On their "installation" page here they show that you have to edit the composer.json file to load plates. If you are unfamiliar with composer all you have to do is install it and run "composer update" in the folder with the composer.json file from the installation page and it will create the vendor folder for you with all the supporting files necessary to run Plates. It will place these files in a vendor folder which is why you need to require vendor/autoload.php.
Plates also assumes that the files in your template directory are php files and that is why they don't require a file extension on the parameter. so 'template' and 'profile' refer directly to the template.php and profile.php files.
The essential idea behind templating is to separate your view and code. Data is obtained by the code and passed into the view. These template files represent the view and the data is passed into the templates via the associative array in the render function in the example.
Because Plates is a php based templating engine, the templates ARE php files. So some php coding will be required to obtain the data from the model (the associative array) and for looping constructs and such. What you want to achieve is to keep the code specific to only what is necessary to render the data in the html and nothing else.
The profile.php page and the template.php page are both "templates" The template.php file is useful if you are going to display a whole page but unnecessary if you just want to output an html element. In the latter case the profile.php file in the example could be produced without the optional page 'layout'.
So what the 'render' function basically does is to load the php file specified by name and insert all the data from the associative array into that file according to its own code and optionally its associated layout template file and return the resulting html.
The class using the templates let's call it Presenter.php should have code something like this in it:
<?php
require 'vendor/autoload.php';
use \League\Plates\Engine;
class Presenter {
private $name;
function __construct($name){
$this->name = $name;
}
function render() {
$templates = new Engine(__DIR__ . '/templates');
echo $templates->render('profile', ['name' => $this->name]);
}
}
and an index.php like this:
<?php
require(__DIR__ . '/Presenter.php');
$presenter = new Presenter('Jonathan');
$presenter->render();
...
where your file structure in your project directory looks something like this:
index.php
Presenter.php
templates/template.php
templates/profile.php
composer.json
composer.lock
vendor/...
That should get anyone interested in trying Plates started.

Related

Codeigniter HMVC asset managment

I am trying to give a shot to HMVC in Codeigniter. Here is my folder structure.
-ROOT
--APPLICATION
---MODULES
----Module_Email
-----Controllers
-----Models
-----Views
-----Assets
------JS
------CSS
------IMG
To render the Module i have to use
Module::run('Module_Email');
This method will output the rendered output, an example is given below
<script type="text/javascript" src="PATH/TO/EMAIL_MODULE/JS/JS_FILE.JS"></script>
<div data-module-name="Module_Email" class="Email_wrapper">
//RENDERED HTML CONTENT
</div>
Now here my problem start. Normally i would like to put all my resources to header. So when i call any module, its dependence need to be added in header instead of from where its get called.
I searched a lot but i couldn't find any good methods.
Please help.
Update
Currently i have a function on my header called get_assets() which will output predefined resources to header. But i cant say which modules is going to use in pages, so the system need to check which modules are used in this page, and if its used then its dependencies need to be added on header.
Seems like your main problem then is trying to figure out what modules were used.
Unfortunately as far as I can tell with the default Wiredesignz modular extension there is no way to access the module name unless you write some sort of hack to get at that data. The module being used is stored in the protected variable $module in the MX_Router class, however, there is no public method to allow you to get access to it. So your only choice would be to extend the class and create a public function.
Alternatively you could use a forked version of Wiredesignz implementation which I did which provides numerous other features including a public function to get at the $module variable. Using the forked version I wrote you could then use code such as this:
<?php $module_name = $this->router->fetch_module(); ?>
However, that will only record the last module you loaded, so you would still need to do work to store all the modules, and then have your function use this information to determine what assets to load. If I were doing something like you I would probably fork my version and then create an additional data structure to store every module that was loaded that you could then later get access to.
I don't think this is exactly what you were hoping for, but might be something to get you on the right track to finding a solution.
I added an array to the Module class to store the assets and two functions to store/retrieve the items. Here is the source (updated Modules.php)
# Register your assets
public static function register_asset( $asset )
{
if( in_array($asset,self::$assets) === FALSE )
{
self::$assets[] = $asset;
}
}
public static function assets()
{
return self::$assets;
}
and now you can register your assets like this inside your module
Modules::register_asset('myslider.js');
You can retrieve all your assets using
Modules:assets();
Which will return an array of assets that can be processed depending up on the situation.

Changing the behaviour of view in Codeigniter

I am using codeigniter for a project that is used by a variety of companies.
The default version of our software is up and running and works fine - however some of our customers want slightly different view files for their instance of the system.
Ideally what I would like to do is set a variable (for example VIEW_SUFFIX) and whenever a view file is loaded it would first check if there was a suffix version available if there was use that instead.
For example if the system had a standard view file called 'my_view.php' but one client had a VIEW_SUFFIX of 'client_1' - whenever I called $this->load->view('my_view') if the VIEW_SUFFIX was set it would first check if my_view_client_1 existed (and if it did use that) or if not use the default my_view.php.
I hope that my question is clear enough... If anyone has done this before or can think of a way to do it I would really appreciate it.
EDIT:
Ideally I would like a solution that works without me changing every place that I am calling the view files. Firstly because there are a few files that may want different client versions and also because the view files are called from a lot of controllers
I had a similar requirement for which I created a helper function. Among other things, this function can check for a suffix before loading the specified view file. This function can check for the suffix and check if the file exists before loading it.
Unfortunately, the file checking logic would be a bit brittle. As an alternative, you can implement a MY_Loader class that will override the basic CI_Loader class.
Something like this in your application/core/MY_Loader.php:
class MY_Loader extends CI_Loader {
protected function _ci_load($_ci_data)
{
// Copy paste code from CI with your modifications to check prefix.
}
}
Could you not do this
// some method of creating $client
// probably created at login
$_SESSION['client'] = 'client_1';
$client = (isset($_SESSION['client'])) ? $_SESSION['client'] : '';
$this->load->view("your_view{$client}", $data);

Injecting CSS into the layout from within a zf2 module

I'm almost done writing a very simple module for zf2. One thing I'd like my module to do is to inject some css to the layout so that the HTML it generates displays in a nicer way.
Is this possible to do from within a module? If so, how?
EDIT: Thank you all for the prompt responses. However I think I probably didn't explain myself very clearly. When I say "inject some css" I mean taking a string of css and having it actually rendered INSIDE the layout. I didn't mean linking to an external css file or having an asset manager publish my files like the answers so far have suggested.
See Publishing assets from modules in Zend Framework 2 or How to merge Zend Framework 2 module public directories for discussion of the options you have for pushing public assets from a module.
And in addition to pushing your module assets to public, you could put the append into a triggered method like onBootstrap:
public function onBootstrap($e) {
$sm = $e->getApplication()->getServiceManager();
$headLink = $sm->get('viewhelpermanager')->get('headLink');
$headLink->appendStylesheet('/assets/MyModule/css/mystylesheet.css');
}
Try to use something like:
$sm = $this->getEvent()->getApplication()->getServiceManager();
$helper = $sm->get('viewhelpermanager')->get('headLink');
$helper->prependStylesheet('/css/mystylesheet.css');
in Your module controller.
EDIT:
If you want to store css style in module, You can either render it in Your layout file (head section) or, the better way, create another route in module, for example /get/style/[:name]. This route point to another action which returns only plain text/css document. More or less :)
Add a variable to your layout for where you'd like the CSS to be inserted:
Some Link
Then in your Controller, load and assign it however you'd like:
$this->layout()->CSS = "CSS";
$this->layout()->CSS = $this->getRequest()->getPost('CSStoInject');
$this->layout()->CSS = fopen(), curl(), etc.

Constants in Kohana

I've used codeigniter in the past but on my current project I'm making the switch to Kohana. What is the best practice on constants?
In codeigniter there is the actual constants.php, but going through Kohana's source I'm not seeing something similar.
Never used kohana, but after a quick googling I find that you can use the config API to create your own config that will house the constants you need.
This thread suggests that if you are storing database sensitive items, to place them in the database.php config, etc.. making them relative to the type of data they are storing.
I'm familiar with Kohana, but not CI so much, so I'm guessing a bit to what you mean by 'constants.' I believe the closest thing to this is indeed Kohana's config API. So, if you wanted to make templates aware of some site-wide constant like your site name, that's a great thing to use the config API for.
To accomplish this, you'll need to create a config file under your /config folder, probably in the /application directory. What you call it isn't very important, but since it contains site information, let's call it site.php.
To quickly get going, here is what you'll want to have in that file:
<?php defined('SYSPATH') or die('No direct script access.');
return array(
// Your site name!
'name' => 'Oh me, Oh my',
);
Now, you can bring this in to a template by doing something like:
A better way to do this (using dumb templating) would be to assign this as a template variable in your Controller. So, assuming you have some default controller set up, the code would be:
public function action_index() {
$this->template->site_name = Kohana::config('site.name');
}
And then your template would have something like this:
<title><?php echo $site_name; ?></title>
Kohana's config API is interesting because it is hierarchical, meaning you can override and merge new configuration values on top of existing config structures. When you call Kohana::config('site.name'), the engine looks through all the config files named site.php, runs all of those config files and merges the results in to an array. The application-level config files will overwrite modules, which will overwrite system, etc... Then, based on that result array, Kohana will attempt to find the 'name' key and return it.
Assuming you want global constants...the following worked well for me.
application/config/constants.php:
define('MY_COOL_CONSTANT', 'foo');
return array();
index.php:
Kohana::$config->load('constants');
MY_COOL_CONSTANT should then be available globally.

Templates in PHP, and the best way to notify the application that one exists?

I'm using CodeIgniter, and will likely use their template library as I want to keep things extremely simple to use. The content for the template variables will come from the database, but I want the business admins to know what content areas are available. Basically the names of the parameters when they choose a specific template. For instance, Joomla uses an extra XML file that defines each area, whereas Wordpress uses comments within a page template to inform the system that the PHP file is a template. I like the Joomla approach because you don't have to parse the PHP file to find the areas, but I like the Wordpress approach because you don't have an extra XML file associated with every template. Are there other approaches that I'm missing?
I think the nicest way would be to add a small hack to the template parser class. The code looks quite readable and clean in system/libraries/Parser.php. You could insert a hook in that class that can be used to keep track of the variables. I don't know, if it works, but here's a snippet:
class CI_Parser {
var $varCallback;
function setVarCallback($callbackFunction) {
$this->varCallback = $callbackFunction;
}
...
function _parse_single(...) {
$callback = $this->varCallback;
$callback($key);
}
...
//Somewhere in your code
function storeVarName($variableName) {
// Persist the variable name wherever you want here
}
$this->parser->setVarCallback('storeVarName');
You could do this directly in the controller:
// in the controller
print_r($data);
$this->load->view("main", $data);
Or a little more rudimentary, but you could pass to the template a PHP array of variables (or an object):
// in the controller
$data = array();
$data["namespace"] = array(
"title" => "My website",
"posts" => array("hi", "something else")
);
$this->load->view("main", $data);
And then in the view, have a flag to print_r the namespace to show all the vars available, so that business admins know exactly what to use.
// in the view
if(isset($namespace["showAllVars"])) print_r($namespace);
One option would be to call token_get_all on the PHP file (only when your business admins are loading it up), and parse the output of that.
The best approach, in my opinion, is to keep the variable definitions in another place (such as a database table, or a separate file). This will help with testing (i.e., a programmer can't just remove a tag and it's gone) and making sure things are still working as you move on with the application development in time.
Another advantage is that your application logic will be independent from the templating engine.
On a side note, if you expect a lot of traffic, you may consider using smarty instead. We have done extensive testing with most of the templating engines around and smarty is the fastest.

Categories