I have the following code that (1) gets the page / section name from the url (2) cleans up the string and then assigns it to a variable.
I was wondering if there are any suggestions to how I can improve this code to be more efficient, possibly less if / else statements.
Also, any suggestion how I can code this so that it accounts for x amount of sub-directories in the url structure. Right now I check up to 3 in a pretty manual way.
I'd like it to handle any url, for example: www.domain.com/level1/level2/level3/level4/levelx/...
Here is my current code:
<?php
$prefixName = 'www : ';
$getPageName = explode("/", $_SERVER['PHP_SELF']);
$cleanUpArray = array("-", ".php");
for($i = 0; $i < sizeof($getPageName); $i++) {
if ($getPageName[1] == 'index.php')
{
$pageName = $prefixName . 'homepage';
}
else
{
if ($getPageName[1] != 'index.php')
{
$pageName = $prefixName . trim(str_replace($cleanUpArray, ' ', $getPageName[1]));
}
if (isset($getPageName[2]))
{
if ( $getPageName[2] == 'index.php' )
{
$pageName = $prefixName . trim(str_replace($cleanUpArray, ' ', $getPageName[1]));
}
else
{
$pageName = $prefixName . trim(str_replace($cleanUpArray, ' ', $getPageName[2]));
}
}
if (isset($getPageName[3]) )
{
if ( $getPageName[3] == 'index.php' )
{
$pageName = $prefixName . trim(str_replace($cleanUpArray, ' ', $getPageName[2]));
}
else
{
$pageName = $prefixName . trim(str_replace($cleanUpArray, ' ', $getPageName[3]));
}
}
}
}
?>
You are currently using a for-loop, but not using the $i iterator for anything - so to me, you could drop the loop entirely. From what I can see, you just want the directory-name prior to the file to be the $pageName and if there is no prior directory set it as homepage.
You can pass $_SERVER['PHP_SELF'] to basename() to get the exact file-name instead of checking the indexes, and also split on the / as you're currently doing to get the "last directory". To get the last directory, you can skip indexes and directly use array_pop().
<?php
$prefixName = 'www : ';
$cleanUpArray = array("-", ".php");
$script = basename($_SERVER['PHP_SELF']);
$exploded = explode('/', substr($_SERVER['PHP_SELF'], 0, strrpos($_SERVER['PHP_SELF'], '/')));
$count = count($exploded);
if (($count == 1) && ($script == 'index.php')) {
// the current page is "/index.php"
$pageName = $prefixName . 'homepage';
} else if ($count > 1) {
// we are in a sub-directory; use the last directory as the current page
$pageName = $prefixName . trim(str_replace($cleanUpArray, ' ', array_pop($exploded)));
} else {
// there is no sub-directory and the script is not index.php?
}
?>
In the event that you want a more breadcumbs-feel, you may want to keep each individual directory. If this is the case, you can update the middle if else condition to be:
} else if ($count > 1) {
// we are in a sub-directory; "breadcrumb" them all together
$pageName = '';
$separator = ' : ';
foreach ($exploded as $page) {
if ($page == '') continue;
$pageName .= (($pageName != '') ? $separator : '') . trim(str_replace($cleanUpArray, ' ', $page));
}
$pageName = $prefixName . $pageName;
} else {
I found this code very helpful
$protocol = strpos(strtolower($_SERVER['SERVER_PROTOCOL']),'https') ===
FALSE ? 'http' : 'https'; // Get protocol HTTP/HTTPS
$host = $_SERVER['HTTP_HOST']; // Get www.domain.com
$script = $_SERVER['SCRIPT_NAME']; // Get folder/file.php
$params = $_SERVER['QUERY_STRING'];// Get Parameters occupation=odesk&name=ashik
$currentUrl = $protocol . '://' . $host . $script . '?' . $params; // Adding all
echo $currentUrl;
Related
I have a simple strange problem but I can not find a function to do this after many search.
I have an URL like http://example.com/folder/folder2/../image/test.jpg and I would like a function which return the correct absolute link:
http://example.com/folder/image/test.jpg
A function with only one param, the url (and not base dir or relative dir like in examples I found)
If you can help me, thanks.
Perhaps a starting point:
<?php
function unrelatify($url)
{
$parts = parse_url($url);
$path = $parts['path'] ?? '';
$hierarchy = explode('/', $path);
while(($key = array_search('..', $hierarchy)) !== false) {
if($key-1 > 0)
unset($hierarchy[$key-1]);
unset($hierarchy[$key]);
$hierarchy = array_values($hierarchy);
}
$new_path = implode('/', $hierarchy);
return str_replace($path, $new_path, $url);
}
echo unrelatify('http://example.com/../folder/../folder2/../image/test.jpg#foo?bar=baz');
Output:
http://example.com/image/test.jpg#foo?bar=baz
You may want to see how browsers and other web clients de-relativify (urls).
thanks to everyone for your answers.
here are a recap and some other ways i've tested
<?php
function unrelatify($url) {
$parts = parse_url($url);
$path = $parts['path'];
$hierarchy = explode('/', $path);
while (($key = array_search('..', $hierarchy)) !== false) {
if ($key - 1 > 0)
unset($hierarchy[$key - 1]);
unset($hierarchy[$key]);
$hierarchy = array_values($hierarchy);
}
$new_path = implode('/', $hierarchy);
return str_replace($path, $new_path, $url);
}
function normalizePath($path) {
do {
$path = preg_replace(
array('#//|/\./#', '#/([^/.]+)/\.\./#'), '/', $path, -1, $count
);
} while ($count > 0);
return str_replace('../', '', $path);
}
function processUrl($url) {
$parsedUrl = parse_url($url);
$path = $parsedUrl['path'];
$pathSegments = explode("/", $path);
$iterator = 0;
$removedElements = 0;
foreach ($pathSegments as $segment) {
if ($segment == "..") {
if ($iterator - $removedElements - 1 < 0) {
return false;
}
unset($pathSegments[$iterator - $removedElements - 1]);
unset($pathSegments[$iterator]);
$removedElements += 2;
}
$iterator++;
}
$parsedUrl['path'] = implode("/", $pathSegments);
$newUrl = $parsedUrl['scheme'] . '://' . $parsedUrl['host'] . "/" . $parsedUrl['path'];
return $newUrl;
}
function path_normalize($path) {
$path = str_replace('\\', '/', $path);
$blocks = preg_split('#/#', $path, null, PREG_SPLIT_NO_EMPTY);
$res = array();
while (list($k, $block) = each($blocks)) {
switch ($block) {
case '.':
if ($k == 0)
$res = explode('/', path_normalize(getcwd()));
break;
case '..';
if (!$res)
return false;
array_pop($res);
break;
default:
$res[] = $block;
break;
}
}
$r = implode('/', $res);
return $r;
}
echo 'path_normalize<br />';
$url = 'http://www.example.com/modules/newsletters/../../images/homeslider-images/test-5.jpg';
echo $url . ' === > ' . path_normalize($url);
echo '<hr />';
$url = 'http://www.example.com/../../images/homeslider-images/test-5.jpg';
echo $url . ' === > ' . path_normalize($url);
echo '<hr />normalizePath<br />';
$url = 'http://www.example.com/modules/newsletters/../../images/homeslider-images/test-5.jpg';
echo $url . ' === > ' . normalizePath($url);
echo '<hr />';
$url = 'http://www.example.com/../../images/homeslider-images/test-5.jpg';
echo $url . ' === > ' . normalizePath($url);
echo '<hr />unrelatify<br />';
$url = 'http://www.example.com/modules/newsletters/../../images/homeslider-images/test-5.jpg';
echo $url . ' === > ' . unrelatify($url);
echo '<hr />';
$url = 'http://www.example.com/../../images/homeslider-images/test-5.jpg';
echo $url . ' === > ' . unrelatify($url);
echo '<hr />processUrl<br />';
$url = 'http://www.example.com/modules/newsletters/../../images/homeslider-images/test-5.jpg';
echo $url . ' === > ' . processUrl($url);
echo '<hr />';
$url = 'http://www.example.com/../../images/homeslider-images/test-5.jpg';
echo $url . ' === > ' . processUrl($url);
?>
I am using this PHP code to get and display the number of visitors to my site (hit counter).
Currently it is set up to display that number in a single block, i.e. - I would like to display each digit in its own html tag in order to style each number differently.
I have experimented with explode, and substr on the $allHits var, but am not getting good results.
Any Ideas?
<?
/*----------------------------
-------- ++ simPHP ++ --------
A simple PHP hit counter.
Description:
simPHP counts both regular and unique views on multiple
webpages. The stats can be displayed on any PHP-enabled
webpage. You MUST have read/write permissions on files.
Script by Ajay: ajay#scyberia.org
http://scyberia.org
----------------------------*/
/*----------CONFIG----------*/
// NOTE: If you change any config after using simphp,
// remove the old files.
// Relative URL of text file that holds hit info:
$lf_name = "hits.txt";
// Save new log file each month
// 0 = No
// 1 = Yes
$monthly = 1;
// Path to store old files:
// Default for June, 2012:
// oldfiles/6-12.txt
$monthly_path = "oldfiles";
// Count unique hits or all hits:
// 0 = All hits
// 1 = Unique hits
// 2 = Both
$type = 2;
// Text to display
// before all hits.
$beforeAllText = "Site Visitors: ";
// Before unique hits.
$beforeUniqueText = "Unique Visits: ";
// Display hits on this page:
// 0 = No
// 1 = Yes
$display = 1;
// Only change this if you are recording both values.
// Separator for unique and all hits display - use HTML tags! (line break is default)
$separator = "<br \>";
// Default would output:
// Visits: 10
// Unique Visits: 10
/*--------------------------*/
/*--------BEGIN CODE--------*/
$log_file = dirname(__FILE__) . '/' . $lf_name;
//Check for "?display=true" in URL.
if ($_GET['display'] == "true") {
//Show include() info.
die("<pre><? include(\"" . dirname(__FILE__) . '/' . basename(__FILE__) . "\"); ?></pre>");
} else {
//Visit or IP.
$uIP = $_SERVER['REMOTE_ADDR'];
//Check for "hits.txt" file.
if (file_exists($log_file)) {
//Check if today is first day of month
if (date('j') == 10) {
//Ensure that monthly dir exists
if (!file_exists($monthly_path)) {
mkdir($monthly_path);
}
//Check if prev month log file exists already
$prev_name = $monthly_path . '/' . date("n-Y", strtotime("-1 month"));
if (!file_exists($prev_name)) {
//If not, move/rename current file
copy($log_file, $prev_name);
//Create new $toWrite based on CONFIG
//Write file according to CONFIG above.
if ($type == 0) {
$toWrite = "1";
$info = $beforeAllText . "1";
} else if ($type == 1) {
$toWrite = "1;" . $uIP . ",";
$info = $beforeUniqueText . "1";
} else if ($type == 2) {
$toWrite = "1;1;" . $uIP . ",";
$info = $beforeAllText . "1" . $separator . $beforeUniqueText . "1";
}
goto write_logfile;
}
}
//Get contents of "hits.txt" file.
$log = file_get_contents($log_file);
//Get type from CONFIG above.
if ($type == 0) {
//Create info to write to log file and info to show.
$toWrite = intval($log) + 1;
$info = $beforeAllText . $toWrite;
} else if ($type == 1) {
//Separate log file into hits and IPs.
$hits = reset(explode(";", $log));
$IPs = end(explode(";", $log));
$IPArray = explode(",", $IPs);
//Check for visitor IP in list of IPs.
if (array_search($uIP, $IPArray, true) === false) {
//If doesnt' exist increase hits and include IP.
$hits = intval($hits) + 1;
$toWrite = $hits . ";" . $IPs . $uIP . ",";
} else {
//Otherwise nothing.
$toWrite = $log;
}
//Info to show.
$info = $beforeUniqueText . $hits;
} else if ($type == 2) {
//Position of separators.
$c1Pos = strpos($log, ";");
$c2Pos = strrpos($log, ";");
//Separate log file into regular hits, unique hits, and IPs.
$pieces = explode(";", $log);
$allHits = $pieces[0];
$uniqueHits = $pieces[1];
$IPs = $pieces[2];
$IPArray = explode(",", $IPs);
//Increase regular hits.
$allHits = intval($allHits) + 1;
//Search for visitor IP in list of IPs.
if (array_search($uIP, $IPArray, true) === false) {
//Increase ONLY unique hits and append IP.
$uniqueHits = intval($uniqueHits) + 1;
$toWrite = $allHits . ";" . $uniqueHits . ";" . $IPs . $uIP . ",";
} else {
//Else just include regular hits.
$toWrite = $allHits . ";" . $uniqueHits . ";" . $IPs;
}
//Info to show.
$info = $beforeAllText . $allHits . $separator . $beforeUniqueText . $uniqueHits;
}
} else {
//If "hits.txt" doesn't exist, create it.
$fp = fopen($log_file ,"w");
fclose($fp);
//Write file according to CONFIG above.
if ($type == 0) {
$toWrite = "1";
$info = $beforeAllText . "1";
} else if ($type == 1) {
$toWrite = "1;" . $uIP . ",";
$info = $beforeUniqueText . "1";
} else if ($type == 2) {
$toWrite = "1;1;" . $uIP . ",";
$info = $beforeAllText . "1" . $separator . $beforeUniqueText . "1";
}
}
write_logfile:
//Put $toWrite in log file
file_put_contents($log_file, $toWrite);
//Display info if is set in CONFIG.
if ($display == 1) {
}
}
Would using a foreach loop work, like this:
$array_allHits = explode(" ",$allHits);
foreach ($array_allHits as $display_digits) {
echo $display_digits[0];
}
You could use a for-loop.
for ($i = 0; $i < strlen((string) $allHits); $i++) {
echo '<span>' . $allHits[$i] . '</span>';
}
The above code will output <span>{number}</span> for every digit in the hit count.
It will loop through every character in the string, similar as to how array indexes are treated.
$totalHits = 125655;
foreach(str_split((string)$totalHits) as $key => $val) {
echo "<span class='position_{$key}'>{$val}</span>";
}
Add styles in you css as below:
.position_0 {
color: red;
}
.position_1 {
color: blue;
}
.position_2 {
color: yellow;
}
I used the code found here for dynamic php breadcrumbs for my website. It works great! however, If I nest a folder more than 1 deep, It causes errors.
Here's the code that I have currently for the breadcrumbs.
<?php
function breadcrumbs($separator = ' » ', $home = 'Home') {
$path = array_filter(explode('/', parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH)));
$base = ($_SERVER['HTTPS'] ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'] . '/';
$breadcrumbs = Array("$home");
$last = end(array_keys($path));
foreach ($path AS $x => $crumb) {
$title = ucwords(str_replace(Array('.php', '_'), Array('', ' '), $crumb));
if ($x != $last)
$breadcrumbs[] = "$title";
else
$breadcrumbs[] = $title;
}
return implode($separator, $breadcrumbs);
}
?>
You are here: <?= breadcrumbs(' ♥ ') ?>
The easiest place to see a live example is here. If you click on the third link on the breadcrumbs, it ignores the second nested folder. I don't know enough PHP to trouble shoot the problem and how to fix it. I would think ideally it would watch for nested folders in the url.
You need to add previous crumbs to get it working correctly. Here's a fix:
<?php
function breadcrumbs($separator = ' » ', $home = 'Home') {
$path = array_filter(explode('/', parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH)));
$base = ($_SERVER['HTTPS'] ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'] . '/';
$breadcrumbs = Array("$home");
$last = end(array_keys($path));
foreach ($path AS $x => $crumb) {
$title = ucwords(str_replace(Array('.php', '_'), Array('', ' '), $crumb));
if ($x != $last)
$breadcrumbs[] = "$title";
else
$breadcrumbs[] = $title;
$base .= $crumb . '/';
}
return implode($separator, $breadcrumbs);
}
?>
You are here: <?= breadcrumbs(' ♥ ') ?>
that's because you're just linking to the current "crumb" $base$crumb
for you'll need to keep track of the path while building the links
foreach ($path AS $x => $crumb) {
$base .= $crumb.'/'; // <- keep adding crumbs to current path
$title = ucwords(str_replace(Array('.php', '_'), Array('', ' '), $crumb));
if ($x != $last)
$breadcrumbs[] = "$title"; //<- link to current path
else
$breadcrumbs[] = $title;
}
Assuming that your script runs fine , I see you have open_basedir restriction in effect so you would have to ,if you're on apache to add this to your httpd.conf
<Directory /var/www/vhosts/domain.tld/httpdocs>
php_admin_value open_basedir none
</Directory>
If script causes problems try one of the answers already given
I have a a function which return links from a given page using regular expression in php,
Now I want to go after each link in found link and so on....
Here is the code I have
function getLinks($url){
$content = file_get_contents($url);
preg_match_all("|<a [^>]+>(.*)</[^>]+>|U", $content, $links, PREG_PATTERN_ORDER);
$l_clean = array();
foreach($links[0] as $link){
$e_link = explode("href",$link);
$e_link = explode("\"",$e_link[1]);
$f_link = $e_link[1];
if( (substr($f_link,0,strlen('javascript:;')) != "javascript:;")){
$sperator = "";
$first = substr($f_link,0,1);
if($first != "/"){
$f_link = "/$f_link";
}
if(substr($f_link,0,7) != "http://"){
$f_link = "http://" . $sperator . $_SERVER['HTTP_HOST'] . $f_link;
}
$f_link = str_replace("///","//",$f_link);
if(!in_array($f_link, $l_clean)){
array_push($l_clean , $f_link);
}
}
}
}
Just do it recursively, and set a depth to terminate:
function getLinks($url, $depth){
if( --$depth <= 0 ) return;
$content = file_get_contents($url);
preg_match_all("|<a [^>]+>(.*)</[^>]+>|U", $content, $links, PREG_PATTERN_ORDER);
$l_clean = array();
foreach($links[0] as $link){
$e_link = explode("href",$link);
$e_link = explode("\"",$e_link[1]);
$f_link = $e_link[1];
if( (substr($f_link,0,strlen('javascript:;')) != "javascript:;")){
$sperator = "";
$first = substr($f_link,0,1);
if($first != "/"){
$f_link = "/$f_link";
}
if(substr($f_link,0,7) != "http://"){
$f_link = "http://" . $sperator . $_SERVER['HTTP_HOST'] . $f_link;
}
$f_link = str_replace("///","//",$f_link);
if(!in_array($f_link, $l_clean)){
array_push($l_clean , $f_link);
getLinks( $f_link, $depth );
}
}
}
}
$links = getLinks("http://myurl.com", 3);
I am trying to figure out how to convert an "external relative path" to an absolute one:
I'd really like a function that will do the following:
$path = "/search?q=query";
$host = "http://google.com";
$abspath = reltoabs($host, $path);
And have $abspath equal to "http://google.com/search?q=query"
Another example:
$path = "top.html";
$host = "www.example.com/documentation";
$abspath = reltoabs($host, $path);
And have $abspath equal to "http://www.example.com/documentation/top.html"
The problem is that it is not guaranteed to be in that format, and it could already be absolute, or be pointing to a different host entirely, and I'm not quite sure how to approach this.
Thanks.
You should try the PECL function http_build_url
http://php.net/manual/en/function.http-build-url.php
So there are three cases:
proper URL
no protocol
no protocol and no domain
Example code (untested):
if (preg_match('#^http(?:s)?://#i', $userurl))
$url = preg_replace('#^http(s)?://#i', 'http$1://', $userurl); //protocol lowercase
//deem to have domain if a dot is found before a /
elseif (preg_match('#^[^/]+\\.[^/]+#', $useurl)
$url = "http://".$useurl;
else { //no protocol or domain
$url = "http://default.domain/" . (($useurl[0] != "/") ? "/" : "") . $useurl;
}
$url = filter_var($url, FILTER_VALIDATE_URL);
if ($url === false)
die("User gave invalid url").
It appears I have solved my own problem:
function reltoabs($host, $path) {
$resulting = array();
$hostparts = parse_url($host);
$pathparts = parse_url($path);
if (array_key_exists("host", $pathparts)) return $path; // Absolute
// Relative
$opath = "";
if (array_key_exists("scheme", $hostparts)) $opath .= $hostparts["scheme"] . "://";
if (array_key_exists("user", $hostparts)) {
if (array_key_exists("pass", $hostparts)) $opath .= $hostparts["user"] . ":" . $hostparts["pass"] . "#";
else $opath .= $hostparts["user"] . "#";
} elseif (array_key_exists("pass", $hostparts)) $opath .= ":" . $hostparts["pass"] . "#";
if (array_key_exists("host", $hostparts)) $opath .= $hostparts["host"];
if (!array_key_exists("path", $pathparts) || $pathparts["path"][0] != "/") {
$dirname = explode("/", $hostparts["path"]);
$opath .= implode("/", array_slice($dirname, 0, count($dirname) - 1)) . "/" . basename($pathparts["path"]);
} else $opath .= $pathparts["path"];
if (array_key_exists("query", $pathparts)) $opath .= "?" . $pathparts["query"];
if (array_key_exists("fragment", $pathparts)) $opath .= "#" . $pathparts["fragment"];
return $opath;
}
Which seems to work pretty well, for my purposes.