I'm trying to figure out the most efficient way to implement RoR-style partials/collections for a PHP template class that I'm writing. For those who aren't familiar with rails, I want to iterate over a template fragment (say a table row or list item) located in a separate file. I want to do this without resorting to eval or placing an include within the loop.
I've seen a similar post that addresses single partials, which are trivial, but nothing that covers implementing partials in a collection. I've been thinking about this so long my head hurts and I'm afraid I'm overlooking an obvious solution. I'm hoping someone here can suggest an elegant solution that, again, doesn't require eval or include within the loop. TIA.
You need a templating engine with that can process includes on its own and then eval the whole thing at once. Much like c preprocessor works.
Step 1 (source template):
$template = '
foreach($bigarray as $record)
#include "template_for_record.php"
'
Step 2 (after preprocessing):
$template = '
foreach($bigarray as $record)
// include statement replaced with file contents
echo $record['name'] etc
'
Step 3 (final rendering)
// eval() only once
eval($template);
In this way you can avoid the overhead of evaling/including subtemplate on every loop step.
You're asking how to do something without resorting to the solution.
Any template system you use is going to use an eval or an include within the loop, even if it's buried in abstraction 1000 layers deep.
That's just how it's done.
Related
What I keep seeing is something like
<?php $page_title = ""; ?>
<?php include_once("inc/header.php"); /* Include Header */ ?>
versus
<?php
$page_title = "";
include_once("inc/header.php"); /* Include Header */
?>
I assume there is no difference in functionality (not sure however), but which way is more semantic / correct does it matter if you declare all your PHP in several PHP blocks or a single one? Is performance affected in any way?
This is a major reason why doing your PHP inline is going out of style. There's no performance hit that I know of. All <?php ?> does is tell the interpreter that this is to be processed by PHP so your first code block is saying
Stop parsing PHP
Start Parsing PHP
I would imagine there's some miniscule hit somewhere if you're trying to wring every last ounce of efficiency out but I consider it to be insignificant. It's important to userstand that if you're using opcode cache (and you should) then the only hit is on the parsing side. Repeated execution of cache will have 0 effect here.
Readability, however, really does demand your code be as compact as possible. Remember, someone may come behind you and work on this code. Having two blocks where only one is needed is inefficient.
There is no real answer to this.
Some people like to have it the "Code-Block"-Way and put it all in one set of tags, some other people prefer the "HTML-Tag"-Way where they put each command in a new set of tags
There is no difference in functionality except for the fact that everything between one ?> and the next <?php gets echo'ed (So you have a lot of spaces in your output HTML, which is okay, since they are ignored)
Performance might be affected, but in numbers you really don't need to care about.
Generally, if you are in templates (or lets say, PHTML, HTML and PHP mixed), try to keep all commands single-lined (Put all single commands in <?php ?> and on own lines), this will make it more readable between all those HTML tags.
If you don't have HTML in your PHP file, there is no reason to enclose all commands with PHP tags
This question is about optimizing a part of a program that I use to add in many projects as a common tool.
This 'templates parser' is designed to use a kind of text pattern containing html code or anything else with several specific tags, and to replace these by developer given values when rendered.
The few classes involved do a great job and work as expected, it allows when needed to isolate design elements and easily adapt / replace design blocks.
The patterns I use look like this (nothing exceptional I admit) :
<table class="{class}" id="{id}">
<block_row>
<tr>
<block_cell>
<td>{content}</td>
</block_cell>
</tr>
</block_row>
</table>
(Example code below are adapted extracts)
The parsing does things like that :
// Variables are sorted by position in pattern string
// Position is read once and stored in cache to avoid
// multiple calls to str_pos or str_replace
foreach ($this->aVars as $oVar) {
$sString = substr($sString, 0, $oVar->start) .
$oVar->value .
substr($sString, $oVar->end);
}
// Once pattern loaded, blocks look like --¤(<block_name>)¤--
foreach ($this->aBlocks as $sName=>$oBlock) {
$sBlockData = $oBlock->parse();
$sString = str_replace('--¤(' . $sName . ')¤--', $sBlockData, $sString);
}
By using the class instance I use methods like 'addBlock' or 'setVar' to fill my pattern with data.
This system has several disadvantages, among them the multiple objects in memory (one for each instance of block) and the fact that there are many calls to string manipulation functions during the parsing process (preg_replace in the past, now just a bunch of substr and pals).
The program on which I'm working is making a large use of these templates and they are just about to show their limits.
My question is the following (No need for code, just ideas or a lead to follow) :
Should I consider I've abused of this and should try to manage so that I don't need to make so many calls to these templates (for instance improving cache, using only simple view scripts...)
Do you know a technical solution to feed a structure with data that would not be that mad resource consumer I wrote ? While I'm writing I'm thinking about XSLT, would it be suitable, if yes could it improve performances ?
Thanks in advance for your advices
Use the XDebug extension to profile your code and find out exactly which parts of the code are taking the most time.
I'm currently using this code:
$blog= file_get_contents("http://powback.tumblr.com/post/" . $post);
echo $blog;
And it works. But tumblr has added a script that activates each time you enter a password-field. So my question is:
Can i remove certain parts with file_get_contents? Or just remove everything above the <html> tag? could i possibly kill a whole div so it wont load at all? And if so; how?
edit:
I managed to do it the simple way. By skipping 766 characters. The script now work as intended!
$blog= file_get_contents("powback.tumblr.com/post/"; . $post, NULL, NULL, 766);
After file_get_contents returns, you have in your hands a string. You can do anything you want to it, including cutting out parts of it.
There are two ways to actually do the cutting:
Using string functions like str_replace, preg_replace and others; the exact recipe depends on what you need to do. This approach is kind of frowned upon because you are working at the wrong level of abstraction, but in some cases it has an unmatched performance to time spent ratio.
Parsing the HTML into a DOM tree, modifying it appropriately (this time working at the appropriate level of abstraction) and then turn it back into a string and echo it. This can be more convenient to work with if your requirements are not dead simple and is easier to maintain, but it typically requires more code to be written.
If you want to do something that's most naturally expressed in HTML document terms ("cutting out this <div>") then don't be tempted and go with the second approach.
At that point, $blog is just a string, so you can use normal PHP functions to alter it. Look into these 2:
http://php.net/manual/en/function.str-replace.php
http://us2.php.net/manual/en/function.preg-replace.php
You can parse your output using simple html dom parser and display olythe contents thatyou really want to display
Is there an standard output library that "knows" that php outputs to html?
For instance:
var_dump - this should be wrapped in <pre> or maybe in a table if the variable is an array
a version of echo that adds a "<br/>\n" in the end
Somewhere in the middle of PHPcode I want to add an H3 title:
.
?><h3><?= $title ?></h3><?
Out of php and then back in. I'd rather write:
tag_wrap($title, 'h3');
or
h3($title);
Obviously I can write a library myself, but I would prefer to use a conventional way if there is one.
Edit
3 Might not be a good example - I don't get much for using alternative syntax and I could have made it shorter.
1 and 2 are useful for debugging and quick testing.
I doubt that anyone would murder me for using some high-level html emitting functions of my own making when it saves a lot of writing.
In regards to #1, try xdebug's var_dump override, if you control your server and can install PHP extensions. The remote debugger and performance tools provided by xdebug are great additions to your arsenal. If you're looking only for pure PHP code, consider Kint or dBug to supplement var_dump.
In regards to #2 and #3, you don't need to do this. Rather, you probably shouldn't do this.
PHP makes a fine HTML templating language. Trying to create functions to emit HTML is going to lead you down a horrible road of basically implementing the DOM in a horribly awkward and backwards way. Considering how horribly awkward the DOM already is, that'll be quite an accomplishment. The future maintainers of your code are going to want to murder you for it.
There is no shame in escaping out of PHP to emit large blocks of HTML. Escaping out to emit a single tag, though, is completely silly. Don't do that, and don't create functions that do that. There are better ways.
First, don't forget that print and echo aren't functions, they're built in to the language parser. Because they're special snowflakes, they can take a list without parens. This can make some awkward HTML construction far less awkward. For example:
echo '<select name="', htmlspecialchars($select_name), '</select>';
foreach($list as $key => $value) {
echo '<option value="',
htmlspecialchars($key),
'">',
htmlspecialchars($value),
'</option>'
}
echo '</select>';
Next, PHP supports heredocs, a method of creating a double-quoted string without the double-quotes:
$snippet = <<<HERE
<h1>$heading</h1>
<p>
<span class="aside">$aside_content</span>
$actual_content
</p>
HERE;
With these two tools in your arsenal, you may find yourself breaking out of PHP far less frequently.
While there is a case for helper functions (there are only so many ways you can build a <select>, for example), you want to use these carefully and create them to reduce copy and paste, not simply to create them. The people that will be taking care of the code you're writing five years from now will appreciate you for it.
You should use a php template engine and just separate the entire presentation and logic. It make no sense for a educated programmer to try to create a library like that.
So I've always developed PHP pages like this: <?php goes at the top, ?> goes at the bottom, and all the HTML gets either print()ed or echo()ed out. Is that slower than having non-dynamic html outputted outside of <?php ?> tags? I can't seem to find any info about this.
Thanks!
--Mala
UPDATE: the consesus seems to be on doing it my old way being hard to read. This is not the case if you break your strings up line by line as in:
print("\n".
"first line goes here\n".
"second line goes here\n".
"third line");
etc. It actually makes it a lot easier to read than having html outside of php structures, as this way everything is properly indented. That being said, it involves a lot of string concatenation.
I'm not sure about speed, but it's typically best practice to separate dynamic elements and the display of them.
Check out a framework like CodeIgniter: This has a "controller" and a "model" that grab data, sort it or do whatever you like with it, and then feed it to a "view" (some sort of template).
This paradigm is called MVC, and is a really, really valuable thing to learn about. I've found its chief advantage to be easier-to-maintain code. I don't end up with a monster document that I have to re-learn each time I approach it.
Resources:
CodeIgniter
MVC
The difference in speed is probably negligible, however, when **print()**ing out all of your HTML with PHP, the code can get very ugly, and makes it much harder to read than if you just have plain HTML.
Edit: Also, if you're are **print()**ing out static HTML that doesn't change, really what is the point? It gives you no added benefit.
Pros
None that I can see
Cons
Code that is hard to read
One more step in processing for the PHP engine, which although probably not noticeable, it is an extra step.
The speed is negligible - trust me, this will not be your bottleneck.
Along with any other MVC framework, you might want to check out a simple templating system, such as Smarty, which separates your PHP logic from your HTML and also does caching.
I don't know if it's slower or faster, but (in my opinion) it makes the code a lot more difficult to understand. Which I guess is why I don't typically do it.
It is almost the same from a performance point of view.
I would set the focus on the readability of the code. If you have a performance problem, figure out the bottleneck and cache it.
Is that slower than having non-dynamic html outputted outside of <?php ?> tags?
Well yes, it is... marginally. But that's not really the issue: it's all about the readability.
this way everything is properly indented
Your example isn't indented at all, which is fairly typical for the print-heavy, PHP I've unfortunately had to maintain!
Try this approach to keeping good, consistent indentation:
<ul>
<?php
// block of arbitrary code blah blah
//
$conditions= get_conditions_from_request();
$isadmin= $user->privileges>=PRIV_ADMIN;
?>
<?php foreach (select_things($conditions) as $thing) { ?>
<li>
<strong><?php h($thing->title); ?></strong>
<?php if ($isadmin) { ?>
<a href="/editthing.php?id=<?php u($thing->id); ?> (Edit) </a>
<?php } ?>
<?php h($thing->description); ?>
</li>
<?php } ?>
</ul>
(This presumes a function h that calls echo htmlspecialchars and u that does echo htmlspecialchars urlencode. Getting this escaping stuff right is essential to having a secure site, and is something that's almost always wrong in print-based PHP, as it tends to use "blah $var blah"-style templating without any escaping at all.)
Maybe not the best practice, but I choose to mix and match print() statements. For large chunks of layout code, I don't use print(), but if I'm rendering a complex if/else or for/while block and I'd be exiting the PHP block every other word, then I'll print out the non-dynamic text with the dynamic text.
Performance is very negligible at best. You can create a page, and put a timer on it. (Here is a tutorial on creating a script timer)
Output the exact same data both ways, and measure it with as many samplings as you can get, this should roughly tell you which is faster. I'm guessing very close to the same.
I have seen a lot of these pages with PHP embedded inside HTML, and I don't like it. As Alex Mcp suggested you should be thinking about a MVC model.
The problem with scripts embedded into html is the flow control and logic aren't easy to read, and there are some wierd problems that occur here and there. The best solution for me is usually to use Smarty or the Zend Framework to create template pages and then swap the data that goes in and out. Much easier to manage in the long run.