The holy war of patterns continues to this day. On one side are the "angular", so called for the fact that on the shoulder straps they mean <? and?>. Generally speaking, it is necessary to use a single number here, since the “angular” one is a big and clumsy bear. And he is opposed by a whole army of smaller “curly-headed ones”. They are all in different forms, but most often on the shoulder straps you can see the signs {and}. The war is protracted with varying success on both sides. Somewhere on the side, the “independent” XSLT stands and observes, but we have mentioned it only for pro forma, since it will not be about it, but about love.
Rushing like a monkey between smart and beautiful does not make any sense, so you need to love one kind of side. Love will be on the calculation, as you know. The author has made his choice, the war is over for him, and there is no point in convincing him of the advantages of the other side. He understands all the pros and cons of each. (If you are a violent opponent of Native PHP, then in order to maintain your mental balance, we suggest that you stop reading this article.) With love, how is it going? You choose a love object for yourself and then you make a beautiful prince from it or at the very least a white horse. An astute reader has already guessed that the author has gone to the “angular” camp and will be telling how to sculpt a bear ... contextual patterns.
What is the main disadvantage of Native PHP? The fact that it is too low-level and therefore "verbose." With this vice beloved and we will fight. One of the first ways that comes to mind are helper functions. That is, some "difficult" pieces of templates are simply placed in the body of auxiliary functions. For example, you need to make the issuance of monetary values in the table, and the negative show red. What it would look like in pure Native PHP:
<table>
...
<? if ($ sum <0) $ color = 'red' ; else $ color = 'black' ; ?>
<tr> <td style = "color: <? = $ color?>" > <? = $ sum?> </ td> </ tr>
...
</ table>
Well, somehow it does not work out elegantly. If you enter a certain helper function, it will look better:
')
<table>
...
<tr> <? = ShowSum ($ sum)?> </ tr>
...
</ table>
Better, it is better, but there is also a "but." Violated the semantic integrity of the template. Part of it belongs somewhere to the end of the file or to another file. "One who stands aside and observes," this approach may not be surprising. But therefore, he stands on the side of few who need it, but we also need to achieve a “beautiful” and full-fledged template.
There is another danger in this approach, called the “template in quotes”. Sooner or later, working with helpers will have to pass some parts of the templates, like literals of the language. This is a very non-constructive approach that undermines the whole idea of patterns.
And now closer to the body. Parse still have to! But we will not parse everything, but only micro pieces and only for what we need in this context. Therefore, this will have very little effect on the overall speed of the application. We will have all the same Native PHP.
In order to demonstrate the elegance of the solution, take a much more complicated case - the form. The form creation theme itself deserves a separate consideration, but here we will empty it with the second storyline, without a detailed indentation, just sticking the slogan here: “No form builders!” What a form template in normal Native PHP would look like:
...
<label for = "field_name" > Name: </ label>
<input type = "text" id = "field_name" name = "name" value = "<? = $ name?>" style = "width: 100px" >
<label for = "field_country" > Country: </ label>
< select id = "field_country" name = "country" style = "width: 100px" >
<? foreach ($ countries as $ c => $ countryname):?>
<? if ($ c == $ country) $ selected = 'selected' ; else $ selected = '' ; ?>
<option value = "<? = $ c?>" <? = $ selected? >> <? = $ countryname?> </ option>
<? endforeach?>
</ select >
...
Quiet horror, right? The most interesting thing is that in the “curly” general-purpose templates, this particular example will look no better. And with our contextual templates, we will kill two birds with one stone at a time: first, we will hide the low level, and secondly, we will show how beautifully and optimally we can make forms without form builders. Thus we will be ahead of the rest!
The point is that many attributes, such as “id”, “value”, “name”, do not have a direct relationship to the design of the template. Therefore they can be hidden. Here's how the same piece will look in a new way:
...
<? form :: element ( 'name' , $ name)?>
<label> Name: </ label> <input type = "text" style = "width: 100px" >
<? form :: element ( 'country' , $ country, $ countries)?>
<label> Country: </ label> < select style = "width: 100px" > </ select >
...
Well, that's another matter! Very clear, semantically correct pattern. Nothing superfluous and at the same time everything you need in one place. We hid unnecessary attributes for the designer (name, value, etc.), while he was free to operate with all others. In our example there is only the style, but you can add anything without restrictions. There are no problems with additional tags. So <label> and <input> could end up in different divs or table cells, this is allowed:
<? form :: element ( 'name' , $ name)?>
<tr>
<td align = right> <label> Name: </ label> </ td>
<td align = left> <input type = "text" style = "width: 100px" > </ td>
</ tr>
(Do not pay attention to bad HTML style, this is only a demonstration of opportunities)
For select, you can set the initial value. Or do not set the initial, but set the visual properties of the options (or both at the same time):
<? form :: element ( 'country' , $ country, $ countries)?>
<label> Country: </ label>
< select style = "width: 100px">
<option value = "" > - Choose please - </ option>
</ select >
<? form :: element ( 'country' , $ country, $ countries)?>
<label> Country: </ label>
< select style = "width: 100px">
<option style = "background-color: yellow" > </ option>
</ select >
What do we have here? Actually nothing new. <? form :: element (...)?> in this case acts as an analogue of the beloved "curly" {block ...} (with the implicit closing of the block at the beginning of the next). The content of the block is buffered, parsed and expanded with all the necessary technical details. Thus, we got rid of the “verbosity” of Native PHP, increasing its level and practically without losing speed.
Look at another example, the same piece, but additionally with the error code. Those fields you need are surrounded by a red frame with a no less red error text and a funny arrow:
<? form :: error ($ element, $ msg)?>
<span style = "color: red; border: solid 1px red;" >
<? = $ element?> ← <? = $ msg?>
</ span>
<? form :: error ()?>
...
<? form :: element ( 'name' , $ name)?>
<label> Name: </ label> <input type = "text" style = "width: 100px" >
<? form :: element ( 'country' , $ country, $ countries)?>
<label> Country: </ label> < select style = "width: 100px" > </ select >
...
Please note that the form code itself remains pristine clean. Only one more block was added at the beginning.
That's probably all! Our task was only to state the method, not offering a concrete solution. The very idea of “context” implies the creation of a specific solution for a specific task. Otherwise, we will be in danger of another rolling into “curvature”. However, the example with the form used here is quite general and can be used in any task. A solution exists and anyone can get acquainted with it at
phella.net/?page=approach#forms The actual name of the “form :: element” block is taken from there.
Note: The author is familiar with the alternative HTML semantics of the <label> tag, which eliminates the “for” and “id” attributes. But it does not matter here. When we got rid of them along with many others, in this form the <label> looks more compact.
Regarding typographical quotes in the HTML code questions to habr