File is not deleted on delete record

PHPMaker 2025

I have a “file field” and the option “Delete file on update/delete” is activated.

Adding a record and updating the records works fine. But on delete the attached file is not deleted from local file storage.

Do I miss some options to check?

Thx

I cannot reproduce, make sure you use the latest template. Click Tools → Update Template to update and try again.

I did Tools → Update Template. The result is the same.

The file get added and even replaced by another file, but not deleted.

Maybe I need to add, that the project is an update from PHPMaker 2024, not from scratch.

Any other suggestion?

where is the file stored? - linux or windows filesystem
ensure if linux, the web/apache server account is the owner of the uploads folder

I tested it on both, an XAMPP Installation on Windows (for dev) and the same web/apache server where the PHPMaker 2024 version was running (for prod).

The server account is the owner of uploads folder and only the owner has write privilege which means, that it can add files and replace files. But why not delete files? I can’t see that privileges on the storage system are the problem.

Any other suggestions?

interesting…
sorry as well… i’m still on v2024, so all of this may be inapplicable to v2025

is the actual record in the table removed?

we have a similar issue, haven’t resolved it yet When deleting a record… the file is deleted, but the record is not, even though it said it was… this is happening with any tables that have “attachments”.
while debugging, we added this to the delete page:

// Page Load event
function Page_Load()
{
    $this->UseTransaction = false;
}

which resolved the issue. but turned off transactions… thing is the table has no other tables or processing that would use transactions.

give it a try, just to rule out…

and in your modules main file:
routine:

    // Delete uploaded files
    public function deleteUploadedFiles($row)
    {
        $this->loadDbValues($row);
        $this->DocumentAttachments->OldUploadPath = $this->DocumentAttachments->getUploadPath(); // PHP
        $oldFiles = EmptyValue($row['DocumentAttachments']) ? [] : [$row['DocumentAttachments']];
        foreach ($oldFiles as $oldFile) {
            if (file_exists($this->DocumentAttachments->oldPhysicalUploadPath() . $oldFile)) {
                @unlink($this->DocumentAttachments->oldPhysicalUploadPath() . $oldFile);
            }
        }
    }

try to step through this and see if the function has the correct file path and filename to be removed and if there are any errors at the unlink function (remove the @, see if it throws an error).

not sure if any of this helps, good luck

Thx for this.

Yes the actual record in the table is removed.

I will definitely dive into this topic. Meanwhile I found out that in 2025 @unlink has been replaced by DeleteFile() which probably comes from one of the libraries, maybe FlySystem?

Here’s the new code:

    // Delete uploaded files
    public function deleteUploadedFiles(array $row)
    {
        $this->loadDbValues($row);
        $this->Dokument->OldUploadPath = $this->Dokument->getUploadPath(); // PHP
        $oldFiles = IsEmpty($row['Dokument']) ? [] : [$row['Dokument']];
        foreach ($oldFiles as $oldFile) {
            if (FileExists($this->Dokument->uploadPath() . $oldFile)) {
                DeleteFile($this->Dokument->uploadPath() . $oldFile);
            }
        }
    }

Maybe somebody already knows something about this. The trick with "UseTransaction = false" points to the problem of deleting a file while there is still a handle to the file open.

Hello, I tested the trick with

$this->UseTransaction = false;

Unfortunately, it does’nt work. I didn’t do a full debug, though.

What would be the easist way to debug whether the DeleteFile Command ist executed correctly or not?

Any hint is appreciated. Thx

Turn on debug, not sure if it will display any unlink/delete errors.

what’s the code in the deletefile() function look like?

You may read Debugging, it is simple with v2025.

I found the problem. Don’t know how to solve it for the moment.

It’s this code in the modules main file:

