Welcome Guest!
Please login
If you do not have an account yet on The Web Squeeze forums, please Register! It’s FREE and there are many benefits:
- Receive Fast Advice
- Learn Programming Languages
- Get Professional Website Reviews
- Quick Troubleshooting Assistance
|
|
Foreach Problem -- Table Of Contents Script
This is a discussion on Foreach Problem -- Table Of Contents Script, within the PHP section. This forum and the thread "Foreach Problem -- Table Of Contents Script" are both part of the Programming Your Website category.
![]() ![]() |
Apr 3 2008, 08:29 AM
Post
#1
|
|
|
Squeeze Machine ![]() ![]() ![]() ![]() ![]() Group: Mentor Posts: 600 Joined: 15-February 08 From: UK Member No.: 143 |
I'm writing some PHP to generate a table of contents. The idea is for me to write the minimum code each time I make a TOC.
So normally, a single entry might look like this: CODE <li><a href=\"".$host."/articles/serving-guide/badminton-serve-types.php\">The four types of serve</a></li> Instead, I want PHP to create this code from (part of) a variable like this:CODE $tocArray = "||badminton-serve-types|The four types of badminton serve"; Here, I use the "||" to separate items and the "|" to separate the URL from the anchor text.With me so far? That bit is okay, but I also need to nest lists to create subsections (one level of nesting). I do this by adding the signal characters "+" and "-" onto the end of the title. "+" signals "opening a nested list" and "-" signals "closing a nested list". This part -- the nested lists -- is causing problems with my foreach loop. It only applies the test for the last entry; all other signalled entries are being ignored by the loop. Here's my full code: CODE <?php The only way to activate my debug text is by changing the last item to have a signal "+", like this:$tocArray = "|Introduction ||basic-technique/|Basic serving technique+ ||backhand-low-serve-technique|Backhand low serve ||backhand-flick-serve-technique|Backhand flick serve- ||tactics|Serving tactics"; $tocList=explode("||", $tocArray); $directory = ""; // placeholder empty string; foreach($tocList as $value) { $temp = explode("|",$value); $temp3 = trim($temp[1]); $temp4 = rtrim($temp3, "+-"); // removes nesting-signal characters from anchor text if ( (substr($temp[0], -1) != "/") && ( strlen($temp[0]) > 0) ) {$temp[0] .= ".php";} // adds .php for all non-directory URLs $tocURL = $host."/articles/".$article."/".$directory.$temp[0]; // creates a URL if ($tocURL == ($host.$path)) { $entry ="<li class=\"here\"><span>".$temp4."</span>"; } // "you are here" formatting else { $entry = "<li><a href=\"".$tocURL."\">".$temp4."</a>"; } // normal link $temp2 = substr($temp[1], -1); if ($temp2 == "+") { // for the start of a section $directory = $temp[0]; // capturing the directory string for later echo $entry."<ol>\n\t"; // starting a nested list echo "DEBUG: I dont understand PHP"; } if ($temp2 == "-") { // for the end of a section echo $entry."</li>\n\t</ol></li>"; // ending nested list $directory = ""; // resetting directory } if ($temp2 != "-" && $temp2 != "+") { echo $entry."</li>\n"; } } ?> CODE $tocArray = If I do this, then if ($temp2 == "+") evaluates as true, and the debug text appears."|Introduction ||basic-technique/|Basic serving technique+ ||backhand-low-serve-technique|Backhand low serve ||backhand-flick-serve-technique|Backhand flick serve- ||tactics|Serving tactics+; What's going on? This post has been edited by MikeHopley: Apr 3 2008, 09:38 AM |
|
|
Apr 3 2008, 09:31 AM
Post
#2
|
|
![]() Rapid Squeezer ![]() ![]() ![]() ![]() Group: Advisors Posts: 176 Joined: 14-February 08 From: Willich, Germany Member No.: 56 |
Grrrrr! That's a tricky one.... I can't find your error, and in an attempt to write a recursive function i only succeeded in frying some brain cells.... i'll have another look at this later.....
-------------------- www.c010depunkk.com ~ the hangout of a web developer
|
|
|
Apr 3 2008, 09:37 AM
Post
#3
|
|
|
Squeeze Machine ![]() ![]() ![]() ![]() ![]() Group: Mentor Posts: 600 Joined: 15-February 08 From: UK Member No.: 143 |
Grrrrr! That's a tricky one.... I can't find your error, and in an attempt to write a recursive function i only succeeded in frying some brain cells.... i'll have another look at this later..... Thanks for looking! I have a feeling it's something fundamental to do with how variables behave inside a loop, but I'm completely out of my depth here... |
|
|
Apr 3 2008, 10:25 AM
Post
#4
|
|
![]() Rapid Squeezer ![]() ![]() ![]() ![]() Group: Advisors Posts: 176 Joined: 14-February 08 From: Willich, Germany Member No.: 56 |
OK, here's a recursive function that can handle endlessly nested toc's
I didn't add all your extra stuff like highlighting the current link and so, but hopefully you can modify it to fit your needs: CODE <?php
$tocArray = "|Introduction ||basic-technique/|Basic serving technique+ ||backhand-low-serve-technique|Backhand low serve ||basic-technique/|Basic serving technique+ ||backhand-low-serve-technique|Backhand low serve ||backhand-flick-serve-technique|Backhand flick serve- ||backhand-flick-serve-technique|Backhand flick serve- ||basic-technique/|Basic serving technique+ ||backhand-low-serve-technique|Backhand low serve ||backhand-flick-serve-technique|Backhand flick serve- ||tactics|Serving tactics"; echo('<ul>'.make_menu($tocArray).'</ul>'); function make_menu(&$str) { $rs=''; //$str=trim($str,"\t"); $last_char=''; do { $vpp=strpos($str,'||'); // find first vertical pipe pair $ss=($vpp?substr($str,0,$vpp):$str); // get sub-text (the inline if is for the very last link $str=substr($str,$vpp+2); // chop the original string $p=explode('|',$ss); // explode link and text $n=rtrim($p[1]); // kill any crapp on the end $ln=strlen($n)-1; // get the length $last_char=$n[$ln]; // get the last char $lt=(($last_char=='+'||$last_char=='-')?substr($n,0,$ln-2):$n); // clean up the link text $rs.='<li><a href="'.$p[0].'">'.$lt.'</a>'; // make the link if($last_char=='+') { // check if we should do a nested list $rs.='<ul>'.make_menu($str).'</ul>'; // call this function recursively for the nested list } $rs.='</li>'."\n"; // end this item } while($vpp&&($last_char!='-')); // keep going as long as no minus or the end of the string comes return $rs; // return the list } ?> -------------------- www.c010depunkk.com ~ the hangout of a web developer
|
|
|
Apr 3 2008, 10:43 AM
Post
#5
|
|
|
Squeeze Machine ![]() ![]() ![]() ![]() ![]() Group: Mentor Posts: 600 Joined: 15-February 08 From: UK Member No.: 143 |
OK, here's a recursive function that can handle endlessly nested toc's I didn't add all your extra stuff like highlighting the current link and so, but hopefully you can modify it to fit your needs: Wow, thank you so much! That's better than just fixing the problem -- you're also helping me learn better coding. I'll have to stop working on this now, but I'll check out your function tomorrow to test it and see if I can understand it. Thanks again! |
|
|
Apr 3 2008, 10:45 AM
Post
#6
|
|
![]() Squeeze Machine ![]() ![]() ![]() ![]() ![]() Group: Administrators Posts: 643 Joined: 13-February 08 From: Catching the squeezed drips downunder. Member No.: 13 |
Well, c010depunkk already gave his code but I'll show you mine...
Just a matter of adding an extra couple of bars around your plus and minus signs -- makes for less conditional checks and string functions. I think the problem you had mike was that your conditionals were coming up in the wrong order and skipping at the incorrect places. CODE <?php
$tocArray = "|Introduction ||basic-technique/|Basic serving technique ||+||backhand-low-serve-technique|Backhand low serve ||backhand-flick-serve-technique|Backhand flick serve ||-||tactics|Serving tactics"; $tocList=explode("||", $tocArray); $directory = ""; // placeholder empty string; foreach($tocList as $key => $value) { $value = trim($value); // First things first // if this is the start or end of some nested elements -- close it all up if ($value == '+') { echo '<ol>'; continue; } else if ($value == '-') { echo '</ol></li>'; continue; } // Get the two parts of the string now $temp = explode("|",$value); $temp[0] = trim($temp[0]); $temp[1] = trim($temp[1]); // Trip that icky white-space // Add .php to all non-directory URLs $temp[0] = substr($temp[0], -1) != "/" && strlen($temp[0]) > 0 ? $temp[0] . '.php' : $temp[0]; // create a noice loitle urelly $tocURL = $host."/articles/".$article."/".$directory.$temp[0]; // Okay so here's what I'm going to do // we will start the list element // "you are here" formatting if ($tocURL == ($host.$path)) { echo "<li class=\"here\"><span>", $temp[1], "</span>"; // normal link } else { echo "<li><a href=\"", $tocURL, "\">".$temp[1]."</a>"; } // Now we check if this element will be followed by a + sign -- we will close the list only if // it is not if ($tocList[$key+1] != '+') echo '</li>'; } ?> -------------------- |
|
|
Apr 3 2008, 11:05 AM
Post
#7
|
|
|
Squeeze Machine ![]() ![]() ![]() ![]() ![]() Group: Mentor Posts: 600 Joined: 15-February 08 From: UK Member No.: 143 |
Thanks Rakuli! It's interesting to see how a slight change in method makes things much simpler -- and hence less likely to fail.
I shall be playing with both of these solutions at some point (though because I'm lazy, I'll probably start with Rakuli's and save c010depunkk's for when I want arbitrary amounts of nesting). Cheers! *whispers* The WebSqueeze left Webforumz in the dust for this problem. Well, c010depunkk already gave his code but I'll show you mine...
Just a matter of adding an extra couple of bars around your plus and minus signs -- makes for less conditional checks and string functions. I think the problem you had mike was that your conditionals were coming up in the wrong order and skipping at the incorrect places. This post has been edited by MikeHopley: Apr 3 2008, 11:08 AM |
|
|
Apr 3 2008, 11:10 AM
Post
#8
|
|
![]() Squeeze Machine ![]() ![]() ![]() ![]() ![]() Group: Administrators Posts: 643 Joined: 13-February 08 From: Catching the squeezed drips downunder. Member No.: 13 |
QUOTE shall be playing with both of these solutions at some point (though because I'm lazy, I'll probably start with Rakuli's and save c010depunkk's for when I want arbitrary amounts of nesting). LOL -- My method allows for arbitrary nesting as well wink...no problem -------------------- |
|
|
Apr 4 2008, 12:41 AM
Post
#9
|
|
![]() Rapid Squeezer ![]() ![]() ![]() ![]() Group: Advisors Posts: 176 Joined: 14-February 08 From: Willich, Germany Member No.: 56 |
ROFL!!! I love it when me and Rakuli flood the forums with alternate solutions
One of these days we are going to have to stage a "PHP Battle" where me and Rakuli battle it out to decide who is the ober-guru It'll be a huge sponsored event, with tons of publicity for The Squeeze and huge amounts of spectators... How about we do it in Heinz Stadium, in PA? We could sell hot dogs.... *c010depunkk cracks his fingers, cackles evilly, hunches lower over the keyboard and sharpens his parentheses* -------------------- www.c010depunkk.com ~ the hangout of a web developer
|
|
|
Apr 4 2008, 12:52 AM
Post
#10
|
|
![]() Squeeze Machine ![]() ![]() ![]() ![]() ![]() Group: Administrators Posts: 643 Joined: 13-February 08 From: Catching the squeezed drips downunder. Member No.: 13 |
** Types message with his spare hand while doing one-armed push-ups **
So, the script has been written? Doesn't mean I can't write a better one -------------------- |
|
|
Apr 4 2008, 06:16 AM
Post
#11
|
|
|
Squeeze Machine ![]() ![]() ![]() ![]() ![]() Group: Mentor Posts: 600 Joined: 15-February 08 From: UK Member No.: 143 |
Hurrah! It works -- with a little tweaking to set the directory paths correctly.
Now I need to add one more element to the script, and then I'll post my completed solution. |
|
|
Apr 4 2008, 06:37 AM
Post
#12
|
|
|
Squeeze Machine ![]() ![]() ![]() ![]() ![]() Group: Mentor Posts: 600 Joined: 15-February 08 From: UK Member No.: 143 |
Finished! Here's my complete code, which also allows for setting skill levels by appending the title with *IA (intermediate and advanced) or *A (advanced only). The really neat thing about this is that, if I mark a section as *A, then all the subsection pages are also affected (because the whole subsection list is contained within the section <li>).
CODE $tocList=explode("||", $tocArray); $directory = ""; // placeholder empty string; foreach($tocList as $key => $value) { $value = trim($value); // First things first // if this is the start or end of some nested elements -- close it all up // Get the two parts of the string now $temp = explode("|",$value); $temp[0] = trim($temp[0]); $temp[1] = trim($temp[1]); // Trim white-space // Apply skill classes (hides some pages from beginners) $skills = explode("*", $temp[1]); if ($skills[1] == "IA") { $skillClass = "intermediate advanced"; $temp[1] = $skills[0]; // Removing skill tokens from anchor text } else if ($skills[1] == "A") { $skillClass = "advanced"; $temp[1] = $skills[0]; // Removing skill tokens from anchor text } else { $skillClass = ""; } if ($tocList[$key-1] == '+') { $tempDir = explode("|", $tocList[$key-2]); $directory = $tempDir[0]; } if ($value == '+') { echo "<ol>\n"; continue; } else if ($value == '-') { echo '</ol></li>'; $directory = ""; continue; } // Add .php to all non-directory URLs $temp[0] = substr($temp[0], -1) != "/" && strlen($temp[0]) > 0 ? $temp[0] . '.php' : $temp[0]; // create a URL $tocURL = $host."/articles/".$article."/".$directory.$temp[0]; // "you are here" formatting if ($tocURL == ($host.$path)) { echo "<li class=\"here\"><span>", $temp[1], "</span>"; // normal link } else { echo "<li class=\"".$skillClass."\"><a href=\"".$tocURL."\">".$temp[1]."</a>"; } // Now we check if this element will be followed by a + sign -- we will close the list only if // it is not if ($tocList[$key+1] != '+') echo "</li>\n"; } ...and here's an example TOC file: CODE <?php $tocArray = "|Introduction ||grip-principles|Grip principles ||racket-bevels|Badminton racket bevels ||grips/|Fundamental badminton grps ||+||basic-grip|Basic grip ||panhandle-grip|Panhandle grip ||thumb-grip|Thumb grip ||bevel-grip|Bevel grip*IA ||-||changing-grip|Changing grip ||grip-adjustments/|Adjusting your grip*IA ||+||grip-length|Grip length ||late-forehand-grip-adjustment|Late forehand ||late-backhand-grip-adjustment|Late backhand ||smash-grip-adjustment|Smash*A ||-||which-grip/|Which badminton grip?*IA ||+||serve|Which grip for serving? ||serve-return|Which grip for returning serve? ||net-shot|Which grip for net shots? ||net-kill|Which grip for net kills? ||drive-push|Which grip for drives and pushes? ||lift|Which grip for lifts? ||smash-defence|Which grip for smash defence? ||clear-smash-drop|Which grip for clears, smashes, and drops? ||-||background/|Background information ||+||old-grips|What happened to the old grips? ||grip-size|Grip size ||marking-the-racket-handle|Marking the racket handle ||alternative-views|Alternative views*A ||mechanics-of-grip-length|Mechanics of grip length*A||- ";?> This has made writing TOC's much easier, and has also allowed me to cut out reliance on javascript for the current-page-highlighting effect. This post has been edited by MikeHopley: Apr 4 2008, 06:40 AM |
|
|
If you found The Web Squeeze to be helpful, please donate so we can keep this site FREE, FRESH, and fortified with Web Design & Development info!
![]() ![]() |
1 User(s) are reading this topic (1 Guests and 0 Anonymous Users)
0 Members:
Similar Topics
| Topic Title | Replies | Topic Starter | Views | Last Action | ||
|---|---|---|---|---|---|---|
![]() |
10 | jackfranklin | 308 | 17th February 2008 - 01:44 PM Last post by: Rakuli |
||
![]() |






Apr 3 2008, 08:29 AM








