Apache Zeta Components - high quality PHP components

eZ Components - Url

Introduction

The Url component provides basic operations to handle urls (including parse, build, get/set path parameters, get/set query and create formatted urls).

Class overview

ezcUrl
This is the main class of this component. It contains methods for url parsing, url building, get/set parameters and get/set query.
ezcUrlConfiguration
This class allows the definition of url configurations (including basedir, script, ordered parameters, unordered parameters and delimiters for unordered parameter names).
ezcUrlCreator
This class allows you to register a url under an alias. You can then use that alias to generate another url suffixed with a value, or to create urls formatted using the syntax of the PHP function sprintf().
ezcUrlTools
This utility class contains useful functions for handling urls, like getCurrentUrl() which builds the current url from the $_SERVER array or another array source, and parseQueryString() which has the same functionality as the PHP function parse_str(), but without converting the dots to underscores in query parameter names.

Notes

Working with path, params and query parts

Do not work with the path, params and query properties directly, because this will not work in PHP 5.2.0 (that is, do not set/get $url->query[0], because a notice will be thrown: "Notice: Indirect modification of overloaded property ezcUrl::$query has no effect"). Instead, use the following methods.

Using url configurations

By using the ezcUrlConfiguration class, you can specify a custom configuration that can be used to parse urls. The properties you can set in objects of this class are the default base directory, default script name (eg. index.php) (which will be hidden when building the url by default, but can be displayed by calling buildUrl( true )), delimiters for unordered parameter names and names for accepted parameters.

A URL is assumed to be of this form:

scheme://host/basedir/script/ordered_parameters/unordered_parameters

Example:

http://example.com/mydir/index.php/groups/Games/Adventure/Adult/(game)/Larry/7

Where:

scheme = "http" host = "example.com" basedir = "mydir" script = "index.php" ordered parameters = "groups", "Games", "Adventure", "Adult" unordered parameters = array( "Larry", "7" )

When creating a configuration with ordered parameters, those parameters are required to be present in the parsed URL, in the same number as the configuration states. Having a different number of ordered parameters in the parsed URL will lead to wrong values assigned to the unordered parameters (if any follow the ordered parameters).

Working with a variable number of ordered parameters is explained in the Changing a url configuration dynamically section.

Working with the query part

Getting the query part

Here is an example of getting the query part of urls:

  1. <?php
  2. require_once 'tutorial_autoload.php';
  3. // create a new Url object from a string url
  4. $url = new ezcUrl'http://www.example.com/mydir/index.php/content/view/article/42/mode/print?user[name]=Bob+Smith&user[age]=47&user[sex]=M' );
  5. // get the query parts
  6. var_dump$url->getQuery() );
  7. ?>

The output would be:

array(1) { ["user"]=> array(3) { ["name"]=> string(9) "Bob Smith" ["age"]=> string(2) "47" ["sex"]=> string(1) "M" } }

Setting the query part

Here is an example of setting the query part of urls:

  1. <?php
  2. require_once 'tutorial_autoload.php';
  3. // create a new Url object from a string url
  4. $url = new ezcUrl'http://www.example.com/mydir/index.php/content/view/article/42/mode/print?user[name]=Bob+Smith&user[age]=47&user[sex]=M' );
  5. // create an array which will be used to set the query part
  6. $query = array( 'user' => array( 'name' => 'Bob Smith',
  7.                                  'age'  => '47',
  8.                                  'sex'  => 'M',
  9.                                  'dob'  => '5/12/1956'),
  10.               );
  11. // set the query part of the Url object
  12. $url->setQuery$query );
  13. var_dumprawurldecode$url ) );
  14. // add a query parameter to the query part
  15. $url->setQueryarray_merge$url->getQuery(), array( 'sort' => 'desc' ) ) );
  16. var_dumprawurldecode$url ) );
  17. // remove a query parameter from the query part
  18. $url->setQueryarray_diff_key$url->getQuery(), array( 'sort' => null ) ) );
  19. var_dumprawurldecode$url ) );
  20. ?>

The output would be as follows (wrapped for clarity):

string(139) "http://www.example.com/mydir/index.php/content/view/article/ 42/mode/print?user[name]=Bob+Smith&user[age]=47&user[sex]=M&user[dob]= 5/12/1956" string(149) "http://www.example.com/mydir/index.php/content/view/article/ 42/mode/print?user[name]=Bob+Smith&user[age]=47&user[sex]=M&user[dob]= 5/12/1956&sort=desc" string(139) "http://www.example.com/mydir/index.php/content/view/article/ 42/mode/print?user[name]=Bob+Smith&user[age]=47&user[sex]=M&user[dob]= 5/12/1956"

