homepage Welcome to WebmasterWorld Guest from 54.167.75.155
register, free tools, login, search, pro membership, help, library, announcements, recent posts, open posts,
Become a Pro Member
Visit PubCon.com
Home / Forums Index / Code, Content, and Presentation / PHP Server Side Scripting
Forum Library, Charter, Moderators: coopster & jatar k

PHP Server Side Scripting Forum

    
PHP Variable Substitution Tricks
separating HTML and PHP code
incrediBILL




msg:4386379
 7:43 am on Nov 13, 2011 (gmt 0)

Basically, I like to keep the design and code separate as much as possible which allows the designer to keep designing and the programmer programming without stepping all over each other, or one waiting on the other to complete something, speeds up projects and allows a broader use of WYSIWYG design tools like DreamWeaver or MS Expression Web over the full lifetime of the project/site for quicker changes.

With that in mind, I prefer doing full page designs with variables embedded and substituted on the fly without having to put snippets of PHP code in the HTML source itself, or worse yet, having HTML intertwined all over a page of PHP code.

IMO, it's easier to implement sites when you separate design from code, the way I've been doing it in other platforms for ages. Code and HTML all mixed together is something I've always disliked about how most implement their PHP code and sites.

Includes don't cut it unless you just want to include a generic header and footer without any dynamic variables included in the code.

Maybe there's an easier way of doing this, but this is the best I've come up with so far.

$mystr = file_get_contents("somepagedesign.html");
eval("\$mystr = \"$mystr\";");
echo $mystr;


The above will basically read in a chunk of HTML and then substitute any $variables found in that HTML without having to have any inline PHP code in the HTML page itself. This method simplifies putting variable data back in forms, especially lengthy forms, among many other things.

Assuming the following variables in PHP:
$ip="127.0.0.1";
$ua="Internet Explorer 7.0";


And following HTML was contained in somepagedesign.html:
<p>Your IP address is: $ip<br>Your user-agent is: $ua


The code above would display:
Your IP address is: 127.0.0.1
Your user-agent is: Internet Explorer 7.0


I find it's actually much faster to code pages this way and with a few tricks, you can even call out subsections of a page for displaying tables of data, etc.

So the question is, is this the best way to do this or are there other PHP tricks for accomplishing a cleaner separation of HTML and PHP code that supports variable substitution that I'm not aware of?

 

bibel




msg:4386642
 9:16 am on Nov 14, 2011 (gmt 0)

That method is very susceptible to errors.
You should take a look at a template engine like Smarty.

brotherhood of LAN




msg:4386702
 1:53 pm on Nov 14, 2011 (gmt 0)

vsprintf and similar are good options.

[php.net...]

- %s placeholders for your variables
- All other %'s have to be escaped to %%

incrediBILL




msg:4386722
 2:25 pm on Nov 14, 2011 (gmt 0)

Smarty is still programming within the web page, doesn't truly fit the real separation of HTML and PHP issue whatsoever. Plus you have to learn all the Smarty syntax, not what I had in mind really.

vsprintf() won't really process an entire HTML page in one shot without knowing how to format it. I just want to embed $variables anywhere on the page without regards to location and be able to print the entire page in one shot, including those variables substituted in the HTML, which my simple like my 3-line code sample above already does without knowing the format.

Why PHP doesn't have any straight forward HTML template options, other than something like Smarty, seems kind of bizarre considering the size of the developer base.

jatar_k




msg:4386724
 2:30 pm on Nov 14, 2011 (gmt 0)

you could always go to a fully implemented MVC framework, keeping all your display in the view sans logic is kinda the point. Though I see a lot of 'model-less' implementations where it's mainly controller with views.

