access to array outside function - php

Have found 2 threads on this here at Stackoverflow, hovever these are about how to return an array. I can generate an array inside the function and it is having the right content, however when doing var_dumping of $target_file outside the function it is NULL. Otherwise the code is doing what it is supposed to do.
Is it a scope thing? or...have I done something completely wrong here?
Can anyone please help me access the returned array outside the function?
function copy_files3($requested, $src_path, $send_path){
//function copy_files renames and copies pdf-files to a specific folder.
//ARRAY $requested (keys INT), (names STR) holds the names of the selected files
//STR $src_path is the full path to the requested files
//STR $send_path is the full path to the re-named files
//ARRAY $target_file holds the names of the renamed files
$i=0;
$target_file = array();
$src_filename = array();
$b=array();
foreach($requested as $value) {
//$value holds the names of the selected files.
//1 Expand to get the full path to the source file
//2 Generate a 10 char + .pdf (aka 14 char) long new file name for the file.
//3 Generate full path to the new file.
$src_filename[$i] = $src_path.$value;
$rnam[$i] = randomstring(); //function randomstring returns a 10 char long random string
$target_file[$i] = $send_path.$rnam[$i].'.pdf';
echo 'target_file['.$i.'] = '.$target_file[$i].'<br>';
copy($src_filename[$i],$target_file[$i]);
$i++;
}
return($target_file);
}
I have files renamed and placed in the correct folders on my server, the only problem is accessing the $target_file array after this function.

$target_file exists only inside the function. And yes, it's a scope thing.
You are returning this variable's value, but not the variable itself.
All you have to do is to assign returned value to some variable while invoking the function.
$returnedValue = copy_files3($requested, $src_path, $send_path);
Now, $returnedValue has the same value as $target_file had inside the function.

<?php
function copy_files3($requested, $src_path, $send_path){
//function copy_files renames and copies pdf-files to a specific folder.
//ARRAY $requested (keys INT), (names STR) holds the names of the selected files
//STR $src_path is the full path to the requested files
//STR $send_path is the full path to the re-named files
//ARRAY $target_file holds the names of the renamed files
$i=0;
$target_file = array();
$src_filename = array();
$b=array();
foreach($requested as $value) {
//$value holds the names of the selected files.
//1 Expand to get the full path to the source file
//2 Generate a 10 char + .pdf (aka 14 char) long new file name for the file.
//3 Generate full path to the new file.
$src_filename[$i] = $src_path.$value;
$rnam[$i] = randomstring(); //function randomstring returns a 10 char long random string
$target_file[$i] = $send_path.$rnam[$i].'.pdf';
echo 'target_file['.$i.'] = '.$target_file[$i].'<br>';
copy($src_filename[$i],$target_file[$i]);
$i++;
}
return($target_file);
}
$returnedValue = copy_files3($requested, $src_path, $send_path);
?>

Related

Get latest file in dir including subdirectory php