Working with url configurations

Creating and using a custom url configuration

The following example creates a custom url configuration and uses it when creating a new url object:

  1. <?php
  2. require_once 'tutorial_autoload.php';
  3. // create an ezcUrlConfiguration object
  4. $urlCfg = new ezcUrlConfiguration();
  5. // set the basedir and script values
  6. $urlCfg->basedir 'mydir';
  7. $urlCfg->script 'index.php';
  8. // define delimiters for unordered parameter names
  9. $urlCfg->unorderedDelimiters = array( '('')' );
  10. // define ordered parameters
  11. $urlCfg->addOrderedParameter'section' );
  12. $urlCfg->addOrderedParameter'group' );
  13. $urlCfg->addOrderedParameter'category' );
  14. $urlCfg->addOrderedParameter'subcategory' );
  15. // define unordered parameters
  16. $urlCfg->addUnorderedParameter'game' );
  17. // visualize the $urlCfg object
  18. var_dump$urlCfg );
  19. // create a new ezcUrl object from a string url and use the above $urlCfg
  20. $url = new ezcUrl'http://www.example.com/mydir/index.php/groups/Games/Adventure/Adult/(game)/Larry/7'$urlCfg );
  21. ?>

The output would be:

object(ezcUrlConfiguration)#1 (1) { ["properties:private"]=> array(5) { ["basedir"]=> string(5) "mydir" ["script"]=> string(9) "index.php" ["unorderedDelimiters"]=> array(2) { [0]=> string(1) "(" [1]=> string(1) ")" } ["orderedParameters"]=> array(4) { ["section"]=> int(0) ["group"]=> int(1) ["category"]=> int(2) ["subcategory"]=> int(3) } ["unorderedParameters"]=> array(1) { ["game"]=> int(0) } } }

Lazy initialization

Lazy initialization is a mechanism to load and configure a component, only when it is really used in your application. This mechanism saves time for parsing the classes and configuration, when the component is not used at all during one request. You can find a description how you can use it for your own components and how it works in the ezcBase tutorial. The keyword for the url component is ezcUrlConfiguration.

  1. <?php
  2. require_once 'tutorial_autoload.php';
  3. class customLazyUrlConfiguration implements ezcBaseConfigurationInitializer
  4. {
  5.     public static function configureObject$urlCfg )
  6.     {
  7.         // set the basedir and script values
  8.         $urlCfg->basedir 'mydir';
  9.         $urlCfg->script 'index.php';
  10.         // define delimiters for unordered parameter names
  11.         $urlCfg->unorderedDelimiters = array( '('')' );
  12.         // define ordered parameters
  13.         $urlCfg->addOrderedParameter'section' );
  14.         $urlCfg->addOrderedParameter'group' );
  15.         $urlCfg->addOrderedParameter'category' );
  16.         $urlCfg->addOrderedParameter'subcategory' );
  17.         // define unordered parameters
  18.         $urlCfg->addUnorderedParameter'game' );
  19.     }
  20. }
  21. ezcBaseInit::setCallback
  22.     'ezcUrlConfiguration'
  23.     'customLazyUrlConfiguration'
  24. );
  25. // Classes loaded and configured on first request
  26. $url = new ezcUrl
  27.     'http://www.example.com/mydir/index.php/groups/Games/Adventure/Adult/(game)/Larry/7',
  28.     ezcUrlConfiguration::getInstance()
  29. );
  30. ?>

This examples configures the URL component exactly like the example before. The main difference is, that we roll out the configuration to an own class, and define a callback using ezcBaseInit::setCallback to this class, which will be called with a url configuration instance as the first parameter on the first call on ezcUrlConfiguration::getInstance().

ezcBaseInit::setCallback accepts as a first parameter a component specific key, which lets the component later request the right configuration callback. The second parameter is the name of the class to perform the static callback on. This class must implement the ezcBaseConfigurationInitializer class. Each component's lazy initialization calls the static method configureObject() on the referenced class.

When the URL is really parsed in your application, like shown in line 35 of the example, a new ezcUrlConfiguration is instatiated an automatically configured by the configureObject() method.

Working with parameters

Getting parameters using a url configuration

