I'm new to this forum and also new to PHP, I'm building some very basic functions on a test site while I learn a little more about how to use PHP. One of the current project I'm experimenting with is combining two directories of CSV files.
I was hoping to use GLOB as sort of a *wildcard to gather up the files in each directory and then combine them. I know the way I'm using below isn't very memory efficient but this is just to learn with. The issue I'm having is setting the GLOB command to pickup all my CSV files and then getting that variable into a file_get_contents.
Here's my code..
$files = glob("http://www.website.com/1/*.csv");
foreach($files as $filepath) {
if ($handle = fopen($filepath, "r")) {
// ...
}
}
$files2 = glob("http://www.website.com/35/*.csv");
foreach($files2 as $filepath2) {
if ($handle2 = fopen($filepath2, "r")) {
// ...
}
}
file_put_contents('final_data.csv',
file_get_contents($files) .
file_get_contents($files2)
);
When you use Glob the resulting array doesn't contain the base path, so you have to add it, like this:
$basePath = '/path/to/csv';
foreach ($files = glob("$basePath/dir1/*.csv") as $filePath)
{
echo "$basePath/$filePath";
//
}
It would also make sense to read from local path instead of remote URL.
Related
In my program I need to read .png files from a .tar file.
I am using pear Archive_Tar class (http://pear.php.net/package/Archive_Tar/redirected)
Everything is fine if the file im looking for exists, but if it is not in the .tar file then the function timouts after 30 seconds. In the class documentation it states that it should return null if it does not find the file...
$tar = new Archive_Tar('path/to/mytar.tar');
$filePath = 'path/to/my/image/image.png';
$file = $tar->extractInString($filePath); // This works fine if the $filePath is correct
// if the path to the file does not exists
// the script will timeout after 30 seconds
var_dump($file);
return;
Any suggestions on solving this or any other library that I could use to solve my problem?
The listContent method will return an array of all files (and other information about them) present in the specified archive. So if you check if the file you wish to extract is present in that array first, you can avoid the delay that you are experiencing.
The below code isn't optimised - for multiple calls to extract different files for example the $files array should only be populated once - but is a good way forward.
include "Archive/Tar.php";
$tar = new Archive_Tar('mytar.tar');
$filePath = 'path/to/my/image/image.png';
$contents = $tar->listContent();
$files = array();
foreach ($contents as $entry) {
$files[] = $entry['filename'];
}
$exists = in_array($filePath, $files);
if ($exists) {
$fileContent = $tar->extractInString($filePath);
var_dump($fileContent);
} else {
echo "File $filePath does not exist in archive.\n";
}
I'm in the process of creating an experiment for a psychology researcher, there are various tasks involved which the participant has to complete. I have been asked to randomise the order of the folders, but keep the order of files inside the directories the same.
I have looked at using glob() but I think I'm implementing it wrong.
My directory looks like this:
Clock
>>Task 1/Files.>>Task 2/Files.>>Task 3/Files.
At the moment I have this:
<?php
function random_folders($dir = 'Clock')
{
$folder = glob($dir. '/Task.*');
$folderRand = array_rand($folder);
return $folder[$folderRand];
}
echo random_folders();
?>
I've tried googling and using stackoverflow to search for a solution but I can't seem to find one, any help will be greatly appreciated.
Edit
I should mention that I'm using HTML5, JavaScript, PHP and MySQL to create the website, if that's relevant.
Thanks.
Your glob() is a little off. You don't want the . before the *. Then use shuffle() to shuffle them:
function random_folders($dir = 'Clock')
{
$folder = glob($dir. '/Task*');
shuffle($folder);
// Returns the randomized array of folders
return $folder;
}
$random_folders = random_folders();
// List them and their contents:
foreach ($random_folders as $rf) {
echo "Folder: $rf\n";
// List files in ascending order
$files = scandir($rf, SCANDIR_SORT_ASCENDING);
foreach ($files as $f) {
if ($file !== "." && $file !== "..") {
echo $file . "\n";
}
}
I am trying to make an HTML5 slideshow system that implements PHP. My idea begins with making a system that detects the images in a folder, and puts them in an array, which the jquery will then be able to access for implementation in the slideshow. Firstly I have a php file that will detect the names of every file in the folder, and output them as plain text.
How, instead of outputting as plain text, can i make the PHP transfer the file names to a numerical array, which can be used with the jquery that will then accompany it?
I intend to use jquery to access the numerical array that is then made. How is this done? Unless it is not possible to do, and so how else can it be done?
The goal is to be able to put files in a folder, and for the scripting to dynamically recognize the presence of files, and incorporate them in a slideshow. This slideshow will then be output to a screen display which will be used in a waiting area, showcasing our school with a slideshow of images about the school.
Here is the code that I have so far:
<?php
//Open images directory
$dir = opendir("images");
//List files in images directory
while (($file = readdir($dir)) !== false)
{
echo "filename: " . $file . "<br />";
}
closedir($dir);
?>
At this point I do not know how to make PHP "talk" with Javascript. I hope that there is some simple method for this, what I think I'm going for is AJAX, but I have no idea how this works.
The answer here is to use JSON, a subset of Javascript supported by many languages that allows you to (amongst many other things) very easily pass structured data into Javascript from external sources. PHP has a function json_encode() which allows you convert PHP data structures - usually arrays or objects - into a format the Javascript can easily read. jQuery also has built-in support for JSON.
<?php
// An array of the image file names
$images = array();
//Open images directory
$dir = opendir("images");
//List files in images directory
while (($file = readdir($dir)) !== false)
{
$images[] = $file;
}
closedir($dir);
echo json_encode($images);
?>
Now, in jQuery you can do this:
$.getJSON('http://url/of/your/script.php', function(images) {
// In here the variable "images" is an array identical to the one you constructed with PHP
});
Yes you can use ajax to fetch the image filenames as an array by changing you php code like follows
<?php
//Open images directory
$dir = opendir("images");
$images = array();
//List files in images directory
while (($file = readdir($dir)) !== false)
{
//echo "filename: " . $file . "<br />";
$images[] = $files;
}
closedir($dir);
echo json_encode($images);
?>
then use $.getJSON o fetch that list
$.getJSON('path_to_above_php_file', function(images) {
//all your files are in images array, you can loop through it to find individual files
});
You could have an array with all your pictures then convert this array to JSON.
There are a few ways to do this, a quick and easy way is to do:
your php:
$dir = opendir("images");
$store = array();
while (($file = readdir($dir)) !== false)
{
$store[] = $file;
}
closedir($dir);
Now you have an array of all files (i might add that you may want to validate the file is an image!). I like to just dump them into JS as a json string as it saves me messing around. so:
echo "<script> var allimages = jQuery.parseJSON('".addslashes(json_encode($store))."'); </script>";
Now if you console.log() the allimages variable you will see you have all your images within that so you can use "$.each" or similar if you wish.
Rather than simply storing the name of the images, why not write the images themselves to your document? So something like:
<?php
//Open images directory
$dir = opendir("images");
//List files in images directory
while (($file = readdir($dir)) !== false)
{
$files[] = YOUR_URL_PATH.$file;
}
closedir($dir);
?>
...
<div id="slideshow">
<?php
foreach($files as $img)
echo '<img class="slide" src="'.$img.'" />';
?>
</div>
...
<script type="text/javascript">
$(document).ready(function()
{
alert($(".slide").length+" slides detected");
});
</script>
That way, instead of relying on PHP to define your jQuery, you're using PHP to define the elements jQuery needs in order to function properly.
UPDATE:
If your PHP and Javascript exist on the same page, and you still want to be able to set a Javascript array using PHP, then I think this is what you're looking for:
<?php
//Open images directory
$dir = opendir("images");
//List files in images directory
while (($file = readdir($dir)) !== false)
{
$files[] = YOUR_URL_PATH.$file;
}
closedir($dir);
?>
...
<script type="text/javascript">
$(document).ready(function()
{
var fileArr = [<?php echo implode(',',$files); ?>];
});
</script>
This requires that your Javascript resides on the same page as your PHP that defines the file array. If your Javascript is intended to be referenced externally, then your best bet is to use JSON array as mentioned by many of the other answers here.
I would say JSON suits your situation well. Just create PHP file that prints (echo) the JSON object containing the list of your files. You can use json_encode() to create the JSON object. On your browser side you can make an AJAX request (or simply use jQuery.getJSON()) and set the data type to JSON and you should be good to go:
$.ajax({
url: url,
dataType: 'json',
data: data,
success: callback
});
Here you can read about using JSON in PHP.
SPL library has function to handler directories
From PHP site:
Usage example:
To see all the files:
<?php
$ite=new RecursiveDirectoryIterator($_POST['path']);
$files = array();
foreach (new RecursiveIteratorIterator($ite) as $filename=>$cur) {
array_push($files, $filename);
}
echo json_encode($files);
?>
Now with jquery.post() you can retrieve the list of files in folder.
I have the following code snippet. I'm trying to list all the files in a directory and make them available for users to download. This script works fine with directories that don't have sub-directories, but if I wanted to get the files in a sub-directory, it doesn't work. It only lists the directory name. I'm not sure why the is_dir is failing on me... I'm a bit baffled on that. I'm sure that there is a better way to list all the files recursively, so I'm open to any suggestions!
function getLinks ($folderName, $folderID) {
$fileArray = array();
foreach (new DirectoryIterator(<some base directory> . $folderName) as $file) {
//if its not "." or ".." continue
if (!$file->isDot()) {
if (is_dir($file)) {
$tempArray = getLinks($file . "/", $folderID);
array_merge($fileArray, $tempArray);
} else {
$fileName = $file->getFilename();
$url = getDownloadLink($folderID, $fileName);
$fileArray[] = $url;
}
}
}
Instead of using DirectoryIterator, you can use RecursiveDirectoryIterator, which provides functionality for iterating over a file structure recursively. Example from documentation:
$path = realpath('/etc');
$objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::SELF_FIRST);
foreach($objects as $name => $object){
echo "$name\n";
}
This prints a list of all files and
directories under $path (including
$path ifself). If you want to omit
directories, remove the
RecursiveIteratorIterator::SELF_FIRST
part.
You should use RecursiveDirectoryIterator, but you might also want to consider using the Finder component from Symfony2. It allows for easy on the fly filtering (by size, date, ..), including dirs or files, excluding dirs or dot-files, etc. Look at the docblocks inside the Finder.php file for instructions.
I'm not sure how simple this would be, but I'm using a script which displays the files from a specific folder, however I'd like them to be displayed in alphabetical order, would it be hard to do this? Here's the code I'm using:
if ($handle = opendir($mainframe->getCfg( 'absolute_path' ) ."/images/store/")) {
while (false !== ($file = readdir($handle))) {
if ($file != "." && $file != "..") {
if (($file != "index.html")&&($file != "index.php")&&($file != "Thumbs.db")) {
$strExt = end(explode(".", $file));
if ($strExt == 'jpg') {
$Link = 'index.php?option=com_shop&task=deleteFile&file[]='.$file;
$thelist .= '<tr class="row0"><td nowrap="nowrap">'.$file.'</td>'."\n";
$thelist .= '<td align="center" class="order"><img src="/administrator/images/publish_x.png" width="16" height="16" alt="delete"></td></tr>'."\n";
}
}
}
}
closedir($handle);
}
echo $thelist;
:)
Instead of using readdir you could simply use scandir (documentation) which sorts alphabetically by default.
The return value of scandir is an array instead of a string, so your code would have to be adjusted slightly, to iterate over the array instead of checking for the final null return value. Also, scandir takes a string with the directory path instead of a file handle as input, the new version would look something like this:
foreach(scandir($mainframe->getCfg( 'absolute_path' ) ."/images/store/") as $file) {
// rest of the loop could remain unchanged
}
That code looks pretty messy. You can separate the directory traversing logic with the presentation. A much more concise version (in my opinion):
<?php
// Head of page
$it = new DirectoryIterator($mainframe->getCfg('absolute_path') . '/images/store/'));
foreach ($it as $file) {
if (preg_match('#\.jpe?g$#', $file->getFilename()))
$files[] = $file->getFilename();
}
sort($files);
// Further down
foreach ($files as $file)
// display links to delete file.
?>
You don't even need to worry about opening or closing the handle, and since you're checking the filename with a regular expression, you don't need any of the explode or conditional checks.
I like Glob
It makes directory reading a snap as it returns an array that's easily sortable:
<?php
$files = glob("*.txt");
sort($files);
foreach ($files as $filename) {
echo "$filename size " . filesize($filename) . "\n";
}
?>
If you're using Joomla1.5 you should be using the defined constant JPATH_BASE instead of
$mainframe->getCfg( 'absolute_path' )
If this is a Joomla extension that you will distribute, don't use scandir() as it is PHP5 only.
The best thing to do is to use the Joomla API. It has a classes for directory and file access that is layered to do this over different networks and protocols. So the file system can be over FTP for example, and the classes can be extended for any network/protocol.
jimport( 'joomla.filesystem.folder' );
$files = JFolder::files(JPATH_BASE."/images/store/");
sort($files);
foreach($files as $file) {
// do your filtering and other task
}
You can also pass a regular expression as the second parameter to JFolder::files() that filters the files you receive.
You also don't want to use URL literals like /administrator/ since they can be changed.
use the JURI methods like:
JURI::base();
If you want to make sure of the Joomla CSS classes in the tables, for:
'<tr class="row0">'
use:
'<tr class="row'.($i&1).'">'
where $i is the number of iterations. This gives you a sequence of alternating 0s and 1s.
if we have PHP built in functions, always use it, they are faster.
use glob instead of traversing folders, if it fits for your needs.
$folder_names = array();
$folder_names = glob( '*', GLOB_ONLYDIR + GLOB_MARK + GLOB_NOSORT );
returs everything in the current directory, use chdir() before calling it
remove the GLOB_ONLYDIR to include files too ( . would be only files )
GLOB_MARK is for adding a slash to folders names
Remove GLOB_NOSORT not to sort the array