PHP site root

How to get the root of your site, regardless of the folder depth of your script while taking into account any Aliases your webserver might have?

Say, for example, that you have in your apache conf the following lines:

  DocumentRoot /var/www/htdocs
  Alias /phpsite /var/www/mysite

That means that your PHP site resides in /var/www/mysite, while rest of your web resides in /var/www/htdocs. How will your PHP scripts know that /phpsite portion, without hardcoding this into scripts, when they do not know how many levels deep in directory structure they themselves are in your site (e.g /phpsite/posts/update.php).

First, if you already don’t have, create a script (call it what ever you like, e.g. config.php) somewhere in your site folder. Preferred is at the top level, but subfolders work too (more on this later).

Secondly, put the following inside that file:

$wwwroot = "http://" . $_SERVER['SERVER_NAME'] .
      str_replace(
        str_replace(
          dirname(__FILE__),
          "",
          $_SERVER['SCRIPT_FILENAME']),
        "",
        $_SERVER['SCRIPT_NAME']);

If you placed your config.php in some subfolder, then you have to multiply the dirname() calls for every subfolder level. E.g if your config.php is in conf/config.php, i.e second level, you need 2 dirname() calls and your 4th line should look like:

dirname(dirname(__FILE__))

Third, include this file in every script, even in subfolders and prepend to links:

require_once "../config.php";
echo "Some script";

Voila!

Under the hood

What this script does is actually rather simple string algebra. The contents of those special variable is as follows:

$_SERVER['SERVER_NAME']
    # => example.com
__FILE__
    # => /var/www/mysite/config.php - the name of the script where this is written
$_SERVER['SCRIPT_FILENAME']
    # => /var/www/mysite/dir/script.php - the full path to script that included config.php
$_SERVER['SCRIPT_NAME']
    # => /phpsite/dir/script.php - the URL path of the script that included config.php

You might already start to grasp what we’re about to do. Leaving aside the obvious hostname part, what the str_replace part does is the following:

  1. calculate filesystem path to the base of the site: dirname(__FILE__): /var/www/mysite/config.php => /var/www/mysite
  2. substract this path from the SCRIPT_FILENAME => /var/www/mysite/dir/script.php => /dir/script.php
  3. substract the result from the URL SCRIPT_NAME => /phpsite/dir/script.php => /phpsite

This method works even if you change the Alias or remove it altogether.

Generic vim counters

I needed a way in vim config to use counters and what better way, but to write a function to simultaneously handle all variables and optinally increase or decrease them:

" define and manage counters
" NB! all counters are namespaced globally (g:)
function! Counter(name,...)
" check if this variable already exists or should we initialise it
  if !exists("g:" . a:name)
    exec 'let g:'  . a:name .' = 0'
  endif
" if second parameter is given, increase/decrease value
  if a:0 > 0
    exec 'let g:'. a:name .' = g:' . a:name . ' + ' . a:1
  endif
  exec 'return g:' . a:name
endfunction

Usage of the function is as follows:

" Get the current value
echo Counter('mycount')

" Increase value by 1(and return the new value)
echo Counter('mycount', 1)

" Decrease value by 2
echo Counter('mycount', -2)