// Delete uploaded files
    public function deleteUploadedFiles(array $row)
    {
        $this->loadDbValues($row);
        $this->Dokument->OldUploadPath = $this->Dokument->getUploadPath(); // PHP
        $oldFiles = IsEmpty($row['Dokument']) ? [] : [$row['Dokument']];
        foreach ($oldFiles as $oldFile) {
            if (FileExists($this->Dokument->uploadPath() . $oldFile)) {
                DeleteFile($this->Dokument->uploadPath() . $oldFile);
            }
        }
    }

this “$this->Dokument->getUploadPath()” returns the path of the field setting which is “files/subdir”.

But it tries to delete the file from “$this->Dokument->uploadPath()” instead. I can’t see where I made a config error.

Any hints to make the code delete file from the correct path?

What is “subdir”? Did you try to use a dynamic subfolder by code? Or are you using a local file system root which is not "."? (If it is ".", uploadPath() should return same value as getUploadPath().)

Click Tools → Update Template to update to latest (updated) template and try again.

I did a Tools → Update Template. Packages where up-to-date.

“subdir” is a string like this

“files/subdir”

and there are no dynamic subfolders by code and there is no bespoke code at all for this module.

this is the code I used to test:

// Delete uploaded files
    public function deleteUploadedFiles(array $row)
    {
        $this->loadDbValues($row);
        $this->Dokument->OldUploadPath = $this->Dokument->getUploadPath(); // PHP
        $oldFiles = IsEmpty($row['Dokument']) ? [] : [$row['Dokument']];
        foreach ($oldFiles as $oldFile) {
            Log("uploadPath() = " . $this->Dokument->uploadPath());
            Log("getUploadPath() = " . $this->Dokument->getUploadPath());
            Log("DOCUMENT_ROOT = " . $_SERVER['DOCUMENT_ROOT']);
            if (FileExists($this->Dokument->uploadPath() . $oldFile)) {
                DeleteFile($this->Dokument->uploadPath() . $oldFile);
            }
        }
    }

and this is what I get in the log file:

[2025-01-03T08:19:34.216935+00:00] log.DEBUG: uploadPath() = files/ [] []
[2025-01-03T08:19:34.220218+00:00] log.DEBUG: getUploadPath() = files/subdir [] []
[2025-01-03T08:30:55.653601+00:00] log.DEBUG: DOCUMENT_ROOT = C:/xampp/htdocs [] []

uploadPath() returns the value in the project setting.
getUploadPath() returns the string in field setting.

So the code wants do delete the file in the wrong directory (files/ instead of files/subdir).

As for the root question, I don’t understand what you mean by system root. Anyway I did not change anything on the system level and the problem occurs on both XAMPP for Windows (see the log) and an Ubuntu installation as well.

With XAMPP the project does not execute in the root directory but in a subdirectory. So the physical path to the file is

C:/xampp/htdocs/project/files/subdir

Out of curiosity I tracked the value of

$this->Dokument->uploadPath()

a little bit deeper.

If I add a record uploadPath() is called in total 11 times. 8 times it returns the global config ‘/files’ and 3 times it returns the field setting ‘files/subdir’.

If I delete a record uploadPath() is called 10 times and returns 10 times the global ‘config /files’.

If I replace the file in an existing record uploadPath() is called 17 times. 12 times it returns the global config ‘/files’ and 5 times it returns the field setting ‘files/subdir’.

this seems to be a more complex mechanism. not sure what to do with this without tracking even deeper. Maybe there are some ideas around.

It is not related to number of times it is called. It depends on whether or not the UploadPath property of the field is set in the context. You better click Tools → Update Template as Webmaster suggested to update the latest template and try again.

I already did Update Template. The problem persists. The UploadPath property is set in the field settings as “files/subdir”

What else can I try?

I cannot reproduce. If you are registered user of v2025, you better send your project files and the required info to support for testing.

Problem solved.

What I did (before asking for support). I removed the content of the accept property (.pdf) in the field setup. And everything went well. I then added the same property (.pdf) again and it still worked well.

The origin of the problem was probably in the project file.