Well what I do on my projects is pretty simple, I rewrite everything to index.php then in index.php I direct the request based on $_SERVER['REQUEST_URI'] which i parse for relevant parts.

RewriteEngine ON
RewriteBase /

RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule (.*) index.php  [L]
    Weedpacket;11014693 wrote:

    The new one, since that is what you want a client to send when it makes a request.

    As for the rule, see http://httpd.apache.org/docs/current/rewrite/intro.html#InternalBackRefs

    Although my thinking is that there's not really any point in doing any of this for an administration control panel, because who cares if the URLs aren't pretty and/or easy to remember? Who's going to see them?

    I see, so in both html urls and forms too? The below html form code will work?

    <form name='form1' method='post' action='user/edit/{$id}'>
    

    Well the idea is to be consistent with the main site though, but yeah I can just direct all requests from admincp to index.php. In fact I am thinking about a similar solution as VB's ACP in which you do not even know which 'url' you are being directed since it all shows as 'index.php' without any other things in query string. I know it can be done, but can be difficult?

    And I'd assume I will need a different .htaccess file in admin control panel's directory if its rewrite rule is different from the main site, correct?

      Lord Yggdrasill;11014709 wrote:

      I see, so in both html urls and forms too?

      There's no difference between the two. URLs are all treated the same, whether your browser is following a hyperlink, submitting a form, downloading an image, downloading a CSS stylesheet, etc.

        Lord Yggdrasill wrote:

        And I'd assume I will need a different .htaccess file in admin control panel's directory if its rewrite rule is different from the main site, correct?

        Again, the Apache documentation has something to say on this subject (http://httpd.apache.org/docs/current/howto/htaccess.html#when):

        In general, you should only use .htaccess files when you don't have access to the main server configuration file.

          If you are running everything (both "normal" users and admin users) under the same framework, then it doesn't really add any work to have the admin interface use "nice" URL's too, especially if it means you don't need different configuration settings (e.g. .htaccess files) for each.

            5 days later
            Weedpacket;11014717 wrote:

            Again, the Apache documentation has something to say on this subject (http://httpd.apache.org/docs/current/howto/htaccess.html#when):

            Well yeah I know about this. The fact is that I am designing a software, it is to be used by people who are either noncoders or beginner programmers. For this reason it is not a good idea to assume every client of my script will have access to the main server configuration file. Some are actually using shared or even free hosts.

              I do pretty much what Derokorian does and everything goes through a front end index.php - though I split the url to the various components in htaccess.
              Admin has its own index.php and I don't rewrite those urls - that has an htaccess with 'rewrite engine off' - just seems nice and simple to maintain this way.
              Hmm, I guess it could all be under the one engine...
              I then put a short check at top of all other scripts to stop them being run directly

                7 days later

                Well there is one thing I was wondering. In the old php url format, you have something like yoursite.com/page.php?action=edit&id=5&confirm=yes. PHP knows how to map each information to $GET array, in this case apparently 'edit' is stored in $GET['action'], '5' is stored in $GET['id'], and 'yes' is stored in $GET['confirm'].

                Now consider a different url format used in most MVC framework, yoursite.com/page/edit/5/yes. There is no such information telling the controller which part of the string belongs to 'action', 'id' and 'confirm'. Consider a user is being redirected to this address through a link or a form, how is the controller supposed to interpret the url? It can get more complicated, some controllers/pages may not follow the format page/action/id/confirm. On a user profile the string may contains the username rather than userid(though you can argue that this is a bad design, the idea is that it's bad and inflexible to assume all controllers on a site share exactly the same format for their url string). It is difficult if not impossible to define one url interpreter method that converts each portion of the string to a variable.

                Of course one can have a slightly different format of MVC style url, like this one yoursite.com/page/action/edit/id/5/confirm/yes. With this it is possible to map 'edit' to 'action', '5' to 'id' and 'yes' to 'confirm' easily since they now follow a valid pattern for any possible controllers(pretty much like array's key value pair), but the url does not look as nice as the one mentioned earlier.

                For those who have rewritten your urls, what did you do to resolve this problem? I am sorry for writing this long, this issue is a bit difficult for me to explain but hopefully you get the idea what I am asking.

                  Using the CodeIgniter framework as an example, something like "www.example.com/foo/bar/this/that/the+other+thing" redirect to "www.example.com/index.php/foo/bar/this/that/the+other+thing". Index.php then parses that URL, and would attempt to load and call the controller class named "foo" and its (public) method named "bar", to which it would pass the remaining 3 args as parameters, in effect calling [FONT=Courier New]$foo->bar('this', 'that', 'the other thing')[/FONT].

                  At that point, those three parameters are available within that method based on whatever variable names were used in its parameter list.

                    umm... So in codeigniter every controller method must accept arguments corresponding to the url parameters on the query string? Sounds interesting, I am not quite sure about it but perhaps it's easier than defining url interpreter methods in all controller classes.

                      I'm taking a similar approach with my current project - Namespace/Class/Method/Args.

                      using [font=monospace]/foo/bar/this/that/the+other+thing[/font] as an example, the URI mapper would first check a list of registered URLs that map to specific pages/actions. If nothing is found, it would explode the URL (on [font=monospace] / [/font]), remove components that can't be classnames (in this case, the part with the [font=monospace]+[/font]'s; these are assumed to be args), and then look for existing (namespaced) classes:

                      • [font=monospace]\foo\bar\this\that[/font]?
                      • [font=monospace]\foo\bar\this[/font]?
                      • etc., until it finds one. If there's no match, it goes to a default controller.

                      say it found the class [font=monospace]\foo\bar[/font]. next, check if there is a public method [font=monospace]\foo\bar::this()[/font]:

                      • if so, do [font=monospace]$controller = new \foo\bar(); $controller->this( 'that','the+other+thing' );[/font]
                      • if not, do [font=monospace]$controller = new \foo\bar( 'this','that','the+other+thing' );[/font]

                      the advantage here is that any or all of the parameters are optional, as long as the n-c-m-a pattern is followed. Using namespaces allows URLs to be customized without having to change classnames. The controller methods themselves can do whatever they like, using some other method to decide what to do (GET, maybe), ignoring particular arguments if it likes, etc..
                      Or a user could skip it entirely and map desired URLs to whatever they like.

                        It should also be mentioned that mod_rewrite in htaccess can perform the same task, assigning query paramaters to preset $_GET variables
                        - that's what I use and my logic dictates that if there is only one variable it must be 'a', if two it must be 'b' and 'a' , and if three 'c', 'b' and 'a'
                        (assigment as required)
                        Also QSA in mod_rewrite will pass through traditional '?' query string parameters at the end, for those few cases where more input is required

                          traq;11015471 wrote:

                          I'm taking a similar approach with my current project - Namespace/Class/Method/Args.

                          using [font=monospace]/foo/bar/this/that/the+other+thing[/font] as an example, the URI mapper would first check a list of registered URLs that map to specific pages/actions. If nothing is found, it would explode the URL (on [font=monospace] / [/font]), remove components that can't be classnames (in this case, the part with the [font=monospace]+[/font]'s; these are assumed to be args), and then look for existing (namespaced) classes:

                          • [font=monospace]\foo\bar\this\that[/font]?
                          • [font=monospace]\foo\bar\this[/font]?
                          • etc., until it finds one. If there's no match, it goes to a default controller.

                          say it found the class [font=monospace]\foo\bar[/font]. next, check if there is a public method [font=monospace]\foo\bar::this()[/font]:

                          • if so, do [font=monospace]$controller = new \foo\bar(); $controller->this( 'that','the+other+thing' );[/font]
                          • if not, do [font=monospace]$controller = new \foo\bar( 'this','that','the+other+thing' );[/font]

                          the advantage here is that any or all of the parameters are optional, as long as the n-c-m-a pattern is followed. Using namespaces allows URLs to be customized without having to change classnames. The controller methods themselves can do whatever they like, using some other method to decide what to do (GET, maybe), ignoring particular arguments if it likes, etc..
                          Or a user could skip it entirely and map desired URLs to whatever they like.

                          I see, so it is indeed a common practice to have GET parameters as controller arguments. Thanks for mentioning, I think I will try this approach and see how it works. I am not quite sure if it is better to separate parameters in a URL by / or by +, guess it's a matter of preference or is there any particular reason behind this? I do not have namespace in my script yet, may consider adding it once I see the benefit of using namespace.

                          cretaceous wrote:

                          It should also be mentioned that mod_rewrite in htaccess can perform the same task, assigning query paramaters to preset $_GET variables
                          - that's what I use and my logic dictates that if there is only one variable it must be 'a', if two it must be 'b' and 'a' , and if three 'c', 'b' and 'a'
                          (assigment as required)
                          Also QSA in mod_rewrite will pass through traditional '?' query string parameters at the end, for those few cases where more input is required

                          I see, but is .htaccess able to work with variation in parameter names/keys? Let's say controller one has parameters 'id' and 'confirm', while controller two has parameter 'name'. How is .htaccess supposed to handle this?

                            Lord Yggdrasill;11015481 wrote:

                            I see, but is .htaccess able to work with variation in parameter names/keys? Let's say controller one has parameters 'id' and 'confirm', while controller two has parameter 'name'. How is .htaccess supposed to handle this?

                            htaccess can handle conditional scenarios though, yes, at that point it may be more flexible to handle from the PHP controller side

                              Yeah, possibly even before the controller: you may want to channel everything through one PHP file which handles the URL parsing, possibly not even looking at $_GET but at the full URL instead, which then invokes the desired controller and method. Therefore, it's only the sequence of the slash-delimited parameters that matter -- no naming of them is needed.

                                Lord Yggdrasill;11015481 wrote:

                                I see, so it is indeed a common practice to have GET parameters as controller arguments. Thanks for mentioning, I think I will try this approach and see how it works.

                                As with any HTTP request, GET parameters are appropriate when there is no change in server state (e.g., it would be appropriate for a search form, but not a registration form: use POST in the latter case).

                                Lord Yggdrasill;11015481 wrote:

                                I am not quite sure if it is better to separate parameters in a URL by / or by +, guess it's a matter of preference or is there any particular reason behind this?

                                It's still nice to keep your URLs organized and human-readable.

                                For example, I might do this:
                                [font=monospace]/home/products/computers/notebooks/15in,1TB,4gb[/font]
                                but not this:
                                [font=monospace]/home/products/computers,notebooks,15in,1TB,4gb[/font]
                                even though my search script (at /home/product) might treat "computers" and "notebooks" as arguments, the user would (rightly) think of them as categories: part of the hierarchy of the URL.

                                Lord Yggdrasill;11015481 wrote:

                                I do not have namespace in my script yet, may consider adding it once I see the benefit of using namespace.

                                I started using namespaces for other reasons (maintainability/ interchangeability/ extensibility, as well as easy autoloading), but I've found it very useful for URI mapping too.

                                  cretaceous;11015487 wrote:

                                  htaccess can handle conditional scenarios though, yes, at that point it may be more flexible to handle from the PHP controller side

                                  For the pedantic amongst us (and yes, I realize that Cretaceous here is repeating Lord Ygg's use of the term), .htaccess is just a configuration file and doesn't do squat; it's the apache module mod_rewrite that's actually doing the work. mod_rewrite can be called from several places in the Apache server, among those is the .htaccess file. 🙂

                                    dalecosp;11015789 wrote:

                                    For the pedantic amongst us (and yes, I realize that Cretaceous here is repeating Lord Ygg's use of the term), .htaccess is just a configuration file and doesn't do squat; it's the apache module mod_rewrite that's actually doing the work. mod_rewrite can be called from several places in the Apache server, among those is the .htaccess file. 🙂

                                    yes I'm a pedant too - tbh I think you have to be when dealing with code so you know you are discussing the same thing -
                                    but if you saw my earlier post in this thread I did specify mod_rewrite - I even realised I'd left it out of this one and thought "I should edit that" !
                                    (guilty as charged, your honour)

                                      7 days later

                                      Well I designed a URL parser class for my admin control panel, its just a primitive design atm.

                                      final class ACPUrlParser{
                                      	private $path;
                                      	private $url;
                                      
                                      public function __construct($url){
                                          if (!filter_var($url, FILTER_VALIDATE_URL, array(FILTER_FLAG_SCHEME_REQUIRED, FILTER_FLAG_HOST_REQUIRED))) {
                                              throw new UrlException('The specified URL is invalid.');
                                          }
                                      
                                          $acppath = "/admincp/";
                                          $this->path = SCRIPTPATH.$acppath;
                                          $this->url = str_replace($this->path, "", $url);
                                      }
                                      
                                      // parse the url and return an array of elements
                                      public function parse(){
                                          if(!$this->url) return array("page" => "index");
                                      
                                          $elements = array();	
                                          $values = explode("/", $this->url);
                                          $controller =  "ACP{$values[0]}";
                                      
                                          $elements['page'] = $values[0];
                                          $elements['action'] = $values[1];
                                          if(is_string($controller::$param)) $elements[$controller::$param] = $values[2];
                                          else{
                                              $index = 2;
                                              foreach($controller::$param as $param){
                                      	       $elements[$param] = $values[$index];
                                      	       $index++;
                                              }
                                          }		
                                          return $elements;
                                      }                
                                      } 
                                      

                                      The entire url is broken down into two parts: path and url. The url part has the format of controller(page)/action/param-1/param-2/.../param-n. The slash '/' symbol is used as delimiter to convert this string into an array. The first two elements of the array store controller and action values, while the rest contain information of the parameter values. The parameter keys are available from each controller's static field $class::$param. This field can be a string or an array, depending on whether my controller has only one possible parameter or multiple parameters. The url parser can be used to construct the $GET array, although in my case I have an input class/object that stores this information and everything inside $GET and $_POST are immutable.

                                      And I was wondering, what do you think about this url parser I created? Any comments, suggestions and criticism? What did you do for your own url parser?

                                        What value does [font=monospace]SCRIPTPATH[/font] contain? (I would expect, maybe, a filesystem path to the web root dir?)

                                        What value do you expect for the [font=monospace]$url[/font]?

                                        assuming [font=monospace]SCRIPTPATH[/font] is something like [font=monospace]/root/users/www[/font], and the [font=monospace]$url[/font] is something like [font=monospace]http://www.example.com/admincp/some/path[/font], I get [font=monospace]Fatal error: Class 'ACPhttp:' not found...[/font] - I have to assume that this will always fail, since you can't use a : in a class name.

                                        If I omit the schema ("http://"), I get a URLException.

                                        (Is [font=monospace]$controller::$param[/font] supposed to be [font=monospace]"$controller::$param"[/font]? I at least don't get a fatal error, that way.)

                                        What am I missing? Does this work as expected for you?

                                          Write a Reply...