I want to separate my presentation layer from the logic layer but I'm unsure what I should do when I have to loop or check stuff within the presentation layer?
Variables and other somewhat static content is easy, I can either do
<div class='description'><?php echo $product['description']; ?></div>
or
<div class='description'>{{product_description}}</div>
But how about looping stuff?
Let's say I'm creating a list of users within a table. Is there any other way except putting up a foreach within the view and printing HTML inside the foreach?
<table>
if (!empty($users)) {
foreach ($users as $key => $value) {
echo "<tr data-user-id='$value[id]'>";
echo "<td>$value[id]</td>";
echo "<td>$value[first_name]</td>";
echo "<td>$value[last_name]</td>";
echo "<td><a href='?id=$value[id]&edit=1' class='edit'>Edit</a></td>";
echo "</tr>";
}
}
</table>
This would work perfectly fine but I can't get over the fact that it's not looking so "viewish" anymore. Is it possible to get the view cleaner? What about when I have to add conditions? It gets more and more messy.
Sounds like the main problem your having has to do more with making the view presentation readable. An easy way to accomplish this using PHP templates is to use the alternative syntax for control flow structures. Doing this can make a template look much more readable, similar to twig for instance.
Using your example:
<table>
<?php if (!empty($users)): ?>
<?php foreach ($users as $key => $value): ?>
<tr data-user-id="<?php echo $value[id]; ?>">
<td><?php echo $value[id]; ?></td>
<td><?php echo $value[first_name]; ?></td>
<td><?php echo $value[last_name]; ?></td>
<td>Edit</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</table>
Notice that I've removed the open curly braquet { and replaced it with a :. This is then closed on line 10 with a endif;. Same idea is repeated with foreach. This is the alternate syntax for control structures. Normally in business logic You would us the other form, but this can really help when you need to write readble template code for view presentation layers.
Related
The code problem:
<?php
if(strtolower($item["category"]) == "books" ) {
?>
<tr>
<th>Category</th>
<td><?php echo $item["category"] ?></td>
</tr>
<?php } ?>
Why I have to write it like that? Instead of:
<?php
if() {
Do some things!
}
?>
You can write PHP in HTML but you cant write HTML IN PHP(without using echo).
AFTER THIS
<?php
if(strtolower($item["category"]) == "books" ) {
?>
You close the php tag to add html.
Then you open the php tag to put the closing braces for if and then close it back so that you can add html
This is just basic stuff, but short explanation is that when server is processing your *.php file and sending it to the browser it starts parsing your file when he sees <?php tag and stops parsing when he runs into ?> tag or the end of the file. So, anything in between those two will be seen by the server as a PHP code and the rest will be sent directly to browser.
Your code above can be written in several different ways to do the same thing, all depends on what you want to do. This is also valid in PHP and sometimes it's much more readable
<?php if (strtolower($item["category"]) == "books"): ?>
<tr>
<th>Category</th>
<td><?php echo $item["category"] ?></td>
</tr>
<?php endif; ?>
I've always wondered: does having a large open and close PHP (i.e. a template) hurt?
To clarify:
<html>
<?php echo $test; ?>
<body <?php echo $test2; ?>>
<table>
<?php foreach ($rows as $row): ?>
<tr>
<td><?php echo $row['cell1']; ?></td>
<td><?php echo $row['cell1']; ?></td>
<td><?php echo $row['cell1']; ?></td>
<td><?php echo $row['cell1']; ?></td>
<?php echo $row['added cells']; ?>
</tr>
<?php endforeach; ?>
</table>
<?php echo $someMorePhp; ?>
<div>
<?php /*do some more php stuff */ ?>
</div>
etc etc
etc
Or would it be advisable to i.e.
<html>
<php echo $test.'<body'.$test2; ?>>
<table>
<?php foreach ($rows as $row) {
echo '<tr>
<td>'.$row['cell1'].'</td>
<td>'.$row['cell2'].'</td>
<td>'.$row['cell3'].'</td>
<td>'.$row['cell4'].'</td>
<td>'.$row['cell1'].'</td>
'.$row['added cells'].'
<tr>';
}
</table>
// etc
I know this might seem like a micro optimization and such. To be clear i'm looking for a rule-of-thumb not a specific usecase... Will it hurt entering and exiting the php engine during a single script run...
No, that is no problem, you should always opt for better readability in this case.
Also think about either activating shorttags if possible (but beware, those might have some sideeffects / problems with XML sytnax as stated in the comments)
<? if ($bool) { ?>
<?= $myVarThatIWantToOutput ?>
<? } ?>
Or think about using a template engine like smarty or twig, which restrict you somehow to force splitting of concerns, make some stuff easier (and more readable) and allow caching of compiled templates to make sure you still get the right speed.
I really don't see the difference between these. How is the templating any better? I don't just don't understand it or how I could convince someone to use it I work with. I understand "separation" of concerns, but I haven't had huge issues. Isn't the first example generating multiple <li> tags just like an echo would? And, I would use php as the "templating language," so I'm not concerned with Smarty or some other system. Thanks.
Why should I use templating system in PHP?
<h1><?=$title?></h1>
<ul>
<?php foreach ($items as $item) {?>
<li><?=$item?></li>
<?php } ?>
</ul>
and (some snippet I found in a forum for an example):
echo "<table>";
for ($i = 0; $i < $largestArray; $i++)
{
echo "<tr>";
if ($i < $array1Size)
{
echo "<td>";
echo $array1[$i];
echo "</td>";
}
else
{
echo "<td>";
echo "null";
echo "</td>";
}
if ($i < $array2Size)
{
echo "<td>";
echo $array2[$i];
echo "</td>";
}
else
{
echo "<td>";
echo "null";
echo "</td>";
}
echo "</tr>";
}
echo "</table>";
or something like this:
<table id="working" border="0" cellspacing="1" cellpadding="3">
<tr>
<?php foreach ($csv->titles as $value): ?>
<td><?php echo $value; ?></td>
<?php endforeach; ?>
</tr>
<?php foreach ($csv->data as $key => $row): ?>
<tr>
<?php foreach ($row as $value): ?>
<td><?php echo $value; ?></td>
<?php endforeach; ?>
</tr>
<?php endforeach; ?>
</table>
EDIT: Should this be a community wiki question?
Your identation seems a bit messed up, but the main point is that the second version is far mor readable (you can easily read tag hierarchy, for example). And a readable code is a code which could be easily maintained or refactored.
Writing the code below using only PHP's echo keyword wouldn't be very readable. You would also had concern about quotes and double quotes. Using a template-like approach, you end up with a code which look similar to an HTML document.
<table id="working" border="0" cellspacing="1" cellpadding="3">
<tr>
<?php foreach ($csv->titles as $value): ?>
<td><?php echo $value; ?></td>
<?php endforeach; ?>
</tr>
<?php foreach ($csv->data as $key => $row): ?>
<tr>
<?php foreach ($row as $value): ?>
<td><?php echo $value; ?></td>
<?php endforeach; ?>
</tr>
<?php endforeach; ?>
</table>
Templating systems such as cakephp and codeignitor use MVC which keeps code cleaner and more standards compliant. You could also write your own MVC.
Template system(s) are not the end-all-be-all solution to separation of presentation logic. They are a solution, and one used by many PHP frameworks. In general "MVC"/MVA/MVP/MVVM PHP development, you do not want any business logic in the presentation layer. Echoing out HTML is a (usually) direct violation of this practice; With templates, business logic is not present in the presentation layer, and vice versa.
Skipping back to the first point, templates are a solution, not the solution. There are a ton of options available for the presentation layer, depending largely on your coding style and/or framework/library usage.
On a personal level I prefer templates (for most small-med projects) for a few reasons beyond what's outlined above:
Makes "theming" and swapping site styles a lot easier. Simply modify the template or implement a theme switcher that can load different templates
Going from mockups to templates is a breeze, because templates are (usually) just HTML with some php snippets echoing out data.
Templates are "dumb." They don't need to know about anything that's happening with the business logic, all they care about is echoing out some data into the HTML.
Readability. This one is almost entirely personal preference, especially considering the wide range of template syntaxes out there.
tl;dr - Templating vs. [insert other solution here] is almost entirely subjective, unless you have constraints based on hosting, customer requirements, traffic levels, etc. If that's the case, then find benchmarks and more about efficiency and scalability and make an informed decision based on the requirements of the project.
I am trying to write PHP code to loop through an array to create an HTML table. I have been trying to do something like:
<div id="results">
<table class="sortable">
<?php $results = $statement->fetchAll(PDO::FETCH_ASSOC); ?>
<?php do: ?>
<tr>
<?php for ($i = 0; $i < count($columns); $i++): ?>
<td><?php echo $row[$i] ?></td>
<?php endfor; ?>
</tr>
<?php while (($row = next($results)) != false); ?>
</table>
</div>
So 2 questions:
Is there an equivalent do-while
syntax as there is a for, if, or foreach syntax in
PHP, where you can split the PHP
code up and have HTML in between?
What is this called when you split
PHP code up with HTML in between?
(if there is a special term for it)
I do not know of a do while syntax that behaves like that, but you can still end your PHP block like this:
<div id="results">
<table class="sortable">
<?php $results = $statement->fetchAll(PDO::FETCH_ASSOC); ?>
<?php do { ?>
<tr>
<?php for ($i = 0; $i < count($columns); $i++): ?>
<td><?php echo $row[$i] ?></td>
<?php endfor; ?>
</tr>
<?php } while (($row = next($results)) != false); ?>
</table>
</div>
You can use curly brackets:
<?php do { ?>
foo
<?php } while ($i--); ?>
No. From http://php.net/manual/en/control-structures.alternative-syntax.php :
PHP offers an alternative syntax for some of its control structures; namely, if, while, for, foreach, and switch.
On the other hand, do { ?> ... <?php } while(...) will work just fine.
What you're trying to do can be done with two foreach loops :
<div id="results">
<table class="sortable">
<?php foreach ($statement->fetchAll(PDO::FETCH_ASSOC) as $row): ?>
<tr>
<?php foreach ($row as $element): ?>
<td><?php echo $element ?></td>
<?php endforeach; ?>
</tr>
<?php endforeach; ?>
</table>
</div>
It solves the problem of having to initialize $row (and handling the empty list special case).
I'm not aware of any specific name for this, but I suspect that if you said "embedded HTML inside my PHP", people would understand.
While I've never used the colon syntax as in your example, everything looks basically right except that on your first time through $row is unassigned.
I would switch it around to look like this:
<div id="results">
<table class="sortable">
<?php $results = $statement->fetchAll(PDO::FETCH_ASSOC);
if ($results) {
while ($row = next($results)) {
?>
<tr>
<?php for ($i = 0; $i < count($columns); $i++): ?>
<td><?php echo $row[$i] ?></td>
<?php endfor; ?>
</tr>
<?php }
} ?>
</table>
</div>
This is excessive use of the embedded php tags.. When there is more PHP than HTML, you're better off using PHP and echoing the HTML.
You can mix php and html in every kind of loop, but your current loop does will not work because $row is not defined the first time it gets there.
It doesn't have a special name :)
You may find using the heredoc syntax a bit cleaner than stepping in and out of PHP / HTML like this, though: http://php.net/manual/en/language.types.string.php
You can use variables inside heredoc blocks so you'll be able to access your database results actually inline without dancing about with braces and new lines.
1) Your best bet is to echo the HTML in strings, all within the <%php ... ?> tag.
What you're doing now is an empty for loop inside of a do-while, which is essentially pointless.
2) I believe that's called "inline" coding, where the code and HTML intermingle, but the practice is frowned upon because you generally want to separate logic (PHP) and content (HTML) when developing for the web.
For a grouped product, I would like to display a link to the simple products it is composed of. For example, if I have a grouped product called Dining Set composed of plates, knives, forks, etc. I'd like each of the subproducts to have a link to that subproduct (click plates goes to the Simple Product for plates)
<?php foreach ($_associatedProducts as $_item): ?>
<tr>
<td><?php echo $this->htmlEscape($_item->getName()) ?></td>
<td class="a-right">
<?php echo $this->getPriceHtml($_item, true) ?>
</td>
<?php if ($_product->isSaleable()): ?>
<td class="a-center">
<?php if ($_item->isSaleable()) : ?>
View
<?php else: ?>
<p class="availability"><span class="out-of-stock"><?php echo $this->__('Out of stock.') ?></span></p>
<?php endif; ?>
</td>
<?php endif; ?>
</tr>
<?php endforeach; ?>
This is a code snippet from the grouped.phtml file in
app/design/frontend/blank/default/template/catalog/product/view/type/grouped.phtml
In particular the line that has $_item->getProductUrl(),
this does not work, and I don't know the code needed to get the url for this associated product item. If anyone could help here it would be much appreciated.
Also, where on earth can I find the method's available (and how they're used) for Products or Categories or $_item and the like?
Easy to find all methods and functions. Always trace back to the Core /app/code/core/Mage/Catalog/Model/Product.php or any of the other files in that Folder.
Your code is perfect. Just use
$_item->getUrlPath() ;
instead of productURL.
Just a few notes on getting the available methods / data:
First, to get all methods actually coded into the classes, you can get all the available methods with:
$array = get_class_methods($_item); //yields an array of the methods in the class
var_dump($array); // to see the methods
To get all data-related methods, first find out the data members in the class. This works with most objects in Magento:
$data = $_item->getData(); // $key => $value array
Then you can get any piece of data you want two ways:
// assuming I want 'my_data'
$data = $_item->getMyData();
$data = $_item->getData('my_data');
<?php echo $this->htmlEscape($_item->getProductUrl()) ?>
or here is the whole A HREF:
<a href="<?php echo $this->htmlEscape($_item->getProductUrl()) ?>">
<?php echo $this->htmlEscape($_item->getName()) ?>
</a>