The following example uses the custom url configuration from before to get the parameters from the provided url:

  1. <?php
  2. require_once 'tutorial_autoload.php';
  3. // create an ezcUrlConfiguration object
  4. $urlCfg = new ezcUrlConfiguration();
  5. // set the basedir and script values
  6. $urlCfg->basedir 'mydir';
  7. $urlCfg->script 'index.php';
  8. // define delimiters for unordered parameter names
  9. $urlCfg->unorderedDelimiters = array( '('')' );
  10. // define ordered parameters
  11. $urlCfg->addOrderedParameter'section' );
  12. $urlCfg->addOrderedParameter'group' );
  13. $urlCfg->addOrderedParameter'category' );
  14. $urlCfg->addOrderedParameter'subcategory' );
  15. // define unordered parameters
  16. $urlCfg->addUnorderedParameter'game'ezcUrlConfiguration::MULTIPLE_ARGUMENTS );
  17. // create a new ezcUrl object from a string url and use the above $urlCfg
  18. $url = new ezcUrl'http://www.example.com/mydir/index.php/groups/Games/Adventure/Adult/(game)/Larry/7'$urlCfg );
  19. // get the parameter values from the url
  20. var_dump$url->getParam'section' ) );
  21. var_dump$url->getParam'group' ) );
  22. var_dump$url->getParam'category' ) );
  23. var_dump$url->getParam'subcategory' ) );
  24. var_dump$url->getParam'game' ) );
  25. // output the url (index.php will not be there)
  26. var_dump$url->buildUrl() );
  27. // output the url (with index.php included)
  28. var_dump$url->buildUrltrue ) );
  29. ?>

The output would be as follows (wrapped for clarity):

string(6) "groups" string(5) "Games" string(9) "Adventure" string(5) "Adult" array(2) { [0]=> string(5) "Larry" [1]=> string(1) "7" } string(72) "http://www.example.com/mydir/groups/Games/Adventure/Adult/ (game)/Larry/7" string(82) "http://www.example.com/mydir/index.php/groups/Games/Adventure/ Adult/(game)/Larry/7"

Getting parameters by aggregating values for unordered parameters

If the URL contains multiple appearances of an unordered parameter (for example 'http://www.example.com/(param1)/x/(param1)/y/z'), then by default only the last encountered values are returned when calling getParam().

To return all the values (to aggregate values) as an array of arrays (for example, array( array( 'x' ), array( 'y', 'z' ) ) for the above URL), use ezcUrlConfiguration::AGGREGATE_ARGUMENTS as the second parameter when calling addUnorderedParameter(), like in this example:

  1. <?php
  2. require_once 'tutorial_autoload.php';
  3. // create an ezcUrlConfiguration object
  4. $urlCfg = new ezcUrlConfiguration();
  5. // single parameter value
  6. $urlCfg->addUnorderedParameter'param1' );
  7. $url = new ezcUrl'http://www.example.com/(param1)/x/(param1)/y/z'$urlCfg );
  8. var_dump$url->getParam'param1' ) ); // will output "y"
  9. // multiple parameter values
  10. $urlCfg->addUnorderedParameter'param1'ezcUrlConfiguration::MULTIPLE_ARGUMENTS );
  11. $url = new ezcUrl'http://www.example.com/(param1)/x/(param1)/y/z'$urlCfg );
  12. var_dump$url->getParam'param1' ) ); // will output array( "y", "z" )
  13. // multiple parameter values with aggregation
  14. $urlCfg->addUnorderedParameter'param1'ezcUrlConfiguration::AGGREGATE_ARGUMENTS );
  15. $url = new ezcUrl'http://www.example.com/(param1)/x/(param1)/y/z'$urlCfg );
  16. var_dump$url->getParam'param1' ) ); // will output array( array( "x" ), array( "y", "z" ) )
  17. // output the url (it will be similar to the input url)
  18. var_dump$url->buildUrl() );
  19. ?>

The output will be:

string(1) "y" array(2) { [0]=> string(1) "y" [1]=> string(1) "z" } array(2) { [0]=> array(1) { [0]=> string(1) "x" } [1]=> array(2) { [0]=> string(1) "y" [1]=> string(1) "z" } } string(46) "http://www.example.com/(param1)/x/(param1)/y/z"

Getting unordered parameters without name delimiters

If the URL doesn't contain delimiters for unordered parameter names, then you can use the getParams() method to return the values after the basedir, script and ordered parameters as a flat array. This array can be parsed later by your application to make it an associative array.