i found out that i can use
$files = scandir('c:\myfolder', SCANDIR_SORT_DESCENDING);
$newest_file = $files[0];
to get the latest file in the given directory ('myfolder').
is there an easy way to get the latest file including subdirectorys?
like:
myfolder> dir1 > file_older1.txt
myfolder> dir2 > dir3 > newest_file_in_maindir.txt
myfolder> dir4 > file_older2.txt
Thanks in advance
To the best of my knowledge, you have to recursively check every folder and file to get the last modified file. And you're current solution doesn't check the last modified file but sorts the files in descending order by name.
Meaning if you have a 10 years old file named z.txt it will probably end up on top.
I've cooked up a solution.
The function accepts a directory name and makes sure the directory
exists. It returns null when the directory has no files or any of its subdirectories.
Sets aside the variables $latest and $latestTime where the last modified file is stored.
It loops through the directory, avoiding the . and .. since they can cause an infinite recursion loop.
In the loop the full filename is assembled from the initial directory name and the part.
The filename is checked if it is a directory if so it calls the same function we are in and saves the result.
If the result is null we continue the loop otherwise we save the file as the new filename, which we now know is a file.
After that we check the last modified time using filemtime and see if the $latestTime is smaller meaning the file was modified earlier in time that the current one.
If the new file is indeed younger we save the new values to $latest and $latestTime where $latest is the filename.
When the loop finishes we return the result.
function find_last_modified_file(string $dir): ?string
{
if (!is_dir($dir)) throw new \ValueError('Expecting a valid directory!');
$latest = null;
$latestTime = 0;
foreach (scandir($dir) as $path) if (!in_array($path, ['.', '..'], true)) {
$filename = $dir . DIRECTORY_SEPARATOR . $path;
if (is_dir($filename)) {
$directoryLastModifiedFile = find_last_modified_file($filename);
if (null === $directoryLastModifiedFile) {
continue;
} else {
$filename = $directoryLastModifiedFile;
}
}
$lastModified = filemtime($filename);
if ($lastModified > $latestTime) {
$latestTime = $lastModified;
$latest = $filename;
}
}
return $latest;
}
echo find_last_modified_file(__DIR__);
In step 7 there is an edge case if both files were modified at the exact same time this is up to you how you want to solve. I've opted to leaving the initial file with that modified time instead of updating it.

How create recursively ZIP file, from array which contains total directory paths WITHOUT the name of the pdfs inside

I have a directory with name 2019. I want to create a ZIP file which contains all the pdf files inside the folders 01-03. In a for loop, I fill an array with all the paths of the directories who are not empty. Now I don't know how to open a stream or something else to put the array values inside in a for loop and recursively add all pdfs under each subfolder path inside it. Any idea guys?
for ($i = 1; $i < 4; $i++) {
// for the 3 months of this year
$absolutepath = "$year_path/0$i";
if (file_exists($absolutepath) && glob($absolutepath . "/*")) {
// check if path/year/month exists
// check if folder contains any files
// store specific full paths inside array for use
array_push($path_array, $absolutepath);
}
}
// how can i put here $path_array into a function to create zip file which contains all the pdfs under each subfolder path of the $path_array ???
It looks like you are creating the string wrong. You have to concatenate the variables outside of the string for the path separator with the leading zero. I think it should be:
$absolutepath = $year_path + "/0" + $i;

Copy and rename multiple files with PHP

Is there a way to copy and rename multiple files in php but get their names from an array or a list of variables.
The nearest thing to what I need that I was able to find is this page
Copy & rename a file to the same directory without deleting the original file
but the only thing the script on this page does is creating a second file and it's name is already preset in the script.
I need to be able to copy and create multiple files, like 100-200 and get their names set from an array.
If I have an initial file called "service.jpg"
I would need the file to be copied multiple times with the different names from the array as such :
$imgnames = array('London', 'New-York','Seattle',);
etc.
Getting a final result of 3 separate files called "service-London.jpg", "service-New-York.jpg" and so on.
I'm sure that it should be a pretty simple script, but my knowledge of PHP is really insignificant at the time.
One approach (untested) that you can take is creating a class to duplicate a directory. You mentioned you would need to get the name of the files in a directory and this approach will handle it for you.
It will iterate over an array of names (whatever you pass to it), and copy/rename all of the files inside a directory of your choice. You might want to add some checks in the copy() method (file_exists, etc) but this will definitely get you going and is flexible.
// Instantiate, passing the array of names and the directory you want copied
$c = new CopyDirectory(['London', 'New-York', 'Seattle'], 'location/of/your/directory/');
// Call copy() to copy the directory
$c->copy();
/**
* CopyDirectory will iterate over all the files in a given directory
* copy them, and rename the file by appending a given name
*/
class CopyDirectory
{
private $imageNames; // array
private $directory; // string
/**
* Constructor sets the imageNames and the directory to duplicate
* #param array
* #param string
*/
public function __construct($imageNames, $directory)
{
$this->imageNames = $imageNames;
$this->directory = $directory;
}
/**
* Method to copy all files within a directory
*/
public function copy()
{
// Iterate over your imageNames
foreach ($this->imageNames as $name) {
// Locate all the files in a directory (array_slice is removing the trailing ..)
foreach (array_slice(scandir($this->directory),2) as $file) {
// Generates array of path information
$pathInfo = pathinfo($this->directory . $file);
// Copy the file, renaming with $name appended
copy($this->directory . $file, $this->directory . $pathInfo['filename'] . '-' . $name .'.'. $pathInfo['extension']);
}
}
}
}
You could use a regular expression to build the new filenames, like this:
$fromFolder = 'Images/folder/';
$fromFile = 'service.jpg';
$toFolder = 'Images/folder/';
$imgnames = array('London', 'New-York','Seattle');
foreach ($imgnames as $imgname) {
$newFile = preg_replace("/(\.[^\.]+)$/", "-" . $imgname . "$1", $fromFile);
echo "Copying $fromFile to $newFile";
copy($fromFolder . $fromFile, $toFolder . $newFile);
}
The above will output the following while copying the files:
Copying service.jpg to service-London.jpg
Copying service.jpg to service-New-York.jpg
Copying service.jpg to service-Seattle.jpg
In the above code, set the $fromFolder and $toFolder to your folders, they can be the same folder, if so needed.

