File


Listing Files

The File utility class has several methods, some are static, while others are not. Listing files using the File::list_files() method is the first thing you can do with this class. This method retrieves a list of all files stored within a specific directory, relative to your app's base directory. This can be useful for getting specific files to download or something else.

use Zap\Core\Utils\File;
$files = File::list_files('path/to/directory');
//loop through the returned array to access file names and paths
foreach ($files as $file) {
 echo "File Name: " . $file['name'] . "\n";
 echo "File Path: " . $file['path'] . "\n";
}

First, the method will scan a given target directory and filters out directory navigational dots (like . or .. ) automatically. Then, it returns an array containing the plain file name and URL-encoded full file path for every file in the given directory.

By default, File class operations are restricted to allowed_roots defined in the /config/app.php. When this class is used to list file located in a directory unlisted in the allowed_roots, it will return:

//trying to list files in the app/Controllers directory
Array
(
    [error] => 1
    [message] => Directory not found or access denied (Invalid path).
    [data] => Array
        (
        )

)
1

It is important to know that the files listed by using this method are for server-side file operations like getting the file content, deleting the file, appending content to the file, etc. They are not directly downloadable by web clients.

Get File Content

The method File::get() can be used to retrieve the raw string contents of a file licated within allowed directories. It works just like the previous method, where a request is validated against allowed roots and directory traversal is blocked

The following content is retrieved from the /storage/logs/test.log:

use Zap\Core\Utils\File;
// Retrieve contents of a storage file
$result = File::get(BASE_PATH . '/storage/logs/test.log');
//$result is an array with keys 'error', 'message', and 'data'
Array
(
    [error] => 0
    [message] => File read successfully.
    [data] => This is from test.log
)
1

Writing File Contents

The put() method writes string data to a file at the specified path, overwriting any existing contents.

This method inspects the parent directory structure and recursively creates missing folders with 0775 permissions prior to writing. It also Wraps underlying file writing calls to handle failures gracefully without throwing unhandled PHP exceptions.

Pass the destination target path and the string payload to File::put(). Check the returned error key (0 on success, 1 on failure) to verify if the file was saved.

use Zap\Core\Utils\File;
$path = BASE_PATH . '/storage/exports/report.txt';
$data = "Status: Completed\nTimestamp: " . date('Y-m-d H:i:s');
$result = File::put($path, $data);
if ($result['error'] === 0) {
 echo "Success: " . $result['message'];
} else {
 echo "Error: " . $result['message'];
}

Appending File Contents

The File::append() method adds string data to the end of an existing file, creating the file if it does not already exist. This can be useful for logging into text files.

As the name suggests, it preserves existing file contents while adding new data at the end. When it does not find the target file, it creates one, ensuring that the operation always succeeds.

Provide the target file path and the string data to be appended File::append(). Check the returned error key to determine if the operation was successful.

use Zap\Core\Utils\File;
$logPath = BASE_PATH . '/storage/logs/activity.log';
$logEntry = '[' . date('Y-m-d H:i:s') . '] User logged in from IP 127.0.0.1';
$result = File::append($logPath, $logEntry);
if ($result['error'] === 0) {
echo "Log entry recorded.";
} else {
echo "Error: " . $result['message'];
}

Deleting Files

The File::delete_file() method safely removes a target file from disk after verifying path permissions.

As with get(), put(), and append(), it prevents path traversal by evaluating paths against allowed roots. This will prevent unauthorized deletion of critical system files.

Pass the target file path to File::delete_file(). Check the returned error key (0 for successful deletion, 1 for failure or access denial).

use Zap\Core\Utils\File;
$filePath = BASE_PATH . '/storage/uploads/temp_report.pdf';
$result = File::delete_file($filePath);
if ($result['error'] === 0) {
echo $result['message'];
} else {
echo "Deletion failed: " . $result['message'];
}

Retrieving Public Media

Media located within the /public/media directory (e.g., images or vides) can be retrieved by using the get_media() method. This method resolves and generates the full web URL for the retrieved media. If the media file does not exists, particularly image, it will return a default image URL for media-not-found.

Instantiate the File class and pass the relative asset path to get_media(). The method returns the full URL string to the media file or the fallback image.

use Zap\Core\Utils\File;
$file = new File();
// Get public URL for an avatar image
$imageUrl =$file->get_media('avatars/user_123.jpg');
echo '<img src="' . $imageUrl . '" alt="User Avatar" class="img-fluid">';

When used in the view, use: $imageUrl = service('Zap\Core\Utils\File')->get_media('svgs/image.svg')

Uploading File

Uplading file becomes more covenient with the $file->do_upload() method. One only need to set the upload configuration by doing init_upload() and pass the $_FILES field name to the do_upload() method.

Custom file name is supported, as well as the target location. However, for security reason, the target location is restricted to the allowed roots set in the /config/app.php. Also, by default, this class prevents users from uploading executables.

// in controller 
public function upload(Request $request) {
 $file = new File;
 $uploadPath = $request->input('target_location'); // or any form field you set
 $customFileName = $request->input('filename', null); // if empty, then null
 $maxSize = $request->input('max_size'); // or any form field you set
 $allowedTypes = ['jpg', 'png'];
 $encryptName = ($customFileName === null); //if not null, then false
 $upload_config = [
 'upload_path' => BASE_PATH . $uploadPath,
 'max_size' => $maxSize,
 'allowed_types' => $allowedTypes,
 'encrypt_name' => $encryptName
 ];
 $file->init_upload($upload_config);
 $file->do_upload('file', $customFileName); // assuming $_FILES['file'];
 return $this->json($file->get_upload_errors()); // assuming upload via AJAX
}