Understanding File Paths
Working with files in Trongate requires understanding three distinct concepts: relative paths (for PHP operations), absolute paths (filesystem paths), and URLs (for browser access).
Get this right, and file management becomes simple. Get it wrong, and you'll encounter "file not found" errors everywhere.
The Three Types of Paths
Before diving into Trongate's file handling, let's clarify what we mean by different path types:
Path Types Explained:
- Relative path: A path relative to an application directory (e.g.,
uploads/file.pdfor../modules/users/files/doc.pdf) - Absolute path: A complete filesystem path from root (e.g.,
/Applications/XAMPP/htdocs/myapp/uploads/file.pdf) - URL: A web-accessible address (e.g.,
https://example.com/files/doc.pdforusers_module/files/doc.pdf)
Use Relative Paths
The File module methods accept any PHP-accessible file path. However, using relative paths is recommended as it aligns with Trongate's conventions and ensures portability.
Path Compatibility Summary:
-
✅ WORKS & RECOMMENDED:
Relative paths
(
uploads/report.txt,../modules/docs/files/manual.md) -
⚠️ WORKS BUT NOT RECOMMENDED:
Absolute paths
(
/var/www/html/public/uploads/data.csv) -
❌ DOES NOT WORK:
Web URLs
(
https://example.com/downloads/log.txt,example.com/files/document.md) -
🔄 SPECIAL CASE:
_moduletrigger paths work only in browser URLs, not with File module methods
What upload() Returns
When you upload a file using the File module's method, it returns an array containing four properties with a file_path key that contains a relative path:
// Example 1: Upload to module directory
$config = [
'destination' => 'documents',
'upload_to_module' => true
];
$file_info = $this->file->upload($config);
// Returns: array(4) {
// ["file_name"]=> string(11) "report.pdf"
// ["file_path"]=> string(42) "../modules/users/documents/report.pdf"
// ["file_type"]=> string(15) "application/pdf"
// ["file_size"]=> int(245760)
// }
// Example 2: Upload to public directory
$config = [
'destination' => 'my_uploads'
];
$file_info = $this->file->upload($config);
// Returns: array(4) {
// ["file_name"]=> string(11) "report.pdf"
// ["file_path"]=> string(21) "my_uploads/report.pdf"
// ["file_type"]=> string(15) "application/pdf"
// ["file_size"]=> int(245760)
// }These relative paths are what you use with all other File module methods including; delete(), copy(), move(), read(), write(), info(), exists().
Path Construction Patterns
Understanding how paths are constructed helps you work with files stored anywhere in your application.
Module Directory Uploads
When upload_to_module is true, files are stored in the target module directory. For example:
$config = [
'destination' => 'cvs',
'upload_to_module' => true
];
$file_info = $this->file->upload($config);
// Relative path returned:
// '../modules/users/cvs/resume.pdf'When you upload a file, using the File module, a PHP array ($file_info) is automatically returned by the upload() method.
The $file_info array contains the following four properties:
'file_name'- The final, sanitized filename on disk'file_path'- The relative path to the file'file_type'- The MIME type of the file'file_size'- The file size in bytes
The value of the file_path will always be a relative_path.
In instances where you've uploaded a file to a module the value of $file_info['file_path'] will follow this pattern:
../modules/{module_name}/{destination}/{filename}Public Directory Uploads
When upload_to_module is false (or not set), files are stored in the public directory:
$config = [
'destination' => 'downloads'
];
$file_info = $this->file->upload($config);
// Relative path returned:
// 'downloads/report.pdf'In this instance, the value of $file_info['file_path'] takes the form: {destination}/{filename}
In the above example, uploaded files would be stored at:
public/downloads/<file-name>Quick Reference Table
| Storage Location | Relative Path Format | Example |
|---|---|---|
| Module directory | ../modules/{module}/{folder}/{filename} |
../modules/users/cvs/resume.pdf |
| Public directory | {folder}/{filename} |
my_uploads/image.jpg |
Reconstructing Paths from Database
A common pattern is to store the file metadata from in your database, then use the stored file_path when needed:
// During upload - store all file metadata
$file_info = $this->file->upload($config);
// Store ALL data returned by upload() for later use
$data = [
'file_name' => $file_info['file_name'],
'file_path' => $file_info['file_path'],
'file_type' => $file_info['file_type'],
'file_size' => $file_info['file_size']
];
$this->db->insert($data, 'documents');
// Later - retrieve the stored file_path
$doc = $this->db->get_where($id, 'documents');
// Use the stored file_path with File module methods
if ($this->file->exists($doc->file_path)) {
$content = $this->file->read($doc->file_path);
$this->file->delete($doc->file_path);
}Important: Always use the complete relative path when calling File module methods. Using just filenames will cause "file does not exist" exceptions.
Relative Paths vs. URLs
Here's where developers often get confused: the relative path you use for PHP operations is different from the URL you use for browser access.
For PHP Operations: Use Relative Paths
// Relative path for File module operations
$file_path = '../modules/users/documents/report.pdf';
$this->file->exists($file_path);
$this->file->read($file_path);
$info = $this->file->info($file_path);
$this->file->delete($file_path);For Browser Access: Use URLs
To let users view or download files, you need a URL that the browser can access. This is where things differ based on storage location.
Accessing Files via URL
Public Directory Files
Files in the public directory are straightforward - the relative path and URL are the same:
// Upload to public directory
$config['destination'] = 'downloads';
$file_info = $this->file->upload($config);
// Relative path for PHP:
// 'downloads/report.pdf'
// URL for browser:
// 'downloads/report.pdf'
// or with BASE_URL: https://example.com/downloads/report.pdfIn your view:
<a href="<?= BASE_URL ?>downloads/report.pdf" target="_blank">
View File
</a>Module Directory Files: The Module Assets Trigger
Files in module directories require a special URL pattern called the module assets trigger:
{module-name}_module/{subdirectory}/{filename}Example:
// Upload to module directory
$config = [
'destination' => 'uploads',
'upload_to_module' => true
];
$file_info = $this->file->upload($config);
// Relative path for PHP operations:
// '../modules/simple_uploader/uploads/document.pdf'
// URL for browser access:
// 'simple_uploader_module/uploads/document.pdf'In your view:
<a href="<?= BASE_URL ?>simple_uploader_module/uploads/document.pdf" target="_blank">
View File
</a>How the Module Assets Trigger Works
When Trongate sees _module in a URL, it automatically serves files from the corresponding module directory:
modules/
simple_uploader/
uploads/
document.pdf
report.csv
users/
files/
resume.pdf
images/
avatar.pngThese files become accessible via:
simple_uploader_module/uploads/document.pdfsimple_uploader_module/uploads/report.csvusers_module/files/resume.pdfusers_module/images/avatar.png
The Module Assets Trigger is defined in config/config.php:
define('MODULE_ASSETS_TRIGGER', '_module');You can change this trigger if needed, but do avoid naming modules with the trigger in the name (e.g., don't name a module users_module - use users instead).
For additional guidance, check out the Module Assets documentation.
Complete Example: Upload, Store in Database, and Display
This example demonstrates how to work with file paths, store file metadata in a database, and then display the data returned by the method.
1. The Controller
In this code, we upload a file, store all metadata in the database, and then redirect to a page that displays the file information retrieved from the database.
<?php
class File_demo extends Trongate {
/**
* Display the upload form
*/
public function index() {
$data['view_module'] = 'file_demo';
$data['view_file'] = 'upload_form';
$this->view('upload_form', $data);
}
/**
* Process the file upload and store in database
*
* Responsibility: Validate, upload file, store metadata, then redirect
* Uses POST-Redirect-GET pattern to prevent duplicate submissions
*/
public function submit_upload() {
// Set validation rules
$this->validation->set_rules(
'userfile',
'File',
'required|allowed_types[pdf,txt,md]|max_size[5000]'
);
if ($this->validation->run() === true) {
// Configure file upload options
$config = [
'destination' => 'uploads',
'upload_to_module' => true,
'make_rand_name' => true
];
// Upload file and get all metadata
$file_info = $this->file->upload($config);
// Store ALL data returned by upload() in database
$data = [
'file_name' => $file_info['file_name'],
'file_path' => $file_info['file_path'],
'file_type' => $file_info['file_type'],
'file_size' => $file_info['file_size']
];
$insert_id = $this->db->insert($data, 'documents');
set_flashdata('File uploaded successfully!');
// Redirect to display page with database ID
redirect('file_demo/display/' . $insert_id);
} else {
// Validation failed - show form again with errors
$this->index();
}
}
/**
* Display file metadata from database
*
* Responsibility: Retrieve file info from database and display it
*/
public function display() {
// Fetch the record ID from the URL.
$id = segment(3, 'int');
// Get file metadata from database
$doc = $this->db->get_where($id, 'documents');
if ($doc === false) {
// Record not found - send the user elsewhere.
redirect('file_demo/file_not_found');
}
// Prepare data for view using database values
$data = [
'file_name' => $doc->file_name,
'file_path' => $doc->file_path,
'file_type' => $doc->file_type,
'file_size' => $doc->file_size,
'formatted_size' => $this->format_size($doc->file_size),
'download_url' => $this->convert_to_url($doc->file_path)
];
$data['view_module'] = 'file_demo';
$data['view_file'] = 'display_file';
$this->view('display_file', $data);
}
/**
* Helper function to format file size (in controller, not view)
*/
private function format_size($bytes) {
$units = ['B', 'KB', 'MB', 'GB'];
$bytes = max($bytes, 0);
$pow = floor(($bytes ? log($bytes) : 0) / log(1024));
$pow = min($pow, count($units) - 1);
$bytes /= pow(1024, $pow);
return round($bytes, 2) . ' ' . $units[$pow];
}
/**
* Convert module file path to URL (in controller, not view)
*/
private function convert_to_url($file_path) {
if (strpos($file_path, '../modules/') === 0) {
$path_parts = explode('/', $file_path);
$module_name = $path_parts[2];
return str_replace("../modules/{$module_name}/", "{$module_name}_module/", $file_path);
}
return $file_path;
}
}The controller example above includes several lines of code dedicated to data processing.
For better organization, separation of concerns, and long-term maintainability, it is recommended to move data-handling logic into a dedicated model file.
2. The View File (display_file.php)
The view displays all file metadata retrieved from the database.
<h2>File Information</h2>
<p><strong>Stored Filename:</strong> <?= out($file_name) ?></p>
<p><strong>File Type:</strong> <?= out($file_type) ?></p>
<p><strong>Size:</strong> <?= out($formatted_size) ?></p>
<p><strong>Relative Path:</strong> <code><?= out($file_path) ?></code></p>
<p><strong>Download Link:</strong> <?= anchor($download_url, 'Download') ?></p>
<p><?= anchor('file_demo', 'Upload Another File') ?></p>Important: This example demonstrates the complete workflow:
upload()returns all four file metadata properties- All four properties are stored in the database exactly as returned
- The
file_pathfrom the database is used for all file operations - Helper functions in the controller format data for display
- The POST-Redirect-GET pattern prevents duplicate submissions
Database Schema Note: Your 'documents' table should have columns for: file_name, file_path, file_type, and file_size to store all metadata from upload().
Path Conversion Quick Reference
| Storage Location | Relative Path (for PHP) | URL (for browser) |
|---|---|---|
| Module directory | ../modules/users/files/doc.pdf |
users_module/files/doc.pdf |
| Public directory | my_uploads/doc.pdf |
my_uploads/doc.pdf |
Key Takeaways
Remember these essentials:
- File module methods expect relative paths
upload()returns four properties in an array- Store all four properties from
upload()in your database - The
file_pathproperty contains the relative path for PHP operations - Module files need path conversion for browser access:
- PHP:
../modules/module_name/... - URL:
{module}_module/...
- PHP:
- Public files use the same path for both PHP and URLs
- Format
file_sizein the controller, not the view - Use POST-Redirect-GET pattern to prevent duplicate submissions
- Always verify file existence with
exists()before operations
We're continually improving the Trongate documentation. If anything is incorrect, unclear, incomplete, or could be better, we'd genuinely appreciate your input.
Share your thoughts in the Documentation Feedback.