Example:

  1. <?php
  2. require_once 'tutorial_autoload.php';
  3. // create an ezcUrlConfiguration object
  4. $urlCfg = new ezcUrlConfiguration();
  5. $urlCfg->basedir '/mydir/shop';
  6. $urlCfg->script 'index.php';
  7. $urlCfg->addOrderedParameter'module' );
  8. $url = new ezcUrl'http://www.example.com/mydir/shop/index.php/order/Software/PHP/Version/5.2/Extension/XDebug/Extension/openssl'$urlCfg );
  9. // get the unordered parameters as a flat array
  10. var_dump$url->getParams() ); // will output array( 'Software', 'PHP', 'Version', '5.2', 'Extension', 'XDebug', 'Extension', 'openssl' )
  11. ?>

The output will be:

array(8) { [0]=> string(8) "Software" [1]=> string(3) "PHP" [2]=> string(7) "Version" [3]=> string(3) "5.2" [4]=> string(9) "Extension" [5]=> string(6) "XDebug" [6]=> string(9) "Extension" [7]=> string(7) "openssl" }

This array can then be translated by your application to this form (if needed):

array( "Software" => array( "PHP" ), "Version" => array( "5.2" ), "Extension" => array( "XDebug", "openssl" ) );

Setting parameters using a url configuration

The following example uses the custom url configuration from before to set the parameters into the provided url:

  1. <?php
  2. require_once 'tutorial_autoload.php';
  3. // create an ezcUrlConfiguration object
  4. $urlCfg = new ezcUrlConfiguration();
  5. // set the basedir and script values
  6. $urlCfg->basedir 'mydir';
  7. $urlCfg->script 'index.php';
  8. // define delimiters for unordered parameter names
  9. $urlCfg->unorderedDelimiters = array( '('')' );
  10. // define ordered parameters
  11. $urlCfg->addOrderedParameter'section' );
  12. $urlCfg->addOrderedParameter'group' );
  13. $urlCfg->addOrderedParameter'category' );
  14. $urlCfg->addOrderedParameter'subcategory' );
  15. // define unordered parameters
  16. $urlCfg->addUnorderedParameter'game'ezcUrlConfiguration::MULTIPLE_ARGUMENTS );
  17. $urlCfg->addUnorderedParameter'patches'ezcUrlConfiguration::AGGREGATE_ARGUMENTS );
  18. // create a new ezcUrl object from a string url and use the above $urlCfg
  19. $url = new ezcUrl'http://www.example.com/mydir/index.php/groups/Games/Adventure/Adult/(game)/Larry/7'$urlCfg );
  20. var_dump$url->buildUrl() );
  21. // set the parameter values in the url
  22. $url->setParam'subcategory''Kids' );
  23. $url->setParam'game', array( 'Monkey_Island''3' ) );
  24. var_dump$url->buildUrl() );
  25. $url->setParam'patches', array( array( 'beta1' ), array( 'rc1''rc2' ) ) );
  26. var_dump$url->buildUrl() );
  27. ?>

The output would be as follows (wrapped for clarity):

string(72) "http://www.example.com/mydir/groups/Games/Adventure/Adult/ (game)/Larry/7" string(79) "http://www.example.com/mydir/groups/Games/Adventure/Kids/ (game)/Monkey_Island/3" string(113) "http://www.example.com/mydir/groups/Games/Adventure/Kids/ (game)/Monkey_Island/3/(patches)/beta1/(patches)/rc1/rc2"

Changing a url configuration dynamically

