doubledee Posted January 2, 2012 Share Posted January 2, 2012 I am having problems with my $_GET. When a user chooses an Article from "article_index.php", they click on a hyperlink, e.g. <a href="<?php echo BASE_URL; ?>articles/postage-meters-can-save-you-money"> This triggers my Mod_Rewrite... RewriteEngine on #PRETTY: articles/postage-meters-can-save-you-money #UGLY: article.php?slug=postage-meters-can-save-you-money RewriteRule articles/([a-zA-Z0-9_-]+)$ article.php?slug=$1 Which should take them to "article.php?slug=postage-meters-can-save-you-money" and then this code is supposed to grab the "slug" and retrieve the Article... // Attempt to Retrieve Article. if (isset($_GET['slug'])){ // Slug found in URL. // Set Slug. $slug = $_GET['slug']; That part is working fine, however, if I go into the Address Bar and delete out the slug, so my URL looks like this... www.MySite.com/articles/"> I would expect the ELSE part of the above code to kick in... }else{ // Slug not found in URL. header("Location: " . BASE_URL . "index.php"); }//End of ATTEMPT TO RETRIEVE ARTICLE Unfortunately I am just getting this error... Not Found The requested URL /articles/ was not found on this server. Apache/2.0.59 (Unix) PHP/5.2.6 DAV/2 Server at local.debbie Port 80 Why is my ELSE not detecting that there is no slug?? Debbie Quote Link to comment Share on other sites More sharing options...
trq Posted January 2, 2012 Share Posted January 2, 2012 Because there is a slug, it just happens to be empty. Try: if (isset($_GET['slug']) && $_GET['slug']) { Quote Link to comment Share on other sites More sharing options...
doubledee Posted January 2, 2012 Author Share Posted January 2, 2012 Because there is a slug, it just happens to be empty. Why is there a slug? My rewrite says... RewriteRule articles/([a-zA-Z0-9_-]+)$ article.php?slug=$1 That doesn't match SPACE or NULL after "articles/" Try: if (isset($_GET['slug']) && $_GET['slug']) { What does your line of code mean? What is it supposed to do? Debbie Quote Link to comment Share on other sites More sharing options...
Psycho Posted January 2, 2012 Share Posted January 2, 2012 Because there is a slug, it just happens to be empty. That's what I was thinking as well. But, looking at the rewrite rule: RewriteRule articles/([a-zA-Z0-9_-]+)$ article.php?slug=$1 The plus symbol after the matching character classes stands for "one or more matches". Since there was no match, the server tried to load the URL as is articles/ - which is looking for a default file in that directory and it apparently doesn't exist. So, in addition to the change you suggested we would also want the mod rewrite rule to send the user to the correct page (even if the slug will be empty). I believe this can be achieved by changing the quantifier to an asterisk RewriteRule articles/([a-zA-Z0-9_-]*)$ article.php?slug=$1 Now, if the user has "articles/" as the end of the URL, the user will always be directed to "article.php" with the 'slug' set to the content after ""articles/" - which could be an empty value (which your suggestion will take care of). What does your line of code mean? What is it supposed to do? C'mon DoubleDee, you've been around long enough to know the difference between isset() and a check for an empty value Quote Link to comment Share on other sites More sharing options...
Psycho Posted January 2, 2012 Share Posted January 2, 2012 OK, there's an even easier solution. If there is no data at the end of articles/ then the server will look for a default file in the "articles" subfolder (which may not currently exist). You could create that folder and add an index.php file which simply includes the articles.php file (assuming that is where you want it to go). Then no changes to the modrewrite would be needed. Also, the solution that thorpe suggested wouldn't be needed either. Quote Link to comment Share on other sites More sharing options...
doubledee Posted January 2, 2012 Author Share Posted January 2, 2012 Because there is a slug, it just happens to be empty. That's what I was thinking as well. But, looking at the rewrite rule: RewriteRule articles/([a-zA-Z0-9_-]+)$ article.php?slug=$1 The plus symbol after the matching character classes stands for "one or more matches". Since there was no match, the server tried to load the URL as it - which doesn't exist. So, in addition to the change you suggested we would also want the mod rewrite rule to send the user to the correct page (even if the slug will be empty). I believe this can be achieved by changing the quantifier to an asterisk RewriteRule articles/([a-zA-Z0-9_-]*)$ article.php?slug=$1 Now, if the user has "articles/" as the end of the URL, the user will always be directed to "article.php" with the 'slug' set to the content after ""articles/" - which could be an empty value (which your suggestion will take care of). That won't work, and here is why... I am in the process of converting physical article files into a database-driven system. There is no "articles" directory. And the fie "article.php" is merely a template. If someone is hacking my URL and goes from this... http://local.debbie/articles/postage-meters-can-save-you-money ...to this... http://local.debbie/articles/postage ...then my code should catch it here... // Check # of Records Returned. if (mysqli_stmt_num_rows($stmt)==1){ // Article was Found. $articleExists = TRUE; }else{ // Article Not Found. header("Location: " . BASE_URL . "index.php"); }//End of FIND ARTICLE RECORD ---------- If someone is hacking my URL and goes from this... http://local.debbie/articles/postage-meters-can-save-you-money ...to this... http://local.debbie/articles/ ...then I want this branch - which is the parent of the one above - to work... if (isset($_GET['slug'])) { // Slug found in URL. }else{ // Slug not found in URL. header("Location: " . BASE_URL . "index.php"); }//End of ATTEMPT TO RETRIEVE ARTICLE Debbie Quote Link to comment Share on other sites More sharing options...
Psycho Posted January 2, 2012 Share Posted January 2, 2012 There is no "articles" directory. And the fie "article.php" is merely a template. If someone is hacking my URL and goes from this... http://local.debbie/articles/postage-meters-can-save-you-money ...to this... http://local.debbie/articles/ ...then I want this branch - which is the parent of the one above - to work... if (isset($_GET['slug'])) { // Slug found in URL. }else{ // Slug not found in URL. header("Location: " . BASE_URL . "index.php"); }//End of ATTEMPT TO RETRIEVE ARTICLE What we have here is a failure to communicate. Let me repeat what I stated previously in a different way: User enters: http://local.debbie/articles/ Your rewrite rule RewriteRule articles/([a-zA-Z0-9_-]+)$ article.php?slug=$1 will not do anything because there was NO MATCH! So, the server will try to load the URL as the user entered it - which does not exist and is causing the error you have. So you CAN'T use that "branch" in your code because it will never load that page. You have multiple options that will do what you want: 1. Change the rewrite rule to use an asterisk so the user will be redirected to article.php even if nothing was added at the end of the URL. If you do that then the slug will have an empty value and you would want to use thorpe's suggestion as well. 2. You can add an additional rewrite rule to handle this one specific scenario to redirect the user to article.php without a slug. Pretty stupid IMHO 3. You can create an 'articles' folder with a default file that can do whatever you want. It can redirect the user to another page, it can provide a message, whatever. Again, this woulod exists just for this one specific scenario which seems a waste to me. 4. (I like this the best). Change your article.php file to index.php and put it in a folder called 'articles'. Then change your rewrite rule to RewriteRule articles/([a-zA-Z0-9_-]+)$ articles/index.php?slug=$1. You would still use the same links that you are using now. All this would do is move the file that is loaded. But, now, if the user enters in articles/ with nothing on the end, then the same file will be loaded without a slug parameter. This is one of those types of solutions that "just works" I've given you four options that can all do what you need if implemented correctly. Quote Link to comment Share on other sites More sharing options...
doubledee Posted January 2, 2012 Author Share Posted January 2, 2012 What we have here is a failure to communicate. *cue the music* Let me repeat what I stated previously in a different way: User enters: http://local.debbie/articles/ Your rewrite rule RewriteRule articles/([a-zA-Z0-9_-]+)$ article.php?slug=$1 will not do anything because there was NO MATCH! Right. So, the server will try to load the URL as the user entered it - which does not exist and is causing the error you have. Okay. So you CAN'T use that "branch" in your code because it will never load that page. A-ha!! You have multiple options that will do what you want: 1. Change the rewrite rule to use an asterisk so the user will be redirected to article.php even if nothing was added at the end of the URL. If you do that then the slug will have an empty value and you would want to use thorpe's suggestion as well. So if I have if (isset($_GET['slug']) && $_GET['slug']) { then my code should catch the missing slug value and my ELSE will kick in and I will re-drect the user to my Home Page, right? 2. You can add an additional rewrite rule to handle this one specific scenario to redirect the user to article.php without a slug. Pretty stupid IMHO Okay. 3. You can create an 'articles' folder with a default file that can do whatever you want. It can redirect the user to another page, it can provide a message, whatever. Again, this would exists just for this one specific scenario which seems a waste to me. Okay. 4. (I like this the best). Change your article.php file to index.php and put it in a folder called 'articles'. Is this a fairly common technique? Then change your rewrite rule to RewriteRule articles/([a-zA-Z0-9_-]+)$ articles/index.php?slug=$1. You would still use the same links that you are using now. All this would do is move the file that is loaded. But, now, if the user enters in articles/ with nothing on the end, then the same file will be loaded without a slug parameter. This is one of those types of solutions that "just works" So just like in Option #1, if the user enters articles/ with nothing on the end, then my code should catch that and the ELSE will kick in and then I can do whatever I want - in my case redirecting to the Home Page. Option #4 sounds pretty good. So if I have other templates called "interview.php" and "case_study.php" then I would repeat what you are saying? Does creating these extra empty folders really hurt anything? Thanks, Debbie Quote Link to comment Share on other sites More sharing options...
Psycho Posted January 2, 2012 Share Posted January 2, 2012 You have multiple options that will do what you want: 1. Change the rewrite rule to use an asterisk so the user will be redirected to article.php even if nothing was added at the end of the URL. If you do that then the slug will have an empty value and you would want to use thorpe's suggestion as well. So if I have if (isset($_GET['slug']) && $_GET['slug']) { then my code should catch the missing slug value and my ELSE will kick in and I will re-drect the user to my Home Page, right? If you change the rewrite rule to work even when there is nothing following articles/ AND you change the if() condition to check that $_GET['slug'] is set AND has a value, then the else condition of that check should be executed 4. (I like this the best). Change your article.php file to index.php and put it in a folder called 'articles'.Is this a fairly common technique? Don't know and don't care. It will work and does not require any special handling. Simplicity is best IMHO. So just like in Option #1, if the user enters articles/ with nothing on the end, then my code should catch that and the ELSE will kick in and then I can do whatever I want - in my case redirecting to the Home Page. Right, and there is no need for the additional check of the GET variable to see if it is empty (that was never the source of the problem anyway). However, it's not a bad idea to check for an empty value anyway. And, I 'assume' you have appropriate error handling of the slug in cases where the user submits a value for which there is no article. Does creating these extra empty folders really hurt anything? There are no "empty" folders. You would put the file that handles the article display into that folder with the name index.php or something that will be treated as a default. Then, the modrewrite rule would be changed to redirect to the new location. The elegant part of this solution is that if the user does not put an article name at the end the rewrite rule is not triggered, but the server will automatically load the right file and the slug will not be set. So: 1. Rename 'article.php' to 'index.php' and put into a sub-folder called 'articles' 2. Change rewrite rule to RewriteRule articles/([a-zA-Z0-9_-]+)$ articles/index.php?slug=$1 The only other changes you may need to make are to any relative paths to include files used in that script. Quote Link to comment Share on other sites More sharing options...
doubledee Posted January 3, 2012 Author Share Posted January 3, 2012 So just like in Option #1, if the user enters articles/ with nothing on the end, then my code should catch that and the ELSE will kick in and then I can do whatever I want - in my case redirecting to the Home Page. Right, and there is no need for the additional check of the GET variable to see if it is empty (that was never the source of the problem anyway). However, it's not a bad idea to check for an empty value anyway. And, I 'assume' you have appropriate error handling of the slug in cases where the user submits a value for which there is no article. See my code below... Does creating these extra empty folders really hurt anything? There are no "empty" folders. You would put the file that handles the article display into that folder with the name index.php or something that will be treated as a default. Then, the modrewrite rule would be changed to redirect to the new location. The elegant part of this solution is that if the user does not put an article name at the end the rewrite rule is not triggered, but the server will automatically load the right file and the slug will not be set. So: 1. Rename 'article.php' to 'index.php' and put into a sub-folder called 'articles' 2. Change rewrite rule to RewriteRule articles/([a-zA-Z0-9_-]+)$ articles/index.php?slug=$1 The only other changes you may need to make are to any relative paths to include files used in that script. If I rename "article.php" to "index.php" and put it in a new folder called "articles" then if a user takes off the slug, Apache would default to "index.php" which is my Article Template, right? But if that happens, I think I would like them re-routed to my "Article Index" which is a summary of all Articles... So should I rename "article_index.php" to "index.php" and place that in the "Articles" folder, and then move "article.php" to the "Articles" folder but do NOT rename it, so that if there is no slug control automatically goes back to my Article Index. Does that make more sense, and still do what you proposed? Here is my code... It is basically the same code I had before, except I am re-directing to "articles/article_index.php" if either the Article cannot be found (i.e. wrong slug) or there is no slug at all. (This is different than what I described above, which I am not thinking wouldn't work.) <?php //Build Date: 2012-01-02 // Initialize a session. session_start(); // Access Constants. require_once('config/config.inc.php'); // Initialize variables. $articleExists = FALSE; // ****************************** // Attempt to Retrieve Article. * // ****************************** // if (isset($_GET['slug'])){ if (isset($_GET['slug']) && $_GET['slug']) { // Slug found in URL. // Set Slug. $slug = $_GET['slug']; // ************************ // Find Article Record. * // ************************ // Connect to the database. require_once(WEB_ROOT . 'private/mysqli_connect.php'); // Set current Script Name. $_SESSION['returnToPage'] = $_SERVER['SCRIPT_NAME'] . '?slug=' . $slug; // Build query. $q = 'SELECT id, title, description, keywords, heading, sub_heading, published_on, author, body, reference_listing, endnote_listing FROM article WHERE slug=?'; // Prepare statement. $stmt = mysqli_prepare($dbc, $q); // Bind variable to query. mysqli_stmt_bind_param($stmt, 's', $slug); // Execute query. mysqli_stmt_execute($stmt); // Store results. mysqli_stmt_store_result($stmt); // Check # of Records Returned. if (mysqli_stmt_num_rows($stmt)==1){ // Article was Found. $articleExists = TRUE; // Bind result-set to variables. mysqli_stmt_bind_result($stmt, $articleID, $title, $description, $keywords, $heading, $subHeading, $publishedOn, $author, $body, $referenceListing, $endnoteListing); // Fetch record. mysqli_stmt_fetch($stmt); // Close prepared statement. mysqli_stmt_close($stmt); // ???? // Set Session variables. $_SESSION['articleID'] = $articleID; }else{ echo 'Article not found'; // Article Not Found. header("Location: " . BASE_URL . "articles/article_index.php"); // Go to Article Index // header("Location: " . BASE_URL . "index.php"); // Go to Home Page }//End of FIND ARTICLE RECORD }else{ echo 'Slug not found'; // Slug not found in URL. header("Location: " . BASE_URL . "articles/article_index.php"); // Go to Article Index // header("Location: " . BASE_URL . "index.php"); // Go to Home Page }//End of ATTEMPT TO RETRIEVE ARTICLE ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> </head> <body> </body> </html> Thanks, Debbie Quote Link to comment Share on other sites More sharing options...
Psycho Posted January 3, 2012 Share Posted January 3, 2012 If I rename "article.php" to "index.php" and put it in a new folder called "articles" then if a user takes off the slug, Apache would default to "index.php" which is my Article Template, right? But if that happens, I think I would like them re-routed to my "Article Index" which is a summary of all Articles... What? Then why have you been complaining that the "else" condition was not executing - which would redirect the user to your home page? }else{ // Slug not found in URL. header("Location: " . BASE_URL . "index.php"); }//End of ATTEMPT TO RETRIEVE ARTICLE If you want the user to see the article directory then change the code in the else condition to load the article directory. I would still do exactly as I had proposed before, but just change the else condition to show the article index. Quote Link to comment Share on other sites More sharing options...
doubledee Posted January 3, 2012 Author Share Posted January 3, 2012 If I rename "article.php" to "index.php" and put it in a new folder called "articles" then if a user takes off the slug, Apache would default to "index.php" which is my Article Template, right? But if that happens, I think I would like them re-routed to my "Article Index" which is a summary of all Articles... What? Then why have you been complaining that the "else" condition was not executing - which would redirect the user to your home page? }else{ // Slug not found in URL. header("Location: " . BASE_URL . "index.php"); }//End of ATTEMPT TO RETRIEVE ARTICLE First, I haven't been "complaining" about anything... My ELSE was not executing. As I explained, if the user took off the slug, I got a page not found error. If you want the user to see the article directory then change the code in the else condition to load the article directory. I would still do exactly as I had proposed before, but just change the else condition to show the article index. I don't think you are following me... I did exactly as you proposed with a minor tweak. 1.) I created an "articles" directory 2.) I changed my Mod_Rewrite to look like this... RewriteEngine on #PRETTY: articles/postage-meters-can-save-you-money #UGLY: article.php?slug=postage-meters-can-save-you-money #RewriteRule articles/([a-zA-Z0-9_-]+)$ article.php?slug=$1 RewriteRule articles/([a-zA-Z0-9_-]+)$ articles/article.php?slug=$1 3.) I moved "article.php" from the Document Root to the "articles" directory 4.) I renamed my "article_index.php" to "index.php" 5.) I moved this new "index.php" to the "articles" directory In this new "index.php" is a link to the the 1st article: local.debbie/articles/postage-meters-can-save-you-money So my Mod_Rewrite would change that behinds the scenes to... local.debbie/articles/article.php?slug=postage-meters-can-save-you-money If a user deletes the slug, then we have... local.debbie/articles/ And Apache just looks for a default file which in this case is "articles/index.php" which is my Article Listing which seems like a better place to take a user that maybe wasn't being malicious, but just wanted to see all of the Articles?! Is that not the spirit of what you recommended? I think I got it right, and it seems to work except for one annoying problem... In my included header file, I can't get the "Articles" tab to be highlighted because our changes messed things up and now I have TWO "index.php" files. Here is some header snippet... <?php // Determine Current Script. $page = basename($_SERVER['REQUEST_URI']); if ($page == '') { $page = "index.php"; } ?> <!-- TOP MENU --> <ul id="topMenu"> <li <?php if($page=="index.php") echo 'class="current"'; ?>> <a href="/index.php">Home</a> </li> <!-- If I change this to "index.php" then it conflicts with the Home Page?! What do I do here? --> <li <?php if($page=="article_index.php") echo 'class="current"'; ?>> <a href="/article_index.php">Articles</a> </li> </ul><!-- End of #TOPMENU --> Thanks, Debbie Quote Link to comment Share on other sites More sharing options...
Psycho Posted January 3, 2012 Share Posted January 3, 2012 Then you need to "fix" your logic for highlighting the tabs. I would not use the file names to determine that. I would suggest you set a variable in your controller pages before including the header file Quote Link to comment Share on other sites More sharing options...
doubledee Posted January 3, 2012 Author Share Posted January 3, 2012 Then you need to "fix" your logic for highlighting the tabs. I would not use the file names to determine that. I would suggest you set a variable in your controller pages before including the header file First, can you please explain what you were getting all frustrated about? Did I not do what you recommend with my original issue?? -------------- What is wrong with my logic on shading the tabs? Here is the code I came up which works... <?php // Determine Script Name. $scriptName = $_SERVER['SCRIPT_NAME']; ?> <!-- TOP MENU --> <ul id="topMenu"> <li <?php if($scriptName=="/index.php") echo 'class="current"'; ?>> <a href="/index.php">Home</a> </li> <li <?php if(($scriptName=="/articles/index.php") ||($scriptName=="/articles/article.php")) echo 'class="current"'; ?>> <a href="/articles/index.php">Articles</a> </li> <li <?php if($scriptName=="/pages/howto_index.php") echo 'class="current"'; ?>> <a href="/pages/howto_index.php">How-To Guides</a> </li> What is wrong with that? Debbie Quote Link to comment Share on other sites More sharing options...
Psycho Posted January 3, 2012 Share Posted January 3, 2012 Then you need to "fix" your logic for highlighting the tabs. I would not use the file names to determine that. I would suggest you set a variable in your controller pages before including the header file First, can you please explain what you were getting all frustrated about? Did I not do what you recommend with my original issue?? I'm not frustrated. I simply stated you needed to fix your logic for the tabs. Your current logic keys off the file names. That's a poor implementation in my opinion (many sites have several index.php files). I almost always use "controller" files which handle all the logic for my pages which allows me a great deal of flexibility. I set any number of variables on the "called" page which then includes the controller script which then does all the heavy lifting. You can solve this new problem in any manner you choose. I provided a solution for the problem you started this thread for - which caused a separate, unrelated problem. I gave you a suggestion on how to fix that. You can either take my suggestion or you can reject it. Quote Link to comment Share on other sites More sharing options...
doubledee Posted January 3, 2012 Author Share Posted January 3, 2012 Then you need to "fix" your logic for highlighting the tabs. I would not use the file names to determine that. I would suggest you set a variable in your controller pages before including the header file First, can you please explain what you were getting all frustrated about? Did I not do what you recommend with my original issue?? I'm not frustrated. I simply stated you needed to fix your logic for the tabs. Your current logic keys off the file names. That's a poor implementation in my opinion (many sites have several index.php files). I almost always use "controller" files which handle all the logic for my pages which allows me a great deal of flexibility. I set any number of variables on the "called" page which then includes the controller script which then does all the heavy lifting. You can solve this new problem in any manner you choose. I provided a solution for the problem you started this thread for - which caused a separate, unrelated problem. I gave you a suggestion on how to fix that. You can either take my suggestion or you can reject it. In Reply #10 you made it sound like I never listened to your advice and that my code didn't match what you suggested. Care to clarify that? As I said in Reply #11, I thought I followed your ideas almost to a "T". ------ Concerning my tabs, then how do you do things? I have no way of knowing how your "controller" works?! If it is superior to my approach, then please let me know how to improve my code some more. Thanks, Debbie Quote Link to comment Share on other sites More sharing options...
Psycho Posted January 3, 2012 Share Posted January 3, 2012 In Reply #10 you made it sound like I never listened to your advice and that my code didn't match what you suggested. There is nothing to be gained from responding to this. Concerning my tabs, then how do you do things? I have no way of knowing how your "controller" works?! If it is superior to my approach, then please let me know how to improve my code some more. I already provided a general approach. I'm not going to try and explain an entire methodology in a forum post. The easiest approach, IMO, for what you already have is to set specific variables in your main pages that will then be utilized by your header script. In addition to defining the area being displayed (so you can highlight the appropriate tab) you can set the page title so it is appropriate based upon the content being displayed. Example: In the main script for displaying articles: $content_area = "articles"; $page_title = "Article: " . $article_name; In the header script you could do something like this. (note: this is just an example, I'm not saying you follow this exact process.) //Define the tab class for each tab if(!isset($content_area)) { $content_area=='home'; } $homeClass = ($content_area=='home') ? 'highlight' : ''; $articlesClass = ($content_area=='articles') ? 'highlight' : ''; //Display the tabs echo "<a href='index.php' class='{$homeClass}'>Home</a><br>\n"; echo "<a href='articles.php.php' class='{$articlesClass}'>Articles</a><br>\n"; Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.