PHP: atomatic include - php

I am using a lot of include files to include my 191 files of with the collection of functions, classes ect.
A problem for me is I really dislike editing the include files its gets a big mess and sometime i just forget to include something.
Therefore I was wondering, is there a include function for php or own made library that includes all the php files in a folder or even better in its own folder + all its sub-folders.
These things make life much easyer and flexible.

If you have a standard between the Class Names and the files you can use the __autoload() function. It will save you a lot of includes.
http://php.net/manual/en/language.oop5.autoload.php

You can use the following function i just created:
function load_folder($folder, $ext = '.php') {
foreach (glob("$folder*$ext") as $file) {
if (file_exists($file)) {
require_once($file);
}
}
}
START EDIT
This is the new version of the same function. Now it allows you to specify folders as folder or folder/ without crashing. Also now it loads all files in all folders and subfolders.
function load_folder($dir, $ext = '.php') {
if (substr($dir, -1) != '/') { $dir = "$dir/"; }
if($dh = opendir($dir)) {
$files = array();
$inner_files = array();
while($file = readdir($dh)) {
if($file != "." and $file != ".." and $file[0] != '.') {
if(is_dir($dir . $file)) {
$inner_files = load_folder($dir . $file);
if(is_array($inner_files)) $files = array_merge($files, $inner_files);
} else {
array_push($files, $dir . $file);
}
}
}
closedir($dh);
foreach ($files as $file) {
if (is_file($file) and file_exists($file)) {
$lenght = strlen($ext);
if (substr($file, -$lenght) == $ext) { require_once($file); }
}
}
}
}
END EDIT
You can also specify a specific extension if you want to load for example only .txt files in a folder you can execute is like this: load_folder('folder/', '.txt');.
Remember that someone think that this is somehow insecure. Before using this function inside a business site, look for more opinion about the topic.
Notice also that if some of your files are regarding classes you could use the __autoload() PHP native function to let PHP call the class where it is really needed (lazy loading).
References:
Autoloading classes

You could just have a 'meta-include' file which has the individual include statements, and then you only include that one single file in your scripts.
Of course, the auto-loading versions in the other answers here would be more efficient. While PHP's pretty fast at loading/parsing, 191 individual files to load for every request would add up pretty quick.

I usually require as first application_top.php with this:
...
function requireAll($folder){
// open the folder
$libs = opendir($folder);
// loop inside to include each file, excluding windows default 'meta-link' . and ..
while ($lib = readdir($libs)) {
if ($lib != "." && $lib != "..")
// require_once to be sure to require only one time
require_once $folder . $lib;
}
// close the dir for cleaning stuff
closedir($libs);
}
//Require all helpers
requireAll(DIR_HELPERS);
//Require all model classes
requireAll(DIR_MODEL);
//Require all mappers
requireAll(DIR_MAPPERS);
...

Related

PHP Move Files With Specific Format vs Move All Files

I have these files in /public_html/ directory :
0832.php
1481.php
2853.php
3471.php
index.php
and I want to move all those XXXX.php (always in 4 digits format) to directory /tmp/, except index.php. how to do it with reg-ex and loop?
Alternatively, how about moving all files (including index.php) first to /tmp/ then later on put only index.php back to /public_html/, which one you think is less CPU consuming?
Last thing, I found this tutorial to move file using PHP: http://www.kavoir.com/2009/04/php-copying-renaming-and-moving-a-file.html
But how to move ALL files in a directory?
You can use FilesystemIterator with RegexIterator
$source = "FULL PATH TO public_html";
$destination = "FULL PATH TO public_html/tmp";
$di = new FilesystemIterator($source, FilesystemIterator::SKIP_DOTS);
$regex = new RegexIterator($di, '/\d{4}\.php$/i');
foreach ( $regex as $file ) {
rename($file, $destination . DIRECTORY_SEPARATOR . $file->getFileName());
}
The best way would be to do it directly via the file system, but if you absolutely have to do it with PHP, something like this should do what you want - you'll have to change the paths so that they are correct, obviously. Note that this assumes that there could be other files in the public_html directory, and so it only get the filenames with 4 numbers.
$d = dir("public_html");
while (false !== ($entry = $d->read())) {
if($entry == '.' || $entry == '..') continue;
if(preg_match("#^\d{4}$#", basename($entry, ".php")) {
// move the file
rename("public_html/".$entry, "/tmp/".$entry));
}
}
$d->close();
in fact - I went to readdir manual page and the fist comment to read is:
loop through folders and sub folders with option to remove specific files.
<?php
function listFolderFiles($dir,$exclude){
$ffs = scandir($dir);
echo '<ul class="ulli">';
foreach($ffs as $ff){
if(is_array($exclude) and !in_array($ff,$exclude)){
if($ff != '.' && $ff != '..'){
if(!is_dir($dir.'/'.$ff)){
echo '<li>'.$ff.'';
} else {
echo '<li>'.$ff;
}
if(is_dir($dir.'/'.$ff)) listFolderFiles($dir.'/'.$ff,$exclude);
echo '</li>';
}
}
}
echo '</ul>';
}
listFolderFiles('.',array('index.php','edit_page.php'));
?>
Regexes are in fact overkill for this, as we only need to do some simple string matching:
$dir = 'the_directory/';
$handle = opendir($dir) or die("Problem opening the directory");
while ($filename = readdir($handle) !== false)
{
//if ($filename != 'index.php' && substr($filename, -3) == '.php')
// I originally thought you only wanted to move php files, but upon
// rereading I think it's not what you really want
// If you don't want to move non-php files, use the line above,
// otherwise the line below
if ($filename != 'index.php')
{
rename($dir . $filename, '/tmp/' . $filename);
}
}
Then for the question:
alternatively, how about moving all files (including index.php) first to /tmp/ then later on put only index.php back to /public_html/, which one you think is less CPU consuming?
It could be done, and it would probably be slightly easier on your CPU. However, there are several reasons why this doesn't matter. First off, you're already doing this in a very inefficient way by doing it through PHP, so you shouldn't really be looking at the strain this puts on your CPU at this point unless you are willing to do it outside PHP. Secondly, that would cause more disk access (especially if the source and destination directory aren't on the same disk or partition) and disk access is much, much slower than your CPU.