The following example uses the custom url configuration from before to set the parameters into the provided url:

  1. <?php
  2. require_once 'tutorial_autoload.php';
  3. // create a default url configuration
  4. $urlCfgDefault = new ezcUrlConfiguration();
  5. $urlCfgDefault->addOrderedParameter'section' );
  6. // create a configuration for artists
  7. $urlCfgArtist = new ezcUrlConfiguration();
  8. $urlCfgArtist->addOrderedParameter'section' );
  9. $urlCfgArtist->addOrderedParameter'artist_name' );
  10. // create a configuration for albums
  11. $urlCfgAlbum = new ezcUrlConfiguration();
  12. $urlCfgAlbum->addOrderedParameter'section' );
  13. $urlCfgAlbum->addOrderedParameter'artist_name' );
  14. $urlCfgAlbum->addOrderedParameter'album_name' );
  15. // create a configuration for music genres
  16. $urlCfgGenre = new ezcUrlConfiguration();
  17. $urlCfgGenre->addOrderedParameter'section' );
  18. $urlCfgGenre->addOrderedParameter'genre_name' );
  19. $url = new ezcUrl'http://mymusicsite.com/showartist/Beatles'$urlCfgDefault );
  20. switch ( $url->getParam'section' ) )
  21. {
  22.         case 'showartist':
  23.                 $url->applyConfiguration$urlCfgArtist );
  24.                 $artist $url->getParam'artist_name' );
  25.         // do stuff with $artist
  26.         var_dump$artist );
  27.                 break;
  28.         case 'showalbum':
  29.                 $url->applyConfiguration$urlCfgAlbum );
  30.                 $artist $url->getParam'artist_name' );
  31.                 $album $url->getParam'album_name' );
  32.         // do stuff with $artist and $album
  33.         var_dump$artist );
  34.         var_dump$album );
  35.         break;
  36.     case 'showgenre':
  37.                 $url->applyConfiguration$urlCfgGenre );
  38.                 $genre $url->getParam'genre_name' );
  39.         // do stuff with $genre
  40.         var_dump$genre );
  41.         break;
  42. }
  43. ?>

The output would be:

string(7) "Beatles"

Using the url creator

Appending a suffix to a url

With the url creator, you can register a url under an alias, then use that alias when you want to prepend the url to a file name.

  1. <?php
  2. require_once 'tutorial_autoload.php';
  3. // register an url under the alias 'map'
  4. ezcUrlCreator::registerUrl'map''/images/geo?xsize=450&ysize=450&zoom=4' );
  5. // display the the url prepended to map_norway.gif
  6. var_dumpezcUrlCreator::prependUrl'map''map_norway.gif' ) );
  7. // display the the url prepended to map_sweden.gif
  8. var_dumpezcUrlCreator::prependUrl'map''map_sweden.gif' ) );
  9. // display the stored url under the alias 'map'
  10. var_dumpezcUrlCreator::getUrl'map' ) );
  11. ?>

The output would be:

string(53) "/images/geo/map_norway.gif?xsize=450&ysize=450&zoom=4" string(53) "/images/geo/map_sweden.gif?xsize=450&ysize=450&zoom=4" string(38) "/images/geo?xsize=450&ysize=450&zoom=4"

Using formatting for a url

With the url creator, you can register a url under an alias, then use that alias when you want to apply formatting to a url.

  1. <?php
  2. require_once 'tutorial_autoload.php';
  3. // register an url under the alias 'map'
  4. ezcUrlCreator::registerUrl'map''/images/geo/%s?xsize=%d&ysize=%d&zoom=%d' );
  5. // display the stored url under the alias 'map' formatted with parameters
  6. var_dumpezcUrlCreator::getUrl'map''map_norway.gif'450450) );
  7. // display the stored url under the alias 'map' formatted with other parameters
  8. var_dumpezcUrlCreator::getUrl'map''map_sweden.gif'450450) );
  9. ?>

The output would be:

string(53) "/images/geo/map_norway.gif?xsize=450&ysize=450&zoom=4" string(53) "/images/geo/map_sweden.gif?xsize=450&ysize=450&zoom=4"

Other url functions

In the class ezcUrlTools there are some useful functions for handling urls.

getCurrentUrl

This function builds the current url from the $_SERVER array or another array source. The $_SERVER array is used by default, but another array source can be specified as a parameter when calling the function.

For example, if the $_SERVER array has these fields:

  1. <?php
  2. $_SERVER = array(
  3.     'HTTPS' => '1',
  4.     'SERVER_NAME' => 'www.example.com',
  5.     'SERVER_PORT' => 80,
  6.     'REQUEST_URI' => '/index.php'
  7.     );
  8. $url ezcUrlTools::getCurrentUrl();
  9. ?>

Then $url will be:

https://www.example.com/index.php

parseQueryString

This function has the same functionality as the PHP function parse_str(), but without converting the dots to underscores in query parameter names.

Example:

  1. <?php
  2. $params ezcUrlTools::parseQueryString(
  3.     'openid.nonce=123456&foo[]=bar&foo[]=baz' );
  4. ?>

Then $params will be:

array(2) { ["openid.nonce"]=> string(6) "123456" ["foo"]=> array(2) { [0]=> string(3) "bar" [1]=> string(3) "baz" } }

By calling parse_str() on the same string, instead of 'openid.nonce' as a key in $params there would have been 'openid_nonce'.