php get list of files as array, output 1 random file name with extension.

So what i am trying to do is get a list of text files from a directory.
take that list and randomly choose 1 file.
then take that file and print out the contents. now i did this a few years back. but can't find my old script. i tried what i have below just to print out a file name.. but event that is not working?
$path = '/seg1';
$files = scandir($path);
$seg = array ( $files );
$rand_keys = array_rand($seg, 1);
print $rand_keys;
Would love some new eyes on this as well as any input.
/*** Search All files in Dir. with .txt extension ***/
foreach (glob('./seg1/*.txt') as $filename)
{
$myFiles[] = $filename;
/*** Array of file names **/
}
/*** Total count of files ***/
$max=sizeof($myFiles);
/*** Select a Random index for Array with Max limit ***/
$fileNo=rand(0, $max);
/*** Path of the Random file to Access ***/
$file=$myFiles[$fileNo];
/*** Get the content from Text file ****/
$data = file_get_contents($file, true);
As your variable naming suggests, you randomly select one key out of the array; try getting the value by
$filename = $seg[$rand_keys];
$path = '/seg1';
$files = scandir($path));
if($files)
echo file_get_contents($files[mt_rand(2,count($files))]);
Recommend you use glob so you only get files you want, this excludes system directories like . and ..
foreach (glob("seg1/*.txt") as $filename) {
$seg[] = $filename;
}
Or an even simpler solution:
$rand_keys = array_rand(glob("seg1/*.txt"), 1);

Adding 1 to the image name every time a new image is uploaded to folder

I am a newbie at PHP and I'm learning.
I've made a basic script where you can upload an image to a director on the server. I want the image names to get a number at the end so that the name won't be duplicated.
This is my script to add 1 to the name (I'm really bad at "for loops"):
for(x=0; $imageName => 50000; x++){
$imageFolderName = $imageName.$x;
}
Please tell me if I'm doing this totally wrong.
Adding to Niet's answer, you can do a foreach loop on all the files in your folder and prepend a number to the file name like so:
<?
$directory = 'directory_name';
$files = array_diff(scandir($directory), array('.', '..'));
$count = 0;
foreach($files as $file)
{
$count++;
rename($file, $count.'-'.$file);
}
?>
Alternatively you could rename the file to the timestamp of when it was uploaded and prepend some random characters to the file with the rand() function:
<?
$uploaded_name = 'generic-image.jpeg';
$new_name = time().rand(0, 999).$uploaded_name;
?>
You'll need to handle and move the uploaded files before and after the rename, but you get the general gist of how this would work.
Here's a potential trick to avoid looping:
$existingfiles = count(glob("files/*"));
// this assumes you are saving in a directory called files!
$finalName = $imageName.$existingfiles;

Categories