Optimising php file reading code

I have the following which is fairly slow. How can I speed it up?
(it scans a directory and makes headers out of the foldernames and retrieves the pdf files from within and adds them to lists)
$directories= array_diff(scandir("../pdfArchive/subfolder", 0), array('..', '.'));
foreach ($directories as $v) {
echo "<h3>".$v."</h3>";
$current = array_diff(scandir("../pdfArchive/subfolder/".$v, 0), array('..', '.'));
echo "<ul style=\"list-style-image: url(/images/pdf.gif); margin-left: 20px;\">";
foreach ($current as $vone) {
echo "<li><a target=\"blank\" href=\"../pdfArchive/subfolder/".$vone."\">".str_replace(".pdf", "", $vone)."</a>";
echo "</li><br>";
}
echo "</ul>";
}
Don't use array_diff() to filter out current and parent directory, use something like DirectoryIterator or glob() and then test whether it's . or .. via an if statement
glob() has a flag that allows you to retrieve only directories for your loops
Profile your code to see exactly what lines/functions are executing slowly
I'm not sure how fast array_diff() is when the array is very large, isn't it faster to simply add a separate check and make sure that '.' and '..' is not the returned name?
Other than that, I can't see there being anything really wrong.
What did you test to consider the current approach slow?
Here is a snippet of code I use that I adapted from php.net. It is very basic and goes through a given directory and lists the files contained within.
// The # suppresses any errors, $dir is the directory path
if (($handle = #opendir($dir)) != FALSE) {
// Loop over directory contents
while (($file = readdir($handle)) !== FALSE) {
// We don't want the current directory (.) or parent (..)
if ($file != "." && $file != "..") {
var_dump($file);
if (!is_dir($dir . $file)) {
// $file is really a file
} else {
// $file is a directory
}
}
}
closedir($handle);
} else {
// Deal with it
}
You may adapt this further to recurse over subdirectories by using is_dir to identify folders as I have shown above.

Require multiple files

I am building a PHP application that uses a select menu to build email templates. The templates are broken into reusable parts (each is a separate html file). Is there an easy way to require multiple files with one expression? (my PHP is really rusty...)
Essentially I want to do something like:
function require_multi() {
require_once($File1);
require_once($File2);
require_once($File3);
require_once($File4);
}
Well, you could turn it into a function:
function require_multi($files) {
$files = func_get_args();
foreach($files as $file)
require_once($file);
}
Use like this:
require_multi("one.php", "two.php", ..);
However, if you're including classes, a better solution would be to use autoloading.
Credit to Tom Haigh from how to require all files in a folder?:
$files = glob( $dir . '/*.php' );
foreach ( $files as $file )
require( $file );
Store all your required files in $dir and the above code will do the rest.
EDIT:
Because you want to require or include multiple files, you could use this recursive
algorithm to include files in a specified folder. The folder is the root that starts
the iterator. Because the algorithm is recursive, it will automatically traverse all
subsequent folders and include those files as well.
public function include_all_files($root) {
$d = new RecursiveDirectoryIterator($root);
foreach (new RecursiveIteratorIterator($d) as $file => $f) {
$ext = pathinfo($f, PATHINFO_EXTENSION);
if ($ext == 'php' || $ext == 'inc')
include_once ($file); // or require(), require_once(), include_once()
}
}
include_all_files('./lib');

Is there a way to put this PHP into an array and simplify it?

The following code loads all .php files found in the specified folder (defined separately). Is there a way to put this into an array to simplify the code?
Only a couple of variables change but essentially the code repeats several times.
// The General Files
$the_general = opendir(FRAMEWORK_GENERAL);
while (($the_general_files = readdir($the_general)) !== false) {
if(strpos($the_general_files,'.php')) {
include_once(FRAMEWORK_GENERAL . $the_general_files);
}
}
closedir($the_general);
// The Plugin Files
$the_plugins = opendir(FRAMEWORK_PLUGINS);
while (($the_plugins_files = readdir($the_plugins)) !== false) {
if(strpos($the_plugins_files,'.php')) {
include_once(FRAMEWORK_PLUGINS . $the_plugins_files);
}
}
closedir($the_plugins);
There are several more sections which call different folders.
Any help is greatly appreciated.
Cheers,
James
I nicer way to do this would to use glob(). And make it into a function.
function includeAllInDirectory($directory)
{
if (!is_dir($directory)) {
return false;
}
// Make sure to add a trailing slash
$directory = rtrim($directory, '/\\') . '/';
foreach (glob("{$directory}*.php") as $filename) {
require_once($directory . $filename);
}
return true;
}
This is fairly simple. See arrays and foreach.
$dirs = array(FRAMEWORK_GENERAL, FRAMEWORK_PLUGINS, );
foreach ($dirs as $dir) {
$d = opendir($dir);
while (($file = readdir($d)) !== false) {
if(strpos($file,'.php')) {
include_once($dir . $file);
}
}
closedir($d);
}
A better idea might be lazy loading via __autoload or spl_autoload_register, including all the .php files in a directory might seem like a good idea now, but not when your codebase gets bigger.
Your code should be layed out in an easy to understand heirarchy, rather than putting them all in one directory so they can be included easily. Also, if you dont need all of the code in the files in every request you are wasting resources.
Check http://php.net/manual/en/language.oop5.autoload.php for an easy example.
This can be done pretty tightly:
$dirs = array(FRAMEWORK_GENERAL, FRAMEWORK_PLUGINS);
foreach($dirs as $dir) {
if (!is_dir($dir)) { continue; }
foreach (glob("$dir/*.php") as $filename) {
include($filename);
}
}
Put that in a function where $dirs comes in as a param and use freely.

move all files in a folder to another?

when moving one file from one location to another i use
rename('path/filename', 'newpath/filename');
how do you move all files in a folder to another folder? tried this one without result:
rename('path/*', 'newpath/*');
A slightly verbose solution:
// Get array of all source files
$files = scandir("source");
// Identify directories
$source = "source/";
$destination = "destination/";
// Cycle through all source files
foreach ($files as $file) {
if (in_array($file, array(".",".."))) continue;
// If we copied this successfully, mark it for deletion
if (copy($source.$file, $destination.$file)) {
$delete[] = $source.$file;
}
}
// Delete all successfully-copied files
foreach ($delete as $file) {
unlink($file);
}
Please try this solution, it's tested successfully ::
<?php
$files = scandir("f1");
$oldfolder = "f1/";
$newfolder = "f2/";
foreach($files as $fname) {
if($fname != '.' && $fname != '..') {
rename($oldfolder.$fname, $newfolder.$fname);
}
}
?>
An alternate using rename() and with some error checking:
$srcDir = 'dir1';
$destDir = 'dir2';
if (file_exists($destDir)) {
if (is_dir($destDir)) {
if (is_writable($destDir)) {
if ($handle = opendir($srcDir)) {
while (false !== ($file = readdir($handle))) {
if (is_file($srcDir . '/' . $file)) {
rename($srcDir . '/' . $file, $destDir . '/' . $file);
}
}
closedir($handle);
} else {
echo "$srcDir could not be opened.\n";
}
} else {
echo "$destDir is not writable!\n";
}
} else {
echo "$destDir is not a directory!\n";
}
} else {
echo "$destDir does not exist\n";
}
tried this one?:
<?php
$oldfolderpath = "old/folder";
$newfolderpath = "new/folder";
rename($oldfolderpath,$newfolderpath);
?>
So I tried to use the rename() function as described and I kept getting the error back that there was no such file or directory. I placed the code within an if else statement in order to ensure that I really did have the directories created. It looked like this:
$tempDir = '/home/site/images/tmp/';
$permanentDir = '/home/site/images/' . $claimid; // this was stored above
mkdir($permanentDir,0775);
if(is_dir($permanentDir)){
echo $permanentDir . ' is a directory';
if(is_dir($tempDir)){
echo $tempDir . ' is a directory';
}else{
echo $tempDir . ' is not a directory';
}
}else{
echo $permanentDir . ' is not a directory';
}
rename($tempDir . "*", $permanentDir);
So when I ran the code again, it spit out that both paths were directories. I was stumped. I talked with a coworker and he suggested, "Why not just rename the temp directory to the new directory, since you want to move all the files anyway?"
Turns out, this is what I ended up doing. I gave up trying to use the wildcard with the rename() function and instead just use the rename() to rename the temp directory to the permanent one.
so it looks like this.
$tempDir = '/home/site/images/tmp/';
$permanentDir = '/home/site/images/' . $claimid; // this was stored above
mkdir($permanentDir,0775);
rename($tempDir, $permanentDir);
This worked beautifully for my purposes since I don't need the old tmp directory to remain there after the files have been uploaded and "moved".
Hope this helps. If anyone knows why the wildcard doesn't work in the rename() function and why I was getting the error stating above, please, let me know.
Move or copy the way I use it
function copyfiles($source_folder, $target_folder, $move=false) {
$source_folder=trim($source_folder, '/').'/';
$target_folder=trim($target_folder, '/').'/';
$files = scandir($source_folder);
foreach($files as $file) {
if($file != '.' && $file != '..') {
if ($move) {
rename($source_folder.$file, $target_folder.$file);
} else {
copy($source_folder.$file, $target_folder.$file);
}
}
}
}
function movefiles($source_folder, $target_folder) {
copyfiles($source_folder, $target_folder, $move=true);
}
try this:
rename('path/*', 'newpath/');
I do not see a point in having an asterisk in the destination
If the target directory doesn't exist, you'll need to create it first:
mkdir('newpath');
rename('path/*', 'newpath/');
As a side note; when you copy files to another folder, their last changed time becomes current timestamp. So you should touch() the new files.
... (some codes for directory looping) ...
if (copy($source.$file, $destination.$file)) {
$delete[] = $source.$file;
$filetimestamp = filemtime($source.$file);
touch($destination.$file,$filetimestamp);
}
... (some codes) ...
Not sure if this helps anyone or not, but thought I'd post anyway. Had a challenge where I has heaps of movies I'd purchased and downloaded through various online stores all stored in one folder, but all in their own subfolders and all with different naming conventions. I wanted to move all of them into the parent folder and rename them all to look pretty. all of the subfolders I'd managed to rename with a bulk renaming tool and conditional name formatting. the subfolders had other files in them i didn't want. so i wrote the following php script to, 1. rename/move all files with extension mp4 to their parent directory while giving them the same name as their containing folder, 2. delete contents of subfolders and look for directories inside them to empty and then rmdir, 3. rmdir the subfolders.
$handle = opendir("D:/Movies/");
while ($file = readdir($handle)) {
if ($file != "." && $file != ".." && is_dir($file)) {
$newhandle = opendir("D:/Movies/".$file);
while($newfile = readdir($newhandle)) {
if ($newfile != "." && $newfile != ".." && is_file("D:/Movies/".$file."/".$newfile)) {
$parts = explode(".",$newfile);
if (end($parts) == "mp4") {
if (!file_exists("D:/Movies/".$file.".mp4")) {
rename("D:/Movies/".$file."/".$newfile,"D:/Movies/".$file.".mp4");
}
else {
unlink("D:/Movies/".$file."/".$newfile);
}
}
else { unlink("D:/Movies/".$file."/".$newfile); }
}
else if ($newfile != "." && $newfile != ".." && is_dir("D:/Movies/".$file."/".$newfile)) {
$dirhandle = opendir("D:/Movies/".$file."/".$newfile);
while ($dirfile = readdir($dirhandle)){
if ($dirfile != "." && $dirfile != ".."){
unlink("D:/Movies/".$file."/".$newfile."/".$dirfile);
}
}
rmdir("D:/Movies/".$file."/".$newfile);
}
}
unlink("D:/Movies/".$file);
}
}
i move all my .json files from root folder to json folder with this
foreach (glob("*.json") as $filename) {
rename($filename,"json/".$filename);
}
pd: someone 2020?

Categories