I know people want a pure way but I will argue once again that [art of why php made it here is becaus eit can never truly be separated, nor should it.

but an MVC structure/framework should suffice.

brotherhood of LAN




msg:4386729
 2:34 pm on Nov 14, 2011 (gmt 0)

>vsprintf() won't really process an entire HTML page in one shot without knowing how to format it.

It is output as soon as it is encountered (it's not stored anywhere new), and the processor should know how to format it as the PHP code is already been interpreted before execution.

jamie




msg:4386753
 3:30 pm on Nov 14, 2011 (gmt 0)

another vote for smarty.

it's almost impossible not to have some sort of programming logic in templates, and the fine thing about smarty is that in design view (dreamweaver), our designers can see the if/else smarty structures, as opposed to just a php placeholder - giving them more understanding of how the page is generated. (i also find it easier to scan through html templates with smatterings of smarty rather than php - but that's just a personal opinion)

i know it means learning another syntax, but for a professional webmaster these days who knows at least 4/5 (html/js/css/php/sql, etc), it's not that big a deal. and with a bookmarklet, the online manual is easy to search to look up syntax.

rocknbil




msg:4386788
 4:50 pm on Nov 14, 2011 (gmt 0)

Code and HTML all mixed together is something I've always disliked about how most implement their PHP code and sites.


WORD!

I don't like frameworks of any sort either. No reason to buy the whole building when you're only using one or two rooms in it. I use a process similar to your but with agreed markers.

[CONTENT]

For variable formatting chunks, I create "pieces"

[PRODUCT_DISPLAY]

I assign classes and/or ID's to all chunks output by the program, so anything generated by the program can be accessed by style sheets and Javascript.

Rather than file_get_contents, I prefer to parse the files line by line to sub out the variable chunks. I don't think it's any faster (or slower) but makes it easier to see what exactly is going on.

incrediBILL




msg:4386879
 9:00 pm on Nov 14, 2011 (gmt 0)

It is output as soon as it is encountered (it's not stored anywhere new), and the processor should know how to format it as the PHP code is already been interpreted before execution.


I should be able to rearrange the variables on any HTML page without changing code, can't so that with vprintf, you have to reorder the format string to match the order of the variables. The little aval() command does them in any order at any time ;)

t's almost impossible not to have some sort of programming logic in templates


Define impossible.

Not too hard unless you're a javascript junky ;)

Readie




msg:4386886
 9:32 pm on Nov 14, 2011 (gmt 0)

Code and HTML all mixed together is something I've always disliked about how most implement their PHP code and sites.


I approve of this comment.

But yea, pretty much agree with what Rocknbil said - I don't go for Smarty because it has so much more than I need. Just a template processing class and a standard for inserting variables !v{VAR_NAME}v!.

Just bear in mind you need to be careful with user defined content - you need to take steps to prevent people inserting variables into their comment. One of my earlier implementations had a while(preg_match()) - can infinite loop it if you have a variable that calls itself.

incrediBILL




msg:4386888
 9:40 pm on Nov 14, 2011 (gmt 0)

It should generally be the very last variable name to be processed so someone cannot insert one of your variables into their comment.


That's why I religiously process all user content through strip_tags() which cleans out any embedded HTML and PHP tags, plus some MySQL stripping as well.

Readie




msg:4386892
 9:46 pm on Nov 14, 2011 (gmt 0)

The problem with just stripping it out is if a user has a legitimate reason for using that text, they can become frustrated. I've bumped into it on forums before, and it's really, really annoying.

It's not so much a problem with my implementation, where it's a rather obscure string of characters, but if someone is using the system Rocknbil showed above, where it's just a name in square brackets, that could cause issues coupled with your sanitisation.

incrediBILL




msg:4386896
 9:55 pm on Nov 14, 2011 (gmt 0)

The problem with just stripping it out is if a user has a legitimate reason for using that text, they can become frustrated. I've bumped into it on forums before, and it's really, really annoying.


Easily solved where UGC that needs to go through unfiltered. The author can be place that code between a couple of tags in the identifying it as code which allows the filtering process to sandbox that code and filter everything around it, then pass it through unprocessed and don't execute it either.

Translating <'s and >'s to &lt's and &gt's in the UGC tagged code pretty much neuters any embedded HTML for the sandboxed code.

It's all about cross the T's and dotting the I's. ;)

eelixduppy




msg:4386974
 12:58 am on Nov 15, 2011 (gmt 0)


eval("\$mystr = \"$mystr\";");


This perhaps has issues when including quotes or other special character in the template file, yes?

>> Smarty is still programming within the web page,

It doesn't have to be. If it suits you to do straight substitution, you can do that, too.

Let me ask you this, though. If you needed to populate in the html page a table with data from a database, how would you go about doing it using your method and still separate the content from the programming logic?

Readie




msg:4386979
 1:30 am on Nov 15, 2011 (gmt 0)

The author can be place that code between a couple of tags in the identifying it as code


It's still kinda nasty though. I don't expect my users to be aware that !v{[a-z_\d]+}v! is reserved for the template, so I try to go to pains to prevent their comment from getting parsed as such. Now that I think about it though... I could just convert the curly braces to their entitys (&123; and &125; )...

Let me ask you this, though. If you needed to populate in the html page a table with data from a database, how would you go about doing it using your method and still separate the content from the programming logic?


2 template files. One for wrapper (containing <table> ) and one for a complete tr. The tr is built up multiple times into a variable, which is then passed into the template processor for the next template.

eelixduppy




msg:4386985
 1:39 am on Nov 15, 2011 (gmt 0)

>> 2 template files.

So a modification to the table requires touching two different template files? Also, what if I have 10 tables? (10 extra template files for a single page? eew) What if I want to conditionally format the tables?

The point being, there is no simple, clean way to do this.

I think Smarty and other frameworks do a decent job of addressing these issues in a rather straightforward way.

incrediBILL




msg:4387002
 3:19 am on Nov 15, 2011 (gmt 0)

I actually have quite a bit of logic in the code besides that 3 line snippet eval() example, it's an entire class actually. I was just getting tired of building the class and looking for a replacement if something was suitable and I'm not finding exactly what I want so maybe I'll just keep working on my class library.

I prefer to parse the files line by line to sub out the variable chunks.


After reading the entire file in, I explode each printable area into an array using the special comments that tag each printable area of the page such as...

"<!-- tagname="menu" --!>"

So my function PrintTemplateTag() returns all the HTML between the specified tagname in the template file and the next tagname, or end of file, whichever comes first. A default template tag "HEADER" prints from the beginning of the HTML page to the first tag encountered, so printing a page using my templates, with a loop in it for repeating data looks kinda like this:

PrintTemplateTag("header");
PrintTemplateTag("body");
for( x=1; x<11; x++; ) {
$list_item="This is line #" . x;
PrintTemplateTag("list");
}
PrintTemplateTag("footer");


The reason I use actual comments is because the browsers and developer studio tools all work with them and handle them just fine, and they can be hidden and unhidden as needed without mucking up the template with a bunch of visible junk.

What if I want to conditionally format the tables?

The point being, there is no simple, clean way to do this.


Regarding tables, I print them from within the template.

Here's how I do a table for instance...

the HTML looks like this:
<!-- tagname="itemlist --!>
<table>
<tr><td>$title</td></tr>
<tr><td>$rowdata</td></tr>
</table>


My class that prints stuff can call out each row of a table by line number or if you want to insert comments between the row, by name. When the PrintTagnameTable() function is first called it extracts the entire table into a buffer and explodes the rows into an array, therefore repeated printing of rows is very fast, thus giving the same working functionality without putting tables in separate files.

The code to print a table looks like this:
PrintTagnameTable("itemlist",table_start);
$title="whatever";
PrintTagnameTable("itemlist",1);
for( x=1; x<11; x++; ) {
$rowdata="This is data row " . $x;
PrintTagnameTable("itemlist",2);
PrintTagnameTable("itemlist",table_end);


The table_start prints everything from the tagname preceding the <table> to the first row <tr> and the table_end prints from the everything from the last </tr> including the </table> to the next tagname, but I'm contemplating making it just print the end of the table only without continuing to the next tagname, who knows.

What do you think of that method?

So other than a few comments and a couple of variables in the pages, this stuff looks very good in a WYSIWYG interface or just previewing in a browser for that matter, real close the the final web page display opposed to Smarty or such, which is what I'm after, actually seeing the design and not all the code when designing.

Being fundamentally lazy ;) I was hoping someone had done something closer to what I want besides Smarty, or some of the other heavy frameworks, but it's sounding like I need to just toss the use of eval() to avoid errors and do my own variable replacement code and call it a day.

I also use this class for creating email templates, plain text or HTML, the code really doesn't care if it has any HTML in it except for the tagname comments, so using it to create an email template actually works really well too.

I really don't want to write the code, I just want to use the code, but I can't find what I really want.

It's like the people building PHP only focus on what the programmers want and really don't give that much thought into the fact that ultimately it's a web page, and being able to integrate with templates should be an integral part of the language and not left up to a bunch of 3rd party template libraries, getting us all on the same page (pun intended).

Damned annoying.

rocknbil




msg:4387238
 5:12 pm on Nov 15, 2011 (gmt 0)

where it's just a name in square brackets, that could cause issues coupled with your sanitisation.


No - the substitution in the template takes place long after input has been cleansed. For example, this forum, and others, using the [phpBB syntax], that all gets parsed out and put into a chunk, say, $content, and $content replaces [CONTENT]. just in the template output function.

Readie




msg:4387276
 6:39 pm on Nov 15, 2011 (gmt 0)

Rocknbil::

I was speaking more to say "be careful how you code it" - if it's like my first implementation of my class, which was something along the lines of:

while(preg_match('/\!v\{([A-Z_\d]+)\}v\!/sm', $html, $match)) {
if(!isset($vars[$match[1]])) {continue;}
$html = str_replace($match[0], $vars[$match[1], $html);
}


Then, say I include a user's comment in the variable "USER_COMMENT" - that user could cause me a headache by entering the string "!v{USER_COMMENT}v!" into their comment.

So my comment was really just saying, if someone were to use similar logic to my above, it's more likely to be an issue using just square brackets as it's more likely to be a string that someone innocently enters into their text.

Readie




msg:4387284
 6:50 pm on Nov 15, 2011 (gmt 0)

Double posting like a boss ;)

My class that prints stuff can call out each row of a table by line number or if you want to insert comments between the row, by name. When the PrintTagnameTable() function is first called it extracts the entire table into a buffer and explodes the rows into an array, therefore repeated printing of rows is very fast, thus giving the same working functionality without putting tables in separate files.


I do quite like the general logic behind this - it's got me thinking of something along the lines of

<table>
!c{loop:SOME_VAR_NAME}c!
<tr>
<td>!v{SUB_VAR_1}v!</td>
<td>!v{SUB_VAR_2}v!</td>
</tr>
!c{endloop:SOME_VAR_NAME}c!
</table>


My parser can then pick up on the loop / endloop, and look for the variable "SOME_VAR_NAME" in my $vars array - which it will expect to be an associative array something like:

$vars['SOME_VAR_NAME'] = array(
array(
'SUB_VAR_1' => 'a',
'SUB_VAR_2' => 'b'
),
array(
'SUB_VAR_1' => 'c',
'SUB_VAR_2' => 'd'
),
array(
'SUB_VAR_1' => 'e',
'SUB_VAR_2' => 'f'
)
);


And it'll foreach through that, replacing the block between the !c tags.

Thanks for that thought... :)

httpwebwitch




msg:4388186
 5:16 pm on Nov 17, 2011 (gmt 0)

incrediBill, I recommend Smarty too.

The syntax is easy to learn, and it does exactly what you want in a tried & tested & optimized way. templates are pre-compiled, substitutions are easy to manage... it does everything right.

It is essentially "the" templating engine for PHP.

There are substitution strategies you can use that employ ob_start() and ob_get_contents() and all the other ob_ functions, rolling your own templating using preg_match(), eval() etc... it's all just reinventing the wheel.

enigma1




msg:4388240
 8:02 pm on Nov 17, 2011 (gmt 0)

IMO none of the template systems does the job. They increase overhead in general, its another interpreted language you need to learn and because of the massive segmentation of the html it increases the time to do something.

Now having php/html spaghetti code also has disadvantages. You may have one or two files to work with, but the code becomes hard to manage or read pretty quick. With templates the code maybe more manageable but it splits over multiple files and takes longer to debug or change something.

So there should be a balance and not only. You don't want to search 50 files on the one hand, because the html is so segmented and at the same time you may have to work with web2.0. These dynamic scripts can be a pain if the framework isn't designed to support them. You may spend ages to implement ajax, replicating code all over the place to have support for both regular and ajax requests.

And unfortunately the current structure of PHP doesn't make things easy although it began as a template language - which is an oxymoron.

The closest I thought of is to use some common sections as templates and leave the rest of code with mixed html and php. It's not something rigid so I can always move more stuff into templates, increase the number of php files a bit to support ajax but keep it as flexible as possible.

In terms of actual implementation, I won't use eval, for example I will use "include" or other native php functions to load other php/html segments when necessary. The include for instance won't give an error if the segment isn't there it can work as an option. So I could include the same number of segments for all pages but point to a separate folder to make exceptions if required and generate different layouts. So I could avoid template scripting at the top of the html.

eelixduppy




msg:4388390
 3:07 am on Nov 18, 2011 (gmt 0)


it's got me thinking of something along the lines of...

This is looking awfully a lot like what Smarty looks like with a lot less flexibility.



They increase overhead in general


I find it hard to believe any web apps are mission critical services requiring perfect optimization with virtually no overhead. If that were the case, you wouldn't be using an interpreted language in the first place. Trust me, Smarty's overhead is minimal and will go unnoticed; it even has a caching mechanism built in if you choose to use it.


With templates the code maybe more manageable but it splits over multiple files and takes longer to debug or change something.


This to me seems to contradict itself. If code it more manageable, how does it become harder to manage? ;)

