Jump to content

Directory Listing & Linking


typo

Recommended Posts

I'm listing the contents of a directory up from the root '/uploads' using the following code:

$upload_dir = './uploads/';

// Get this folder and files name.
$this_script = basename(__FILE__);
$this_folder = str_replace('/'.$this_script, '', $_SERVER['SCRIPT_NAME']);

// Declare vars used beyond this point.
$file_list = array();
$folder_list = array();
$total_size = 0;

// Open the current directory...
if ($handle = opendir($upload_dir))
{
// ...start scanning through it.
    while (false !== ($file = readdir($handle)))
{
	// Make sure we don't list this folder, file or their links.
        if ($file != "." && $file != ".." && $file != $this_script && $file != ".DS_Store")
	{
		// Get file info.
		$stat				=	stat($upload_dir.'/'.$file); // ... slow, but faster than using filemtime() & filesize() instead.
		$info				=	pathinfo($upload_dir.'/'.$file);
		// Organize file info.
		$item['name']		=	$info['filename'];
		$item['lname']		=	strtolower($info['filename']);
		$item['ext']		=	$info['extension'];
			if($info['extension'] == '') $item['ext'] = '.';
		$item['bytes']		=	$stat['size'];
		$item['size']		=	bytes_to_string($stat['size'], 2);
		$item['mtime']		=	$stat['mtime'];
		// Add files to the file list...
		if($info['extension'] != '')
		{
			array_push($file_list, $item);
		}
		// ...and folders to the folder list.
		else
		{
			array_push($folder_list, $item);
		}
		// Clear stat() cache to free up memory (not really needed).
		clearstatcache();
		// Add this items file size to this folders total size
		$total_size += $item['bytes'];
        }
    }
// Close the directory when finished.
    closedir($handle);
}

 

This file is index.php and reads from a sub directory /uploads/. The listing works fine but the links to each file leave out the uploads directory from the URL so clicking on each one results in a 404. The HTML is as follows:

 

<? if($file_list): ?>
<? foreach($file_list as $item) : ?>
		<tr class="file">
			<td class="name"><a href="<?=$item['name']?>.<?=$item['ext']?>"><?=$item['name']?>.<?=$item['ext']?></a></td>
			<td class="size"><?=$item['size']['num']?><span><?=$item['size']['str']?></span></td>
			<td class="time"><?=time_ago($item['mtime'])?> old</td>
		</tr>
<? endforeach; ?>
<? endif; ?>

 

The anchor link doesn't specify the upload directory variable but I'm not sure how to include this path information. Can anyone suggest how I may alter it so it includes the specified upload directory declared in the variable?

 

Thanks

Link to comment
Share on other sites

Well, it looks like you're just missing $upload_dir in front of the filename:

 

<td class="name"><a href="<?=$upload_dir.$item['name']?>.<?=$item['ext']?>"><?=$item['name']?>.<?=$item['ext']?></a></td>

 

Another thing: Your code is difficult to read when you're using short tags and echo shortcuts.

Link to comment
Share on other sites

Ah yes, that would be the easiest way :). Thanks for pointing that out. So obvious when you look at it from a different angle.

 

I'm new to PHP but trying to work on a small PHP project in my spare time to get to grips with it so no doubt my methods wont always be the best way to do something. Would you recommend that instead of short tags I use the full <?php echo ?> tags? Any suggestions on how to improve overall code efficiency and readability are all welcomed.

 

Thanks

Link to comment
Share on other sites

Yes, full tags and echo instead of <?= are always recommended. And in your second snippet, I wouldn't open and close PHP on every line. And I would use brackets instead of endforeach and endif, with proper indentation to make things clear, but that's a matter of taste. How I probably would write it:

 

<?php
if ($file_list) {
foreach ($file_list as $item) {
	echo
'		<tr class="file">
		<td class="name"><a href="' . $upload_dir . $item['name'] . '.' . $item['ext'] . '">' . $item['name'] . '.' . $item['ext'] . '</a></td>
		<td class="size">' . $item['size']['num'] . '<span>' . $item['size']['str'] . '</span></td>
		<td class="time">' . time_ago($item['mtime']) . ' old</td>
	</tr>
';
}
}
?>

 

Even though it contains a lot of concatenation (dots), I still find it easier to read. You could also put the string inside double quotes, and the array values inside curly brackets, but then you'd have to escape all double quotes in the HTML.

 

Additional note: The simple fact that your code is syntax highlighted here on PHP Freaks, when full tags are used, is reason enough to why you should use them ;)

Link to comment
Share on other sites

Thanks for the tips. Out of interest is it necessary to have the spaces between the concatenation operators or is this simply for readability? I can see how it's more efficient to have everything inside a single php tag but from a beginner point of view matching the quotes and keeping track of the dots is a little tricky at first. If it's best policy though then I'll try and adopt it now before I get the chance to form bad habbits. ;)

 

I thought array values were normally best represented inside square brackets?

Link to comment
Share on other sites

is it necessary to have the spaces between the concatenation operators

 

Nope. You can also use commas instead of dots, feeding several strings/parameters to echo instead of a single concatenated string. But then if you decide to store a string instead of echoing it, you'll have to use concatenation again.

 

I thought array values were normally best represented inside square brackets?

 

That's right. What I meant was putting the whole thing inside curly brackets (else you'll get a warning). Like this:

 

<?php
$array['key'] = 'Google';
echo "<a href=\"http://google.com\">{$array['key']}</a>";
?>

 

Generally, just go with whatever you find best. But I wouldn't recommend opening and closing PHP on every line.

 

You could make your foreach snippet a bit simpler by storing $item['name'] . '.' . $item['ext'] in a variable, since that's used twice.

Link to comment
Share on other sites

I find it a little easier to read without the spaces in between the concatenation operators but I was just wandering why it needs one at the very start such as before $upload_dir? This isn't joining anything yet but doesn't seem to work if left out.

 

Also with regards to the array, I haven't had any warnings for not using the curly braces but I am using error_reporting(1); at the top of the document to surpress a number of notices. None of these concern the array however.

 

Thanks again.

Link to comment
Share on other sites

why it needs one at the very start such as before $upload_dir? This isn't joining anything

 

That dot joins the preceding string <tr class="file"><td class="name"><a href=" with $upload_dir.

 

In regards to the warning I'm talking about; you'll only get it when using an array value inside double quotes like this:

 

<?php
$array['key'] = 'Google';
echo "I'm using $array['key'] for my searches.";
?>

 

And only when warnings are turned on, which they aren't by default. The way you're using them is perfectly correct, I just wanted to tell you if you decided to use double quoted strings later on.

Link to comment
Share on other sites

echo "I'm using {$array['key']} for my searches.";
// or
echo "I'm using " . $array['key'] . " for my searches.";

 

You need to properly use it when echoing, either by concatenation (2nd item) or by using { } to evaluate the array since it has single quotes inside of it.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.