/    Sign up×
Community /Pin to ProfileBookmark

Beginning PHP and MySQL E-Commerce

[CODE][/CODE]

I am building an ecommerce website with the aid of the book Beginning PHP and MySQL E-Commerce: From Novice to Professional 2nd edition. This book uses smarty tpl files along with php files. It also uses yui css files. My problem is as follows.

I am using a file called product-list.tpl as a template to display my products. Using code from this book, I am unable to display more than 2 products per line. In other words, I am unable to display more than 2 table cells per row. Here is the code I am using to display products in product-list.tpl:

[CODE]{if $obj->mProducts}
<table class=”product-list” border=”0″>
<tbody>
{section name=k loop=$obj->mProducts}
{if $smarty.section.k.index % 2 == 0}
<tr>
{/if}
<td valign=”top”>

<p>
{if $obj->mProducts[k].thumbnail neq “”}
<a href=”{$obj->mProducts[k].link_to_product}”>
<img src=”{$obj->mProducts[k].thumbnail}”
alt=”{$obj->mProducts[k].name}” />
</a>
{/if}
</p>

<p class=”product-title”>
<a href=”{$obj->mProducts[k].link_to_product}”>
{$obj->mProducts[k].name}
</a>
</p>

<p class=”section”>
Price:
{if $obj->mProducts[k].discounted_price != 0}
<span class=”old-price”>{$obj->mProducts[k].price}</span>
<span class=”price”>{$obj->mProducts[k].discounted_price}</span>
{else}
<span class=”price”>{$obj->mProducts[k].price}</span>
{/if}
</p>

{* Show Edit button for administrators *}
{if $obj->mShowEditButton}
<form action=”{$obj->mEditActionTarget}” target=”_self”
method=”post” class=”edit-form”>
<input type=”hidden” name=”product_id”
value=”{$obj->mProducts[k].product_id}” />
<input type=”submit” name=”submit” value=”Edit Product Details” />
</form>
{/if}

</td>
{if $smarty.section.k.index % 2 != 0 && !$smarty.section.k.first ||
$smarty.section.k.last}
</tr>
{/if}
{/section}
</tbody>
</table>[/CODE]

The CSS for this is as follows:

[CODE].product-list tbody tr td {
border: none;
padding: 5px;
width: 150px;

}

.product-list tbody tr td p img {
border: none;
margin: 0 10px;
vertical-align: top;
}[/CODE]

I looked through all the yui css and there was nothing that would affect a table td or tr. When using tables in the past with css I had always built the entire table and used the css to style the table. I no nothing in css that can limit table cells. If there is something, it isn’t used in any of the CSS I’m using. This leaves me with smarty. I looked all through out smarty to see if something in the Smarty_Compiler.class.php was limiting how many times the products could loop in one row. But I really don’t understand smarty.

I need to fit four products per line and despite all my efforts of messing with td width only two can fit in one row before the products go to the next row. Does anyone know why this is? Please help, I’m very confused.

to post a comment
PHP

6 Comments(s)

Copy linkTweet thisAlerts:
@MindzaiMay 26.2010 — Your issue is here:[COLOR="White"]&#37;[/COLOR]

[code=php]{if $smarty.section.k.index % 2 == 0}[/code]

The denominator (currently 2) is controlling how many iterations occur before a <tr> tag is written. The $smarty.section.k.index value will increment by 1 each time the loop is iterated. The remainder after dividing by 2 is then checked, and when it is 0 (ie when the number evenly divides by 2) a new row is output.

I know you're working with a book and so have little choice, but my advice is to ditch smarty. PHP is already about the best templating language you could hope for, and adding the extra layer of abstraction just means another (unnecessary) thing to learn.
Copy linkTweet thisAlerts:
@teddybearauthorMay 26.2010 — Your issue is here:[COLOR="White"]%[/COLOR]

[code=php]{if $smarty.section.k.index % 2 == 0}[/code]

The denominator (currently 2) is controlling how many iterations occur before a <tr> tag is written. The $smarty.section.k.index value will increment by 1 each time the loop is iterated. The remainder after dividing by 2 is then checked, and when it is 0 (ie when the number evenly divides by 2) a new row is output.

[/QUOTE]


That's exactly what I thought was controlling the <tr> and now that you've explained it, it makes more sense. I did try to change the number 2 to 4. I tried again this morning just in case but it still goes to another row after only 2 table cells. Actually, it does this

<tr><td></td><td></td></tr>

<tr><td></td></tr>

<tr><td></td></tr>

Above is what haapens when i change the code to look like this:

[CODE]{if $smarty.section.k.index % 4 == 0}
<tr>
{/if}[/CODE]


and

[CODE] {if $smarty.section.k.index % 4 != 0 && !$smarty.section.k.first ||
$smarty.section.k.last}
</tr>
{/if}[/CODE]


I don't get it. Now that I understand the conditional is controlling the <tr> part of the table it would seem logical that simply changing the number from 2 to 4 would give me four cells per table row. This not what happens, and I am confused.
Copy linkTweet thisAlerts:
@teddybearauthorMay 27.2010 — hmmm. I've been thinking about the divisor that mindzai mentioned. I'm trying to figure it out. So, say I want 4 products per line and I do this:

{if $smarty.section.k.index &#37; 4 == 0}

<tr>

{/if}

does that mean the calcualtions smarty is making are as follows

4/4=1; 3/4=.75; 2/4=.5; 1/4=.25?

or does it calculate them differently?

Obviously I'm not the mosyt experienced person with PHP. Understanding how these items are calculated might help me get the correct amount of products on each row.
Copy linkTweet thisAlerts:
@MindzaiMay 27.2010 — The &#37; operator in PHP is modulus, which gives the remainder of i after dividing by n. In your case, i will be an integer increasing in value by 1 each time your loop is iterated, and n is the desired number of <td>s per row. The calculations therefor are:

<i>
</i>0 % 4 = 0 (0 doesn't divide into 4, so the whole amount remains)
1 % 4 = 1 (as above)
2 % 4 = 2 (as above)
3 % 4 = 3 (as above)
4 % 4 = 0 (4 divides evenly into 4 with no remainder)
5 % 4 = 1 (5 divides into 4 once with a remainder of 1)
6 % 4 = 2 (6 divides into 4 once with a remainder of 2)
7 % 4 = 3 (7 divides into 4 once with a remainder of 3)
8 % 4 = 0 (8 divides into 4 twice with no remainder)
etc


So using this technique you can make anything occur every nth iteration. Some raw PHP which may be easier to understand:

[code=php]
for ($i = 0; $i < 30; $i++) {
if ($i % 5 == 0) {
echo "{$i}th iteration!n";
}
}[/code]


<i>
</i>0th iteration!
5th iteration!
10th iteration!
15th iteration!
20th iteration!
25th iteration!


Translating this to your situation is actually a little more complex because of the closing </td> tag - my fault for not thinking it through properly in the first place. Here is how you might need to do this in raw PHP, but the same applies for smarty:

[code=php]
<table>
<?php

for ($i = 0; $i < 30; $i++) {

if ($i % 4 == 0) {
echo '<tr>';
}

echo "<td>$i</td>";

if ($i % 4 == 3) {
echo "</tr>n";
}

}

?>
</table>
[/code]


Note that here you want to create an opening <tr> tag every 4th iteration, but you don't want to also make the closing tag every 4th iteration, but rather every iteration before the 4th, ie before the next opening tag, so you need to write the </tr> when the remainder is 3.

However you still have another issue here in that if you don't have a number of items which is exactly divisible by 4, you will have broken HTML. For example, the above code outputs the following HTML:

[code=html]
<table>
<tr><td>0</td><td>1</td><td>2</td><td>3</td></tr>
<tr><td>4</td><td>5</td><td>6</td><td>7</td></tr>
<tr><td>8</td><td>9</td><td>10</td><td>11</td></tr>
<tr><td>12</td><td>13</td><td>14</td><td>15</td></tr>
<tr><td>16</td><td>17</td><td>18</td><td>19</td></tr>
<tr><td>20</td><td>21</td><td>22</td><td>23</td></tr>
<tr><td>24</td><td>25</td><td>26</td><td>27</td></tr>
<tr><td>28</td><td>29</td></table>
[/code]


As you can see all is good until the last line. To get round this you will need to fill in any missing <td>s and close out the <tr>. One way would be to find out how many empty cells you need to add by using the modulus operator again. Empty cells = total items % items per row. In the above example, this gives 30 % 4 = 2, so after your loop you need to echo 2 x <td>&nbsp;</td> followed by the closing </tr> and </table> tags.
Copy linkTweet thisAlerts:
@teddybearauthorMay 30.2010 — I thank you with great enthusiasm for this solution! I almost teared up when I saw it work. You not only gave me an awesome solution but a lesson in basic php. I'm sure I learned this a while back, but to be perfectly honest I've forgotten a lot of php basics that I haven't used. Anyway, just in case someone else is using this book, here is the solution I used to get four products per line.

[CODE] {if $smarty.section.k.index % 4 == 0}
<tr>
{/if}[/CODE]


and

[CODE]{if $smarty.section.k.index % 4 == 3 && !$smarty.section.k.first ||
$smarty.section.k.last}
</tr>
{/if}[/CODE]
Copy linkTweet thisAlerts:
@HolmesSPHJun 01.2010 — I used to use table for stuff like this but I stopped lol.. I try and use un ordered lists.

If you create a list and have it setup with each <li> being "inline-block" then it will display more likke a grid and it will automatically with the same row numbers in what ever space you give it.. Then you never have to worry about how much is where..
×

Success!

Help @teddybear spread the word by sharing this article on Twitter...

Tweet This
Sign in
Forgot password?
Sign in with TwitchSign in with GithubCreate Account
about: ({
version: 0.1.9 BETA 5.28,
whats_new: community page,
up_next: more Davinci•003 tasks,
coming_soon: events calendar,
social: @webDeveloperHQ
});

legal: ({
terms: of use,
privacy: policy
});
changelog: (
version: 0.1.9,
notes: added community page

version: 0.1.8,
notes: added Davinci•003

version: 0.1.7,
notes: upvote answers to bounties

version: 0.1.6,
notes: article editor refresh
)...
recent_tips: (
tipper: @AriseFacilitySolutions09,
tipped: article
amount: 1000 SATS,

tipper: @Yussuf4331,
tipped: article
amount: 1000 SATS,

tipper: @darkwebsites540,
tipped: article
amount: 10 SATS,
)...