I know most people here work on their own websites alone but using a well known templating framework such as Smarty allows someone who is unfamiliar with your website to come in and just start making changes. Plus, you don't need to spend valuable resources on maintaining a proprietary framework.

But if you are really inclined and want total control over how your template framework operates, Smarty (as well as others) are completely open source projects. Have at it -- at least you'd be starting with a pretty solid base to work from.

incrediBILL




msg:4388403
 3:56 am on Nov 18, 2011 (gmt 0)

I find it hard to believe any web apps are mission critical services requiring perfect optimization with virtually no overhead.


In my case, I was complaining about the bloat in library overhead.

I hate installing all those big fat libraries, and having to keep them updated when someone finds a flaw and the hackers hit.

Might as well use WordPress!

eelixduppy




msg:4388404
 4:11 am on Nov 18, 2011 (gmt 0)

>> and having to keep them updated when someone finds a flaw and the hackers hit.

Don't see how this would be any different if you were to roll your own. You're going to have some aspect of upkeep regardless of what you use to get the job done.

I personally would rather replace the 2 directories Smarty is contained in with 2 new ones and be done, rather than find out how someone is exploiting my code and writing a patch for it myself.

>> Might as well use WordPress!

hah, now that's a different story.

incrediBILL




msg:4388425
 5:43 am on Nov 18, 2011 (gmt 0)

