Whether you're drawing customers into your restaurant for dinner, or friends over to your house for dessert, these tips will whet everyone's appetite.
Converting Absolute Paths to Relative Paths in PHP
Submitted by Guy Paddock on Mon, 09/19/2011 - 11:45
In PHP code, have you ever needed to convert an absolute path to a path that's relative to another path? If you look through the PHP function library, you'll find that there doesn't seem to be a function to do this.
Luckily, RedBottle is here to make your day! Here's an implementation of a utility function to convert absolute paths to relative paths, licensed under the GNU GPL v3:
<?php
/**
* @file
* <p>The <code>absolute_to_relative_path()</code> utility function.</p>
*
* <p>© 2011 RedBottle Design, LLC. All rights reserved.</p>
*
* <p>http://www.redbottledesign.com</p>
*
* <p>This source code is free software: you can redistribute it and/or modify
* it under the terms of the Lesser GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.</p>
*
* <p>This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Lesser GNU General Public License for more details.</p>
*
* <p>You should have received a copy of the Lesser GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.</p>
*
* @author Guy Paddock (guy.paddock@redbottledesign.com)
*/
/**
* Convert an absolute path to a path relative to another absolute path.
*
* @param string $from_path
* The starting absolute path.
*
* @param string $to_path
* The ending absolute path.
*
* @return string The relative path for navigating from
* <code>$from_path</code> to <code>$to_path</code>.
*
* @throws InvalidArgumentException
* If <code>$from_path</code> or <code>$to_path</code> are
* NULL, empty, or not absolute paths.
*/
function absolute_to_relative_path($from_path, $to_path) {
if (empty($to_path)) {
throw new InvalidArgumentException('$to_path must not be NULL or empty.');
}
if ($to_path[0] !== '/') {
throw new InvalidArgumentException('$to_path must be an absolute path.');
}
if (empty($from_path)) {
throw new InvalidArgumentException('$from_path must not be NULL or empty.');
}
if ($from_path[0] !== '/') {
throw new InvalidArgumentException('$from_path must be an absolute path.');
}
// Trim off trailing slashes for consistency, then turn paths into arrays
$to_path_parts = explode('/', rtrim($to_path, '/'));
$from_path_parts = explode('/', rtrim($from_path, '/'));
$common_part_count = 0;
/* Count how many parts the two paths have in common, since those parts
* aren't included in the relative path.
*/
for ($i = 0; $i < max(sizeof($to_path_parts), sizeof($from_path_parts)); ++$i) {
if (isset($to_path_parts[$i]) && isset($from_path_parts[$i])) {
if ($to_path_parts[$i] == $from_path_parts[$i]) {
++$common_part_count;
}
else {
break;
}
}
else {
break;
}
}
$relative_parts = array();
/* Each part of the "from path" that remains after the common parts has to
* be replaced with ".." to get back to the common root for both paths.
*/
if (sizeof($from_path_parts) > $common_part_count) {
$replacement_count = sizeof($from_path_parts) - $common_part_count;
$relative_parts = array_fill(0, $replacement_count, '..');
}
/*
* Each part of the "to path" that remains after the common parts is merely
* appended to the relative path.
*/
if (sizeof($to_path_parts) > $common_part_count) {
$remaining_to_path_parts = array_slice($to_path_parts, $common_part_count);
$relative_parts = array_merge($relative_parts, $remaining_to_path_parts);
}
// Turn array back into path string
return implode('/', $relative_parts);
}
?>
Here's a simple set of test cases that demonstrate the function:
<?php
$paths = array(
array(
'/path/a/b/c',
'/path/d/e',
'../../../d/e'
),
array(
'/path/d/e',
'/path/a/b/c',
'../../a/b/c'
),
array(
'/a/b/c',
'/',
'../../..'
),
array(
'/',
'/a/b/c',
'a/b/c',
),
array(
'/a/b/c',
'/a/b/c/d/e',
'd/e'
),
);
foreach ($paths as $path_set) {
$from_path = $path_set[0];
$to_path = $path_set[1];
$expected_result = $path_set[2];
$result = absolute_to_relative_path($from_path, $to_path);
print "From path: $from_path\n";
print "To path: $to_path\n";
print "Result: " . $result . "\n";
print "Test result: " . (($result == $expected_result) ? 'PASS' : 'FAIL') . "\n\n";
}
?>
RBD News
New RedBottle Website
06.16.2011
ROCHESTER, NY - Red Bottle Design, LLC has launched its new corporate website running on Drupal 7.
Latest Blog Posts
- 1 of 14
- ››
Social Media
- RedBottleDesign W'hoo! Love the new RedBottle Design Office. t.co/LWvEcn1R
- RedBottleDesign t.co/FNwqApQi t.co/FapBkC21
- RedBottleDesign We have a great feeling about 2012... stay tuned!
- RedBottleDesign RedBottle Design wishes everyone a safe and happy Holiday Season.
- RedBottleDesign New blog entry: Java-inspired Enumerated Types in PHP - t.co/Mzix0Vh0
