lauantai 3. elokuuta 2013

PHP: Using functional programming for listing files and directories

Have you ever had situation where you need to list all specific files or folders in directory? In this post I go thought some PHP's functions which are very useful for listing files or directories.

There are several functions for listing contents of directory, scandir, readdir and glob. In this article I am going to use glob. Reason for using glob over scandir and readdir is first of all that scandir function returns file names without paths, so if we want to pass the output into some another function, it is not so safe than glob, which return file names with full or relative path. On another hand, readdir function needs directory handling resource created with opendir function, so it is unnecessary complex.

Listing files and folders is simply done with glob function:

glob('mydir/*')

Code above will create an array containing all files and directories from "mydir" directory:
Array (
    [0] => mydir/file
    [1] => mydir/images
    [2] => mydir/memo.txt
    [3] => mydir/other stuff
    [4] => mydir/page.html
)

Filtering the output

Getting only directories

You may want to filter the list to get only files or only directories. Glob-function takes second parameter a flag, which gives some possibilities of procesing the output. Using function with flag GLOB_ONLYDIR make function to return only directories

glob('mydir/*',GLOB_ONLYDIR)
Return:
Array
(
    [0] => mydir/images
    [1] => mydir/other stuff
)

Getting only files

There are no handly flag for filtering list to contain only files. However, we may use the array_filter function, which is nice way to filter the output of glop. Function takes two parameters, an array and callback function for filtering. It is easy to use PHP's is_file function is this situation. 

array_filter(glob('mydir/*'),'is_file')

We wrapped the glob function with array_filter function and gave it callback function "is_file" The output should contain just files but not directories

Array (
    [0] => mydir/file
    [2] => mydir/memo.txt
    [4] => mydir/page.html
)


There are dozen of another build in functions which can be used to filter the list, such as is_readable, is_writable and is_executable. Sometimes build in functions are not enought and you need advanced filtering, for that, we are going to use closures.

Advanced filtering with closure


Lets assume we want to have list of files, which are smaller than 30 kilobytes. To get size of file, we use filesize function.

array_filter(glob('mydir/*'),function($file) {
 return (is_file($file) && filesize($file)<30000);
})
In example above, instead of giving a name of function as second parameter for array_filter, we wrote a function. In function, we used is_file to ensure that instance is a file and filesize funtion to get size of file for comparison. Again, there are dozen of another simple functions we may use for filtering, such as fileatime, filemtime and fileperms.

Get contents of files


Many times it is needed to do something with files. Lets see how we can open each file from directory. Getting a content of file is very easy with file_get_contents function. Function takes file path as parameter, read the content and insert it into a variable.
$contents=array_map('file_get_contents',array_filter(glob('mydir/*'),function($file) { 
return (is_file($file) && filesize($file)<30000);
}));
Example above we used array_map function. The function takes two argument, an array and function. Then it applies the function to all members of array. Finally it return the modified array. As result we have $contents variable which hold content of all files in mydir-directory which are smaller than 30 kilobytes.

Closing remarks

PHP have dozen simple functions which do one task, for example is_file and file_get_contents. Combining simple functions with array handling functions such as array_map or array_filter gives lot of possibilities with just few lines of code. You might also noticed that we didn't use any loops, using functional programming gave us possibility to do complex program with just couple lines of code.

Ei kommentteja:

Lähetä kommentti