Don't see how this would be any different if you were to roll your own.


When you roll your own:

a) the hackers don't have source code to review and...

b) there aren't any generic footprints to find using SEs and...

c) if you find a problem, you can probably fix it quickly without waiting on someone else to make a patch!

That good old security through obscurity, it does work for the most part.

Smarty, as popular as it may be, still has too much crap in the template for my tastes.

Been working with templates for years that were really abstracted at a high level from the code. Not sure at this stage in the game I can stomach going to what I consider a hiuge backwards.

Not that I won't keep an open mind, but I'm not happy with it so far.

enigma1




msg:4388466
 8:51 am on Nov 18, 2011 (gmt 0)

This to me seems to contradict itself. If code it more manageable, how does it become harder to manage? ;)

Because you have more files, you always need others who also know the same languages is difficult to maintain and further develop. Try to search 50 files to modify some code remotely instead of 5. Check the frameworks who use template systems. Files filled with few lines of code and in some cases empty files which supposedly serve as placeholders for application expansion, user hooks which almost never used etc.

And so the smarty template as every other traditional template system adds another layer to the top of the framework. Another scripting language to learn (and why?), whether you want it or not, is going to take longer to execute, harder to find other developers who use the combination of languages you use and more difficult to port code from other open source software. And if you think you have something modular in the end you don't. You have something more convoluted.

