Code vs. Templates

Started by ptmuldoon, March 13, 2010, 03:38:09 PM

Previous topic - Next topic

ptmuldoon

Got another newbie question :P

I currently have 2 files I'm working with, along with some css, a

/Sources/MyMod.php  and
/Themes/default/MyMod.Template.php

I would think the main purpose of both is for the separation of code vs. layout.

In my template file, I've setup a basic 2 column tableless layout.  Now for each 'section' of the template, I'd like to.

a)  Keep all code in the MyMod.php file
b)  Have separate functions for each area, running loops/foreach, etc and to place that data into its appropriate area in the template file.

Eventually, I'll be pulling the info from a DB.  For for now, just learning the layout of SMF is enough to keep me busy.

Can anyone point towards some basis examples of outputting the mod code to the template? 

I would really like to have separate functions/templates for each section of my main MyMod.template.php file for easier editing of sections down the road.

Thanks
PT

Arantor

Yup, the idea is that the file in Sources gets data for your page(s) and stores it in $context, and the function(s) in the template file display it.

Means it's easier to restyle later if you decide you want to.


I'd direct you to my Buddy Page mod; it's a simple enough piece of code in Sources/BuddyPage.php and has different templates depending on whether it's 2.0 RC1.2 or 2.0 RC2/3 meaning that I have a single Sources file and one of two templates - they just get the data from $context and output it.

ptmuldoon

First....... Thanks for all your help.  You've been great in getting me started, and I hope I'm making some sense as well.

I have a basic template layout of below. 

echo '
<div id="container">
<div id="r_menu">Menu Area</div>
<!-- Open Left Column -->
<div id="r_leftcol">
<div id="r_gamelist">Active Games List</div>
<div id="r_chatarea">AJAX Chat Area</div>
</div>
<!-- Close Left Column -->

<!-- Open Right Column -->
<div id="r_rightcol">
<div id="r_topten">Top Ten Players</div>
<div id="r_mygames">Players Game List</div>
</div>
<!-- Close Right Column -->

<!-- Footer  -->
<div id="footer">Footer</div>

<!-- Close Container  -->
</div>

';


So, I'll need to break in and out between echo statements and foreach loops, etc in the template with arrays obtained/created in the Mod file?

I was hoping to have separate 'template' files for each area of the Module page, and than a main template that pulled it all together.

Also, perhaps it may be better to concatenate a $output variable, and then echo the $output at the end?

Arantor

You *can* do that if you like. We do in SimpleDesk.

The template file is really just a method of gathering functions together that relate to a common cause.

To give you an example from SimpleDesk, SimpleDesk-Post.template.php (one of the uber nasty files).

The entire template is broken down into many individual units, and glued together with a master function which is called directly through setting $context['sub_template'] in the source file.

function template_ticket_post()
{
global $context;

// Back to the helpdesk.
echo'<div class="floatleft">', template_button_strip(array($context['navigation']['back']), 'bottom'), '</div><br /><br />';

template_preview();
template_ticket_info();
template_ticket_subjectbox();
template_ticket_meta();
template_ticket_postbox();
template_ticket_footer();
if (!empty($context['ticket_form']['do_replies']))
{
template_ticket_begin_replies();
template_ticket_do_replies();
template_ticket_end_replies();
}
template_ticket_pageend();
}


The neat thing about doing that is that I can mash it up as I need to. A number of those things apply to replying to tickets, as well as quick reply. So all we do is make sure loadTemplate('SimpleDesk-Post') has been called, and call the different components as necessary.

If you want to have multiple files, do so but there's no need to have multiple files when one singular file with multiple functions will suffice.

ptmuldoon

ok, I seem a little stuck/confused again in understanding how to do some of the separation.   In learning, I have a array of the menu items.  But I can't seem to figure how to output the array in template file.


//function from MyMod.php
//Create the Menu
function r_Menu(){
global $context, $settings, $options, $scripturl, $modSettings, $txt;

$menu = array(
'browser' => 'Browser',
'create' => 'Create Game',
'glog' => 'Game Log',
'mlog' => 'Mission Log',
'profile' => 'Profile'
);

// Template
$context['sub_template'] = 'RMenu';

}


and in the template I have

function template_RMenu(){
global $context, $settings, $options, $scripturl, $modSettings, $txt;

foreach ($menu as $key => $menu)
{
echo '<a href="' . $scripturl . '?action=riskbrowser;sa=' . $key . '">' . $menu . '</a> | ';
}

}


And I have the RMenu template being called in the 'main' template of the file.

Arantor

