Mods: Automatic Base Detection

Aus CodeCoupler Wiki
Zur Navigation springen Zur Suche springen

Summary

Sometimes it is difficult to move an application from one subfolder into another or into the root folder. Another problem is moving your applcation to another domain. It would be much simpler is the application use only relative url's and all the other stuff would be done automatically.

In the most cases there are at least two points in your application you must always have to remember to modify if you move your application around. If you are using redirections with mod_rewrite you have to modify at least the RewriteBase if you move them from one subfolder into another. And the most frameworks need extra configuration and special code to generate relative Url's. With CodeIgniter for example you have functions like base_url() or site_url() which should helps you to built links to ressources your application without to know about your current place. But this not very handy as you have always remember to use these functions in every link and to setup correctly your configuration value in $config['base_url']. Furthermore these functions produce absolute URLs, which is not necessary imo:

Example for HTML:

<a href="<?php echo base_url();?>controller/method/parameter">...</a>

Example for JSON-Objects:

{
   url: "<?php echo base_url();?>controller/method/parameter"
}


So why not using only relative URLs?

CodeCoupler includes a htaccess file that detects and save the current base folder in a server variable and redirects everything into the index.php. Now you can set the base in your html page and use only relative URLs:

<base href="<?= (isset($_SERVER['BASE'])?$_SERVER['BASE']:$_SERVER['REDIRECT_BASE']) ?>">

If you are using the template html it will be set in every page automatically.

From now you do not have to bother how to point to ressources anymore or use the index.php. Just start everytime with the name of controller:

Example for HTML:

<a href="controller/method/parameter">...</a>

Example for JSON-Objects:

{
   url: "controller/method/parameter"
}

Remarks:

If you are running PHP in CGI mode then apache will prefix your environment variables with REDIRECT_. So we have to check first if the index $_SERVER['BASE'] ist set. If not we should use the index $_SERVER['REDIRECT_BASE'].

Some Notes

If you nevertheless should really need the function base_url() of CodeIgniter here a note to the base_url variable in config.php:

This variable should always be empty to let CodeIgniter automatically detect the protocol the hostname and the subdirectory in functions like base_url(). In some cases you have to set this variable and then you have another place to remind if you move your application around. With CodeCoupler you can set this variable in a way that moving the application at least to another folder do not break your links:

$config['base_url'] = 'http://YOUR_FIXED_DOMAIN/'.(is_cli()?'':ltrim($_SERVER['BASE'],'/'));

How this works

Every line of the htaccess file explained:

RewriteCond %{ENV:URI} ^$
RewriteRule ^(.*)$ - [ENV=URI:$1]

The first line looks if the variable URI is empty. If yes, the second line stores the path from the location of the htaccess file to the requested file into the variable URI.

  • Example Request: http://host/subdir/request-dir/request-file?var=val
  • If this htaccess is placed in subdir the stored value will be: request-dir/request-file
RewriteCond %{ENV:BASE} ^$
RewriteCond %{ENV:URI}::%{REQUEST_URI} ^(.*)::(.*?)\1$
RewriteRule ^ - [ENV=BASE:%2]

The first line looks if the variable BASE is empty. The condition of the second line is always true. The only point of this line is saving the some values in two groups. It works as follows:

Remember:

  • Our example Request: http://host/subdir/request-dir/request-file?var=val
  • The variable URI have the value because of the rule above: request-dir/request-file

Now the condition is:

Test-String: request-dir/request-file::/subdir/request-dir/request-file
Condition  : (        group 1       )::(group2)request-dir/request-file
                                               ^- This is the        -^
                                               ^- Backreference \1   -^
                                               ^- to the value of    -^
                                               ^- "group 1"          -^

Now we have in group 2 the base that we need. The third line save this value into the variable BASE. And we are ready for our final rewrite:

RewriteCond $1 !^index\.php
RewriteRule ^(.*)$ %{ENV:BASE}index.php [L,QSA]

If you need to exclude some requests redirecting to index.php you can add them in the rewrite condition like here:

RewriteCond $1 !^(index\.php|assets)