Cheap php templating with vprintf? - php

Ok,
so printf/sprint/vprintf all accept a certain type specifier syntax %[num][type]. (http://us2.php.net/sprintf see examples 3 and 4) Where num is the index to the type.
Example:
vprintf('Number %1$d string %2$s. String %2$s, number %1$d',array(1,"no"));
Yes, it is limited... And you would need to maintain the indexes. But it's native to the language and (i think) fast.
I just want some thoughts on how useful this would be as say a second stage to something like this: http://www.techfounder.net/2008/11/18/oo-php-templating/.
(and if anyone knows about printf/vprintf's speed that would be appreciated)
full example of what i'm talking about:
frontpage.php:
<html>
<head>
<title> %1$s </title>
</head>
<body>
Hello %2$s! You have reached page: %1$s!
</body>
</html>
whatever.php:
ob_start();
include frontpage.php;
$ob_output = ob_get_clean();
vprintf($ob_output,"Page Title","Bob");

If you want cheap PHP templating, use separate files with PHP expression blocks. It is possible to make a templating system using printf-style format strings, but there are two main problems I can see with this approach: speed and readability. The printf functions are intended for use on shorter strings, and although I don't have any statistics on hand, I think it's safe to say that running a sprintf() or a vprintf() on one huge string representing the page body will be slower than just using PHP expression blocks in a file.
That leads into the next issue: readability. Compare these two HTML templates:
<html>
<head>
<title>%s</title>
</head>
<body>
<div id="main">
<h1>%s</h1>
<p>%s</p>
</div>
<div id="other">
<p>%s</p>
</div>
<p id="footer">
%s. Took %.2f seconds to generate.
</p>
</body>
</html>
and
<html>
<head>
<title><?= $title ?></title>
</head>
<body>
<div id="main">
<h1><?= $header ?></h1>
<p><?= $body_text ?></p>
</div>
<div id="other">
<p><?= $misc_info ?></p>
</div>
<p id="footer">
<?= $copyright ?>. Took <?= $load_time ?> seconds to generate.
</p>
</body>
</html>
Or, let's say I had decided to use format strings with indexed arguments. Say, something like this:
<h1>%1$s</h1>
<p>%2$s</p>
<span id="blah">%3$s</p>
<p>%4$s</p>
<p>%5$s</p>
Now, what if I wanted to switch the ordering around?
<h1>%1$s</h1>
<p>%3$s</p>
<span id="blah">%5$s</p>
<p>%4$s</p>
<p>%2$s</p>
These are obviously contrived, but think about how it would be to maintain the printf templates in the long run.
So, in general, if you want quick-and-dirty PHP templating, use template files that contain PHP expression blocks. The printf functions are a lot better at tackling smaller string formatting tasks.

I generally have two files:
A controller of some sort (recipes.controller.php rewritten to /recipes/123)
One of many views for a controller (recipes.view.html)
I simply do all of the logic/database work within the controller and then include the appropriate view at the end. The view has access to all of the variables in the controller so I already have things like $title, $ingredients[], etc. created. I'm not really sure why people make it any more complicated than that. It's very easy to follow.
The view file will basically just look like this:
<html>
<head>
<title><?=$title ?></title>
</head>
etc...

Rasmus Lerdorf, creator of PHP, prefers to include his variables something like this:
<select class="f" name="cat" id="f_cat" size="1">
<option selected>Category</option>
<?php foreach($categories as $cat) echo <<<EOB
<option value="{$cat}">{$cat}</option>
EOB;
?>
For reference, <<<EOB through EOB; is a heredoc.
Source: The no-framework PHP MVC Framework by Rasmus Lerdorf

Related

A different angle on How to write html code inside php?

We write PHP code inside the HTML code via <?php ... ?> tags. So normally it would not make sense to write HTML code inside PHP code that is already inside HTML code, if you can just exit the PHP for the lines you need. But what if you need the HTML code in the same line as you have the PHP code?
My example would go like this:
<div>
<?php ($bool) ? <script>...</script> : <script></script> ?>
</div>
Is this:
<div>
<?php if($bool): ?>
<script>...</script>
<?php else: ?>
<script>...</script>
<?php endif; ?>
</div>
the only way?
Note: instead of <script> you could have <h1>, <strong>, <title> or any other "one-liner".
Thank you in advance.
Sure, alternative syntax would be the way to go when you have multiple lines of HTML, as you already stated...
However, for one liners, you can shorten <?php echo '...' ?> with <?= '...' ?> and wrap your HTML within single or double quotes, depending if you are already using double quotes within your HTML syntax. You may also escape them if you like, but that'd be messy.
<div>
<?= ($bool) ? "<script>...</script>" : "<script></script>" ?>
</div>
In order to print any string into your html code from PHP snippets use echo function.
http://php.net/manual/en/function.echo.php
So you just need to add echo
<div>
<?php
if($bool) {
echo '<script>...</script>';
} else {
echo '<script>...</script>';
} ?>
Stumbled upon this and decided to answer my own question just to point other newbies in the right direction.
Important note: Nowadays I'm using Laravel Framework and if you don't know it, you should definitely get to know it (there are alternatives though).
But I started following MVC architecture strongly even before that. So even before Laravel's Blade templates, my views looked something like the following.
<html>
<body>
<?php if ($isUserAuthenticated) : ?>
<div>
<span>Welcome <?= $username ?>
</div>
<?php else : ?>
Login
<?php endif ?>
</body>
</html>
As you can see there is absolutely no data manipulation in the view.
I also tried my best not to store any HTML strings into variables, but sometimes it makes for less code, so I did something like the following.
$alert = match($errorCode) {
1 => <<<HTML
<div class="alert alert-danger">Big error</div>
HTML,
2 => <<<HTML
<div class="alert alert-warning">Small error</div>
HTML,
default => ""
};
That way I can keep syntax highlighting (in VSCode) for HTML.
Note: match expression is new in PHP8, but you could achieve the same before with a switch statement.

Assign php code to smarty template engine

I make a new website for my company and i want to use smarty (v3.1.29) for it. Now the problem is that we store the code for all pages in our database (home, products, downloads, ...). Some pages contains PHP inline functions like:
<?php include("functions.php"); ?>
<p> Hello <?php echo printWorldInColor(); ?> </p>
In my template (.tpl) file I have a div-section to load the content from our database:
<html>
<body>
<div id="content">
{$content}
</div>
</body>
</html>
So my code looks like this afterwards:
<html>
<body>
<div id="content">
<?php include("functions.php"); ?>
<p> Hello <?php echo printWorldInColor(); ?> </p>
</div>
</body>
</html>
Is there a way that smarty processes the PHP-code before parsing it?
Hint: I dont want to edit my template file. I just want to parse the database content to my content-section of the website.
What i tried:
saved database-content into a string and replaced PHP-tags with smarty-PHP-tags, then assign it to the template
SmartyBC-Class
You can't do that in Smarty. Also running php code stored in the database sounds like a terrible idea. But if for some reason you have to go on with this nonsense (and considering that you can't use eval), you can try this:
Read the php code from the database.
Save to a temporal php file
Turn on output buffering with ob_start()
include the file you have created
assign the output to a variable with ob_get_clean()
assign the variable to the template
But if I was you, I would try to do the project in another way.

Reusable user interface in PHP?

For most of my projects I make an administration interface, which has the same design for every project. The design of the header, the footer, the topbar, the leftmenu, the css, etc. are always the same. It is a pity to create the views every time; so I was thinking: maybe there would be a nice way to put the admin interface in my MVC library, as it is reused by every project?
But for the moment, in every single view I got code like the following:
<?php $this->_include('/includes/doctype.php'); ?>
<head>
<?php $this->_include('/includes/head.php'); ?>
<title>Some title</title>
</head>
<body>
<?php $this->_include('/includes/topbar.php'); ?>
<div id="page">
<?php $this->_include('/includes/header.php'); ?>
<?php $this->_include('/includes/leftmenu.php'); ?>
<div id="content" role="main">
<h1>Some title</h1>
<p>Blah blah blah.</p>
</div><!-- /#content -->
<?php $this->_include('/includes/footer.php'); ?>
</div><!-- /#page -->
</body>
</html>
Would it be a good idea to extract the custom content from the structure of the interface, and put that structure in my library somehow to make it reusable?
After that how will it be possible to customize the title and the actual menus?
I do this all the time. I have a custom header and footer file that are called at the start and end of every page.
<?PHP
Require("includes/header.php");
...
Require("includes/footer.php");
?>
The header provides a database handle, a datetime string and handles logon, priveleges, logging of pageviews etc.
The footer provides a standard HTML page but includes some systematised variables. It also generates the menu dynamically from the driving database then closes the database connection.
This way when I write code, I don't get mixed up in the HTML and any bugs are easy to find.
I like variables akin to:
$display_scripts - adds extra data in the head section.
$display_onload_scripts - adds onload scripts to body section.
$display_style_sheets - option to include link to additional stylesheets
$display_above_menu - will appear above the menubar. NOT recommended.
$display_below_menu - will appear immediately below the menubar.
$display_one_column - page contents when only one column is to be used
$display_left_column - page contents when two columns used. Left pane.
$display_right_column - page contents when two columns used. Right pane.
$display_footer - appears in footer division.
My main code then just has to generate the appropriate variable. Fundamentally, what you need to do is examine the source of a good age you have produced then replace the stuff you want to change with variables.
Here is a schematised version of the file I use (pseudocode) to give you an idea of how I do it.
// Code here generates the menu from database
// Code here genereates popup alert messages from other users
//permanent links to external style sheets go here.
//You can also select skins here.
<?PHP
echo $display_style_sheets;
echo "<title>".$display_page_title."</title>";
?>
<script type="text/javascript" src="JAVASCRIPT GOES HERE.js"></script>
</head>
<body <?PHP echo $display_onload_scripts;?> >
<div id="page_area" >
<div id="banner">
</div>
<?php
echo $display_above_menu;
if(!$hide_menu){echo $display_menu;} //Insert the menu variable here.
echo $display_below_menu;
?>
<div id="content_area">
<div id="inner_content">
<?PHP
if($display_number_of_columns==1)
{
echo "<div id='onecolumn'>".$display_one_column."</div>"; //I only use this one
}
if($display_number_of_columns==2)
{
echo "<div id='leftcolumn'>".$display_left_column."</div>"; //these are left for legacy support from before I got better at CSS.
echo "<div id='rightcolumn'>".$display_right_column."</div>";
}
echo "<div id='footer'>".$display_footer."</div>"; //just in case - I hardly use it.
echo $display_pop_box; //for user alert messages to other users
?>
</div>
</div>
</div>
<div id="logbox"> Automatic Logout statement</div> //this is called by JS to activate timeouts.
</body>
</html>
<?PHP
$mysqlidb->close();
?>
Sorry it's such a lot of code. The layout allows easy adaptation and makes it simple to find the offending variable if things are not going as expected. There are more elegant solutions but this works well for me and is very fast.

Fixing HTML spacing issues from nested PHP

This is something that has always bothered me about PHP and I have never found an answer. Hopefully this example will provide enough information to understand my question, as I don't know how to explain it thoroughly in words.
Here is some PHP inside of HTML, in a .php file. This type of things occurs pretty often:
<html>
<head>
<!-- whatever -->
</head>
<body>
<section id="content">
<ul class="errors">
<?php
foreach ($errors as $error)
{
?>
<li><?= $error ?></li>
<?php
}
?>
I have disregarded the end tags of the HTML and used <?= shortcuts to avoid any unnecessary text.
Now, here is what expect in the HTML output (i.e., right-click -> view source):
<html>
<head>
<!-- whatever -->
</head>
<body>
<section id="content">
<ul class="errors">
<li>Example Error</li>
However, here is the actual result:
<html>
<head>
<!-- whatever -->
</head>
<body>
<section id="content">
<ul class="errors">
<li>Example Error</li>
Why? Because the foreach loop from PHP is indented 3 tabs in, so the <li> it is generating gets an ADDITIONAL 3 tabs. The solution I have been using? Here:
<html>
<head>
<!-- whatever -->
</head>
<body>
<section id="content">
<ul class="errors">
<?php
foreach ($errors as $error)
{
?>
<li><?= $error ?></li>
<?php
}
?>
Sure, this works - but man is it ugly! It seems like I have two options: make my HTML output ugly and my code readable OR make my HTML readable and my code ugly. Why can't I have both? Is there no other way?
The best thing to do, I guess, is make the code readable and the output ugly. Who checks the source code anyway? I know this is probably the most popular reaction. Ugly HTML source code just bothers me, and I wish there was a way around it without sacrificing PHP code readability.
php code doesn't generate any indents on the page. What's generating the indent is the indent in the
<li> line</li>
What you can do is: use echo to output it
<?php
foreach ($errors as $error)
{
echo "<li>$error</li>";
}
?>
Or you could do:
<?php
foreach ($errors as $error)
{?>
<li><?=$error?></li> /(indent it in the begining as much as you want in the markup)
<?}
?>
Although, imo, you needn't worry about how the markup looks. Its not important. Indents have no effect on the output
One solution would be to use the output buffer functions in PHP to buffer all HTML output, and then post-process it to indent everything properly.
See this other question on the topic:
How to properly indent PHP/HTML mixed code?

Are there any more Unobtrusive Server-side Scripts like hQuery for easier templating?

I came across this interesting templating tool, what the author calls as hQuery which is an 'Unobtrusive Server-side Scripting'. [More information here - https://github.com/choonkeat/hquery ]. It is built in Ruby for the RoR platform.
I wanted to know if something similar is available for other platforms (PHP, Python, Java)
PS : I know about templating engines like smarty and twig. I'm looking for something closer to hQuery.
Not that I know of, but I have been doing something similar in concept, although a lot more simple, in PHP using phpQyery and some custom html-like markup.
For instance, here is a simplified non-standard html chunk:
<bodynode>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<div class="holder">
<article>
<header class="col_12f">
<component id="logo"></component>
<component id="address"></component>
<component id="languages"></component>
<component id="mainmenu"></component>
</header>
<section id="banner">
<component id="maingallery"></component>
<component id='sideMenu'></component>
</section>
<section class="col6 first" id="intro_title">
<h1 class="underlined"></h1>
<section class="col3 first" id="intro_col1"></section>
<section class="col3 last" id="intro_col2"></section>
</section>
<section class="col3" id="location"></section>
<section class="col3 last" id="services"></section>
</article>
<div class="clear"></div>
</div>
<component id="footer"></component>
</bodynode>
Using phpQuery, which works server-side with XML and HTML Dom Nodes, in a way very similar to jQuery, I map all tags with content coming from the db, using their ID as key. as well as all <component></component> tags with custom output from functions. So the existence of a <component id="logo"></component> would cause the call of a function called component_logo, using:
function replaceComponents ($pqInput){
$pqDoc = phpQuery::newDocument($pqInput);
$comps = pq('component');
foreach ($comps as $comp){
$compFunc = 'component_'.pq($comp)->attr('id');
pq($comp)->replaceWith($compFunc($comp));
}
return $pqDoc;
}
and
function component_logo($comp){
$pqComp = phpQuery::newDocument(file_get_contents('Templates/Components/logo.component.html'));
$pqComp->find('a')->attr('href','/'.currentLanguage().'/')->attr('title','Website Title');
$pqComp->find('img')->attr('src','/Gfx/logo.png');
return $pqComp;
}
Although it's not based on a MVC pattern and uses straight procedural programming, so far this method has allowed for a very quick development of small to medium sized sites, while keeping things nicely DRY.
I don't like using other templating engines much, really because I find them a little to heavyweight for anything I actually want to do (smarty for example).
There is a school of thinking that would say: PHP is already a templating engine... why build templates within templates?
I do disagree with this to an extent, I find templating very useful in abstracting HTML from PHP code.
Below is an edited method from my templating class that I use that will explain how easy it is to actually make yourself.
$params = array("<!--[CONTENT]-->" => "This is some content!");
$path = "htmltemplates/index.html";
$html = implode("",file($path));
foreach($params as $field => $value) {
$html = str_ireplace($field, $value, $html);
}
echo $html;
There is quite a bit more meat around this, but this is the core code. Read a file into an array, implode, search through the $params array and replace $field with $value in $html. Output the edited $html.
your index.html file will look something like:
<html>
<head>
<title>This is a template</title>
</head>
<body>
<div id="page-container">
<!--[CONTENT]-->
</div>
</body>
</html>
Your output will be:
<div id="page-container">
This is some page content!
</div>
Maybe look at implementing your own templating engine! :)

Categories