using a well known templating framework such as Smarty allows someone who is unfamiliar with your website to come in and just start making changes.


About unfamiliar with the code now, If you really want to use a template system, it can be done via a user interface and be pretty much independent from the actual code of a framework and transparent to users and developers. Create and position the layout sections around pages with drag and drop have a graphical interface etc. Then whether developers or users use the interface is up to them. You don't add anything extra to the code this way. And so you don't force anyone to learn another scripting language, it becomes optional. The code doesn't have an extra template layer that you have to learn. The drawback is of course such an interface with the application is very specific and requires tremendous work.

Another reason you will see this type of resistance these days is because of the typical site requirements and framework details. So you need to know html, css, xml, js, php, sql, server and o/s specifics in many cases. Plus the code differences due to versions of each of those, plus the frameworks at the top of each of these languages split in different layers - that's only coding - and then you say that another layer via a template makes our life easier. It doesn't.

Global Options:
 top home search open messages active posts  
 

Home / Forums Index / Code, Content, and Presentation / PHP Server Side Scripting
rss feed

All trademarks and copyrights held by respective owners. Member comments are owned by the poster.
Home ¦ Free Tools ¦ Terms of Service ¦ Privacy Policy ¦ Report Problem ¦ About ¦ Library ¦ Newsletter
WebmasterWorld is a Developer Shed Community owned by Jim Boykin.
© Webmaster World 1996-2014 all rights reserved