We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 27072
    • 76 Posts
    Quote from: worchyld at Feb 25, 2009, 02:49 AM
    I’ve got a similar problem and I’m not sure how to solve it, and after reading this topic I’m a little closer -- but I am still having issues as to how to solve it.

    In the next post I’ll detail what I did (without adaptation to your exact situation). Let me know if it’s of any help.
      Cheers,
      Shlomo Tommer
      • 27072
      • 76 Posts
      The issue:

      I have many celebrities and for each I want to publish a few pages.

      • foo.com/celebrities/
      • foo.com/celebrities/brad-pitt/
      • foo.com/celebrities/angelina-julie/ (Angelina’s hub page)
      • foo.com/celebrities/angelina-julie/profile/
      • foo.com/celebrities/angelina-julie/contact/
      • foo.com/celebrities/angelina-julie/gallery/
      The pages (index, profile, contact, gallery) are common to all the celebrities, but their content is generated on the fly by database queries and PHP scripting.

      (3,700 celebrities and some of the content are published today here. These pages are all static, generated by a backoffice application that I developed, and uploaded (with a one-way synchronization utility via FTP). The static pages are well optimized and the new solution must use best SEO practices as well, friendly URLs included.)


      The solution:

      Two issues need to be approached:

      • Dynamic rendering of friendly URLs, that will work with MODx core navigation libraries and related MODs such as WayFinder, Breadcrumbs, etc.
      • Enabling browser accessibility to these pages.

      Note 1: The tactic behind the solution uses MODx 404 document extensively. This document is being called each time the system cannot interpret the URL. The 404 document calls a snippet that includes the business logic on how to forward the call (server-side) to a valid document.

      Note 2: The ability to browse friendly URLs can be easily achieved via .htaccess rules, but I chose to keep the business logic within the framework repository, and to maintain cross-platform compatibility with IIS servers without ISAPI_Rewrite installed.

      Note 3: The page URL mapping could have been easier had I set the following structure:
      foo.com/celebrities/profile/angelina-julie/
      but it doesn’t adhere to this particular site’s UI logic and SEO principles.


      Site Settings

      Under Tools -> Configuration -> Friendly URLs:
      Prefix for friendly URLs: [+URLPrefix+]/
      Suffix for friendly URLs: /

      [+URLPrefix+] is a PlaceHolder that is initialized in the snippet getCelebParams


      Template Settings

      I’m using one template only for all the celebrities documents.
      In this template I placed a call to getCelebParams: [[getCelebParams]]


      Snippets

      There are two snippets: getCelebParams and 404Router. The first has a role in setting up friendly urls, and the latter - in routing a URL call to the appropriate document. I will detail the snippets last in order to maintain fluidity here.


      404 Document

      Just set up a 404 document, and define its docID in site settings.

      Make sure NOT to cache the document.

      Include this call to 404Router snipped in the document content: [[404Router]] or [!404Router!].


      Celebrity Documents


      • Each of the celebrity pages has its own document (index, about, contact, profile, etc.)
      • Make sure to include the document pathname in the Document’s alias.
      • Make sure to assign a template that calls getCelebParams snippet.
      • Don’t cache the document.

      getCelebParams Snippet

      This snipped is called by the template that is shared by each of the celebrity documents.
      <?php
      
      $celebFileName = $modx->celebFileName;
      
      $sql = $modx->db->query("SELECT * FROM `cg_celebs` WHERE (FileName = '$celebFileName')");
      $result = $modx->db->getRow($sql);
      
      // Setting Placeholders:
      // =================
      $modx->setPlaceholder('URLPrefix', "celebrities/".$result['FileName']);
      
      // There is much more written here that is not related to the topic at hand.
      
      ?>
      


      404Router Snippet

      This snippet is called from the 404 document above.
      <?php
      
      // Getting the requested URL:
      $RequestURL = $_SERVER['REQUEST_URI'];
      
      // Testing if the requested URL points to the celebrities "folder":
      if (strpos($RequestURL, "celebrities/") <> 0)
      {
      // Isolating the FileName portion of the URL from the Document one:
      $celebURL = str_replace("http://", "", $RequestURL);
      $split_url = explode('/', $celebURL);
      $celebFileName = $split_url[2];
      $celebDocument = $split_url[3];
      $celebDocument = str_replace(".html", "", $celebDocument);
      
      // Casing Document for DocID:
      switch ($celebDocument) {
          case "index":
              $celebDocID = 89; // Celebrity's Homepage (Hub Page)
              break;
          case "birth-data":
              $celebDocID = 114;
              break;
          default:
             $celebDocID = 89;  // Celebrity's Homepage (Hub Page)
      }
      
      // Rerouting request to index.php without changing requested URL:
      $modx->celebFileName = $celebFileName;
      $modx->sendForward($celebDocID);
      }
      ?>
      

      Last but not least - I’m a total newbie to MODx, and a rather poor PHP coder. Please feel free to suggest improvements to this solution.
        Cheers,
        Shlomo Tommer
        • 32645
        • 377 Posts
        Questions;


        URLs
        ====
        Under Tools -> Configuration -> Friendly URLs:
        Prefix for friendly URLs: celebrities/[+URLPrefix+]/
        Suffix for friendly URLs: /

        [+URLPrefix+] is a PlaceHolder that is initialized in the snippet getCelebParams

        What happens if you go elsewhere on the website, such as "/about/"? Does it add the URL prefix to this?

        Also, does this still work if you have FURL aliases on? ie: "/parent/child/"?


        Use a 404 router to go to the actual page you want
        [[404Router]]

        But what happens if you have a legitimate 404 error?

        You’re solution is very interesting, and requires further in-depth analysis.
          • 27072
          • 76 Posts
          Quote from: worchyld at Feb 26, 2009, 02:21 AM
          What happens if you go elsewhere on the website, such as "/about/"? Does it add the URL prefix to this?

          Also, does this still work if you have FURL aliases on? ie: "/parent/child/"?

          FURL is always turned on. Thanks to your question, I changed URLPrefix placeholder to "celebrities/".$FileName, and removed "celebrities/ from the site’s friendly URL Prefix.

          Now, whenever you don’t care to activate this navigation logic, just initialize URLPrefix as "" from another template or document. This way you fully restore to the MODx natural friendly URL way.

          Quote from: worchyld at Feb 26, 2009, 02:21 AM
          But what happens if you have a legitimate 404 error?

          As you can tell by the 404 snippet script, sendForward() applies only when the URL includes "celebrities/". Otherwise the 404 document acts normally.

          Also, in the snippet’s routing casing - you get to choose where to go in case the requested page isn’t a valid one within "celebrities/" via the "default:" option.

          Hope it helps.
            Cheers,
            Shlomo Tommer
            • 32645
            • 377 Posts
            Thanks, I’ll be trying out your idea with my paritcular problem, I may opt to use HTAccess to solve the problem, but if that doesn’t work -- at least there is a backup of your solution.
              • 32645
              • 377 Posts
              Hi.

              I got this replicated on my localhost.

              Here’s what I did -- if I made a mistake, please let me know.

              1. Created a snippet called 404Router similar to yours, but because I’m only doing /celebrities/(ID)/ I don’t need the extra parameters you’re checking on.

              <?php
              /**
               * 404Router
               * @updated: 05 March 2009 
               */
              $debug = false;
              $celebDocID = 73; 
              
              // Getting the requested URL:
              $RequestURL = $_SERVER['REQUEST_URI'];
              
              if ($debug == true) print auto_p($RequestURL);
              
              // Testing if the requested URL points to the celebrities "folder":
              if (strpos($RequestURL, "celebrities/") <> 0)
              {
              	// Isolating the FileName portion of the URL from the Document one:
              	$celebURL = str_replace("http://", "", $RequestURL);
              	$split_url = explode('/', $celebURL);
              	$celebFileName = $split_url[2];
              	$celebDocument = $split_url[3];
              
              	if ($debug == true) print auto_p( "1) " . $celebURL);
              	if ($debug == true) print auto_p( "2) " . print_r($split_url)   );
              	if ($debug == true) print auto_p( "3) " . ($celebFileName) );
              
                     $modx->celebFileName = $celebFileName;
                     
                     if ($debug == true) print auto_p($celebDocID);
              
                    // Rerouting request to index.php without changing requested URL:
                    $modx->sendForward($celebDocID);
              }
              
              function auto_p($str)
              {
              	return ('<p>'.$str.'</p>');
              }
              ?>
              



              2. Created a getCelebParams snippet

              <?php
              /** 
               *  getCelebParams 
               * @updated: 05-Mar-2009
               */
              print "<p>IN getCelebParams</p>";
              print "<p>IN HERE....</p>";
              print "<p>CELBFILENAME: " . $modx->celebFileName . "</p>";
              


              I am not doing a search at the moment, as I just want to see if its working properly.

              3. I created a 404 error page which has the [!404Router!] call described.

              4. On the /celebrities/ page I put the [[getCelebParams]] snippet.

              Questions.

              1. When you go to /celebrities/ it outputs the contents of getCelebParams (which are obviousily empty). Is this right?

              2. How do you handle 404 errors under the /celebrities/ tree?

              If you go to /celebrities/something/somethingelse/

              This still tries to find the relevant page.

              Ideally I need to make it redirect if it can’t find the relevant DB data in getCelebParams.

              3. How do you prevent /celebrities/someID/somethingillegal?

              Where someID is a real id, and something illegal is just anything else. I don’t want it to handle illegal URLs (linked to question 2).

              4. How do you change the title of the page based upon what the DB data is? Does it mean creating a specific template with the getCelebParams call appearing above the custom template?

              If any of the questions are confusing, please let me know.

              Thanks.



                • 32645
                • 377 Posts
                I have a problem!

                If you use [+URLPrefix+]/ in the prefix it ruins all the links!

                I think I’m just going to use a rewrite rule to solve my problem.
                  • 32645
                  • 377 Posts
                  Hi there.

                  I’ve tried your solution and although I could only get the 404Router part working, there is a problem!

                  The problem is that Google Webmaster tools will always report it as being a 404 error in its report, therefore using 404Router is not only bad practice, it could result in bad SEO.

                  My thread on this is here:
                  http://modxcms.com/forums/index.php/board,316.0.html
                    • 22303 MODX Staff
                    • 10,725 Posts
                    Quote from: worchyld at Jun 14, 2009, 06:29 AM

                    Hi there.

                    I’ve tried your solution and although I could only get the 404Router part working, there is a problem!

                    The problem is that Google Webmaster tools will always report it as being a 404 error in its report, therefore using 404Router is not only bad practice, it could result in bad SEO.

                    My thread on this is here:
                    http://modxcms.com/forums/index.php/board,316.0.html
                    The 404Router should return an appropriate header if it "finds" things to render at the current URL, or leave it as 404 if the page really isn’t found, or redirect with a 302 Found...
                      • 32645
                      • 377 Posts
                      I understand. Thanks.