Jump to content

How to use a variable from one template in another


Reid Bramblett
 Share

Recommended Posts

I only stumbled across WP a few weeks ago, but have already been able to accomplish far more than over months spent banging my head against the baroque code of several shall-remain-nameless frameworks. I could weep thinking of how much time I have wasted elsewhere.
 
I have, however, hit a speed bump--possibly due to the fact that I am still a bit shaky on how templates interact. 
 
My set-up (a sample travel site): 
 

Places

Place1
see
poi1
poi2
do
poi3
poi4
sleep
poi5
plan
poi6
Place2
see
poi7
do...
 
Interests
Interest1
Interest2
Interest3...
 
"Interests” act a bit like tags assigned to the "poi"s (this is an internal tagging system, open to admin only; no free tags/users cannot assign). 
 
For the record, that odd "poi" nomenclature stands for "point of interest" (as a unique name, it's handier than using something vague like "item").
 
(Aside: Yes, I realize "see, do, etc." could exist instead as a third "Categories" tree. I fiddled with that, but in the end figured I'd just use the already powerful and straightforward parent/child nesting format of pages that PW provides. Also [ahem], I couldn’t get urlSegments to work; another time.)
 
A simple foreach loop on my _main.php page creates a link-list of the Interests assigned to a given poi. 
<?php foreach ($page->interests as $i) {
echo "<li><a href='{$i->url}'>{$i->title}</a></li>";
} ?>

When you click on these generated links, it takes you to the appropriate "Interest" page, populated by all POIs assigned that Interest. 

 
Here is the relevant part of my Interest.php code:
$int = $page->id;
    $pois = $pages->find("template=poi, interests=$int");
    $content .= renderNav($pois);  
Problem: I do not want to see _all_ the POIs assigned that Interest. I need to limit it to other POIs in this particular Place (the grandparent of the referring POI).
 
In other words, I only want to see other "Museums" (interest) in London, not those in Bath, Manchester, and Oxford as well.
 
This is easy to do in absolute terms (I can limit to "has_parent=London" or something); but I need it to be some kind of $place variable instead, one assigned by the referring POI.
 
For the life of me, I cannot figure out what code to use and where to stick it--in the foreach loop of the poi.php page? On the "Interests" template page? In short, how does this variable (the "Place" grandparent of a given POI) get assigned to the link and hence carry over to be able to be used in the functions being applied by another template (Interests)?
 
I suspect the answer is so glaringly obvious only an interactivity noob like me would not know. That would explain why I canot seem to find the answer after a solid week of trolling every forum thread, tutorial, and wiki at PW. 
 
While I’ve built my own static HTML sites for 20 years (wow, that seems long; anyone else remember dividing text blocks with HRs, or the glorious day HTML3 finally allowed us to align GIFs so text could actually flow around them?) I am only a journeyman at PHP and MySQL. I've never even created a form. I know. Shameful.
 
Thanks for your help.
Link to comment
Share on other sites

Maybe you could use something with $page->parents to get which are the parent pages, and make a selector accordingly?

$parents = $page->parents;
$pois = $pages->find("parent=" .getPathString($parents). ",template=poi, interests=$int");

I included that getPathString() because $page->parents returns a PageArray that I don't know how if has a method to make it into a string like "/this/is/a/path/".

Link to comment
Share on other sites

@elabx, not possible. We are in one of the interests pages at this point.

--

You have only two ways of passing info to the future page when pressing a url: the url itself or session. With session there is no way to create a permanent shareable page, so i would go for the url.

you can do this with url segments or using a get in the url referring to the place.

--

I would simulate with url segments that interests is at the same level of the tree as (do, see, etc) and link to there instead, leaving the interests pages without a template file. You could do it like this:

<?php foreach ($page->interests as $i) {
    $place = $page->closest("template=place"); //or whatever works
    $url = $place->url . "/interest_" . $i->name
    echo "<li><a href='{$url}'>{$i->title}</a></li>";
} ?>

On the template from the places pages you would have something like (rough draft):

if ($input->urlSegment1) {

    if (!substr($input->urlSegment1,0,9) == "interest_" ) throw new Wire404Exception();
   
    $reduced = str_replace("interest_", "", $input->urlSegment);
    $sanitized = $sanitizer->name($reduced);
    $int = $pages->get("name=$sanitized");
    $pois = $pages->find("template=poi, interests=$int");
    $content .= renderNav($pois);

}

Edit: And welcome to PW!

Edit2: corrected typo

  • Like 3
Link to comment
Share on other sites

I think it can be much simpler:

Turn on url segments for interests, and link to /interests/interest1/PLACE/, where PLACE is the first url segment.

  //poi.php
  $url = "/interests/interest/{$page->parent->parent->id}/";

  //interest.php
  if ($input->urlSegment1){
    //validate that the url segment isn't bullshit
    $place = $pages->get((int)$input->urlSegment1);
    if (!$place->id || $place->template != 'place') { $session->redirect( … ); }

    $pois = $place->find('template=poi, interest={$page->id}');
    // here you go.

    // alternatively, if you want to fiter out the 'sender',
    // add it as second url segment (and after check&validation), use:
    $pois = $place->find("template=poi, interest={$page->id}, id!={$poi_from_segment_id}");
  }
  • Like 2
Link to comment
Share on other sites

Not sure if I would. Depending on how the site would be built I would probably use your solution and create the views for those. Probably with a listing of all the interests and a sublist of all the places in each interest, but then, maybe it makes more sense interests inside places and not the opposite. It really depends on the content.

  • Like 1
Link to comment
Share on other sites

Thanks, guys.

I got the first halves of both suggestions working: Diogo's spoofing the system to think Interests was on the same level as Cat [see, Do, etc] (though I also had to remove the / before interests since my template's defaults are set to have trailing slashes and it was doubling them up), and Adam's fooling it into sticking the place at the end of an interests/interest url (though I tried a variation using the user-friendlier "name" instead of the nonsensical id number for place).

The second half of each of your fine suggestions, however, only produced frustration.

As I mentioned, I had no luck fiddling with urlSegments earlier, when I was trying to make a Categories tree work, and my failure stands. I am not sure why, and it looks as if I might have to solve this problem before being able to move forward on anything else.

Might it have anything to do with the profile I am using? I didn't just do a "Blank" install, but rather started building from the Default profile. It was close to where I was heading anyway, already had a top nav and all, and had sliced things into a _func.php for renders and a _main.php for page content, leaving all the template-based phps little more than containers to string together brief calls of $content .= [something].

As I said, I am new to the structure (and mindset) of building a site based on including files from other files, so I was happy to have someone else (Ryan) do this for me so I could muddle through figuring out how it worked as I went. However, given my noobiness, I may be missing something here? Is that setup what is fouling my attempts to use urlSegments? (I've already turned them on for pretty much every template in my experimentations, just to be sure that setting its not what's tripping me up.)

Diogo: I do not mind creating views for template levels. In fact, it might be best. I'd like the site to be navigable (no offense to the lovely "navigatable") in various ways, since no two people consume data the same way. Some want a hierarchy, others a flat map, still other visual cues. I just want to help people find the information they are looking for in whatever way makes the most sense to them.

Besides, in the long run I would like to have the "Interests" results reflect whatever level of "places" sent the request. So if you clicked on "History" from a page within, say, Florence, it would show all Florence results with the History "Interest" tag, but if you did so from within its parent in the Places tree, Tuscany, it would show all Tuscan results, and from its parent, Italy, all Italian results.  

I tried to keep my original question limited because I was hoping that learning a simple way to carry a set variable ("where are we?") over to another template would give me the tool to build the more complex site I had in mind than the example I gave.

However, just so you know where I am heading (and in case it changes your above suggestions), I envision these Interests acting kind of like sidebar filters, as you might see on an ecommerce site (size, brand, color, etc.). The user just ticks off all the ones she wants, and the site returns a page showing the POIs (if any) that match all her choices.

 

I am imagining the overall backend architecture to have three main page trees: Places, Categories, and Interests, each with two levels underneath (Places has cities, and under that the POIs; Categories and Interests both have main cats and interest groupings, and then more finely sliced subcats and interests under that). These would all interact. This makes things tricky, but I am sure if can be done!

The Places tree is where all the real contents lies; Categories helps organize it all; and Interests (and Categories and their subcats) are there to help users filter results more finely. (The Interest groupings are largely just to provide smaller subsections of Interest tags so that I don't end up with a single, leviathan list on the left sidebar!)

Places

London
poi1
poi2
poi3
poi4...
Oxford
poi5...
Categories
See [cat]
Monument [subcat]
Museum [subcat]
Church
Do [cat]
Tour [subcat]
Shop
Get active
Relax
Interests
History [grouping]
Ancient [interest]
Medieval
Renaissance
Modern
Gastronomy [grouping]
Food [interest]
Beer
Wine
Markets

You get the idea... The reason there are separate Interest and Categories trees is that Interests are horizontal tags, applicable to any POI across all categories (the Interest "Family-friendly" would apply to a Museum under "See" or a B&B under "Sleep"), whereas Categories are vertical (a POI has only one unique Category and subcat).

Thanks again for your help.

Link to comment
Share on other sites

Oh, snap! Adam, your solution did, in fact, work. Before biting the bullet and doing a fresh install to try and track down my problem, I moused over the links one more time in hopes of a revelation... and got one! It was linking to interest/interest from the root of localhost, not from the site root. All I did was add a ".." before the initial slash in the $url call in poi.php and it worked!

//poi.php
$url = "../interests/interest/{$page->parent->parent->id}/"; //added ".." before /interests/interest

Thanks!

But the question remains: Will this be scalable, and work with the Grand Backend Architecture I mentioned above?

I mean, I am about to put on my hardhat and descend into the coding mines to see if I can make it work, but if you Jedi masters can tell at a glance whether or not this padawan will be wasting his time, please do let me know. (Sorry; just finished ordering the just-released Millennium Falcon LEGO set for my son's 8th birthday next month; they had sold out of the old one before last Christmas, and it had been the only thing on his list, so he has been waiting an eternity, in seven-year-old time.)

Link to comment
Share on other sites

Ack! In my excitement, I posted too soon. While it is, indeed, now limiting things to just the appropriate "place," it is rendering all pois in the cat (see, do, etc.), not filtering them by interest at all. Also, I get an unwieldy url: "places/london/so/interests/interest/london," when it woudl be far better to have "places/london/do/interests/interest/[name of interest]."

I will tinker and see if I can't get it working properly. At least it is doing _something_ now!

Link to comment
Share on other sites

Not much time here, but just to say that you can always link to a search page where you filter the results by get variables.

for example:

/places-search?place=london&cat=see&interests=history
/places-search?place=london&subcat=monument&interest=ancient
Link to comment
Share on other sites

OK, after trying many permutations and substitutions, i think I am having a problem back at square one with Alex's solution. Where, exactly, do I stick that 

$url = "/interests/interest/{$page->parent->parent->id}/";

into my poi.php (or, rather, my _main.php that is being called into poi.php)? Is it in the foreach loop thusly:

<?php
foreach ($page->interests as $i) {
$url = "/interests/interest/{$page->parent->parent->id}/";
echo "<li><a href='{$url}'>{$i->title}</a></li>";

...because that doesn't work. It just sends me to a (non-existent) "interests/interest/1024" page (1024 is the id for London) at my localhost root.

I've tried jamming it into every level of the site by prefacing the folder with varying strings of "../../," but it doesn't seem to be calling the interest.php template no matter where I send it, from the site root (siteroot/interests/interest/1024) all the way to a sub of the current POI page (siteroot/places/london/do/poi2/interests/interest/1024).  

I've also tried changing things up, but to no avail (I keep feeling that the {$page->parent->parent->id} really should be something more like interest->name, since that is what we're actually talking about, but figured this hack was how we were going to piggyback the place into the url to be played with later).

Link to comment
Share on other sites

You should probably take a pen, a paper, draw a sitemap and define a use case: (example) "when user clicks on interest on the page /places/london/see/, he should be taken to /interests/interest/{$name}, where he'll see other interests from this place".

Because otherwise this is a guessing game; ProcessWire allows you to structure your content any way you might want (and some you definitely do not want). Unless you have an idea what you want, every opinion will just confuse you.

On the other hand, when you'll have the sitemap (and well defined usecase), we can better assist you in achieving what you want/need.

Link to comment
Share on other sites

Thanks, guys. A few tweaks to diogo's code got me the result I was hoping for. (I was simultaneously trying to figure out if I would instead hack a search function to get what I wanted—nice thing about PW is that you can find many avenues and answers to the same result—but this is far more useful and extensible.)   

And believe me, Adam. I have the whole thing intricately mapped out. Before I discovered PW, I had a labyrinthian MySQL database model all planned out, with all the one-to-many and many-to-many connections, and a spreadsheet of all the scripts to interconnect them. I;m just having to figure out how to apply PW's logic of pages, templates, template pages, and fields to the site I have in mind.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...