To r_Menu(), add:
$context['rmenu'] = $menu;

Then in template_RMenu(), change the foreach to:
foreach ($context['rmenu'] as $key => $menu)

The principle problem is variable scope. Variables only live for the length of a function normally. $context is a global variable, so you pull it in from outside functions into your function and use it there.

Note that you really shouldn't do foreach ($variable as something => $variable) since that messes up $variable, $menu in this case, ready for the next iteration.

ptmuldoon

I'm not sure if Missed something, as I still can't get it show up.


// MyMod.php
//Create the Menu
function r_Menu(){
global $context, $settings, $options, $scripturl, $modSettings, $txt;

$menu = array(
'browser' => 'Browser',
'create' => 'Create Game',
'glog' => 'Game Log',
'mlog' => 'Mission Log',
'profile' => 'Profile'
);

$context['rmenu'] = $menu;

// Template
$context['sub_template'] = 'RMenu';

}


and

//MyMod.template.php
function template_RMenu(){
global $context, $settings, $options, $scripturl, $modSettings, $txt;

foreach ($rmenu as $key => $menu)
{
echo '<a href="' . $scripturl . '?action=riskbrowser;sa=' . $key . '">' . $menu . '</a> | ';
}

echo 'something to test';
}


I added the 'something', which will show up, thus template is being seen.   For the foreach loop, I am using both the key and value though, with the key used as the subaction, and the value for the Link Name.  Is there a better way than?

Arantor

Yeah, the foreach is still wrong, because $rmenu is a variable it knows nothing about. It has to use $context['rmenu'].

There isn't a *better* way than what you're doing, merely *different* ways. I do something quite similar to that at times :)

ptmuldoon

Well, I fixed the foreach to use the $context, yet it still didn't print.  I added a an echo statement inside the loop as well, and it doesn't print.  So it seems the template is not seeing the array somehow.


//MyMod.template.php
function template_RMenu(){
global $context, $settings, $options, $scripturl, $modSettings, $txt;

foreach ($context['rmenu'] as $key => $menu)
{
echo 'Does it work?';  //This still doesn't print
echo '<a href="' . $scripturl . '?action=riskbrowser;sa=' . $key . '">' . $menu . '</a> | ';
}

echo 'something to test';  // And this does show on the page
}

Arantor

Anything in the error log?

ptmuldoon

Yep, there's an error, and pointing right to that foreach statement as well.
Quote
2: Invalid argument supplied for foreach()
Apply Filter: Only show the errors from this file
File: C:/Program Files/wamp/www/smf/Themes/default/MyMod.template.php (MainBrowser sub template - eval?)
Line: 44

ptmuldoon

I still can't seem to figure out what could be wrong with the foreach statement, as the array exists.  I was able to echo the foreach statement originally in the MyMod.php file.  Yet, moving the foreach statement to the template, give an error?

Arantor

OK, in the template, do var_dump($context['rmenu']), see what's actually there.

ptmuldoon

#13
Actually, this is sort of strange.

Its working now this morning, although I didn't change anything.  I unsure, but I wonder if it could have been a cache issue, although the echo statement outside the loop was always showing.

Although the error is still there in the log. I'll do a var_dump and see what it shows as well.

And here's the results of the var_dump

array(5) {
  ["create"]=>
  string(11) "Create Game"
  ["browser"]=>
  string(7) "Browser"
  ["glog"]=>
  string(8) "Game Log"
  ["mlog"]=>
  string(11) "Mission Log"
  ["profile"]=>
  string(7) "Profile"
}

Arantor

Now that's really weird... :( I have no idea why that's not working. If the variable's there it should work.

ptmuldoon

Yep, It was strange.

It is working now this morning as it should, yet wasn't yesterday.

ptmuldoon

ok, I thought I understand how using the $context global works, and trying to simply things before getting into querying data, etc.  So, shouldn't the below work?

//Mod file
function r_ActiveGames(){
global $context;

$context['mytext'] = 'Why does this not print?';

// Template
$context['sub_template'] = 'ActiveGames';
}

//Template File
function template_ActiveGames(){
global $context;

echo '<div>Testing:  This Prints Fine/div';

echo $context['mytext'];  //Yet this is not getting info from the Mod file?

}

Arantor

When are you calling loadTemplate?

ptmuldoon

I'm calling loadtemplate earlier in the file.  The page loads, and in this example, the echo of "Testing" in the sub template works.  Yet, the echo of the $context variable is not showing.  And I can't seem to understand why.

Arantor

Can you show me more of the file please?

Advertisement: