Real Media Library folder structure


In the above screenshot you can see a folder structure built with premium plugin Real Media Library. Now I want to create an extension plugin which can organize the folder structure into physical folder structure - RML is only visual structure.

Update #2 (2017-01-27): Check out the answer!

Have a look at Physical organization of wordpress media library (Real Media Library plugin) where I have created a free extension plugin.

Update #1 (2016-12-14): The first success: Custom thumbnail upload folder

Now, I have created another plugin Real Thumbnail Generator, whichs allows you to create custom thumbnail upload folder. Just have a look at this screenshot:

Real Thumbnail Generator Upload folder

Why custom thumbnail folders? Custom thumbnail folders are easier to maintain, because here, we do not need to maintain the database update URLs because the thumbnails are still in the same location (which is still not changed by the RML extension).

If you want to learn more about the custom thumbnail generator, you can have a look at this thread, where I have explained a technical approach Each custom image size in custom upload directory? .

Please keep on this thread, because the beginning of 2017 I will continue the development of the RML extension which allows synchronization between RML and the server uploads folder. The extension is also compatible with Real Thumbnail Generator plugin, so there should be the database update.

Original post

My extension goal.

At the moment I am in the folder "/ Unorganized", that means it is the folder /wp-content/uploads/. When I move the file (as you can see in the screenshot) to the folder PDFs/SubDir the file is in the visual folder. Now my extension detects the different folder to the physical one and shows a little "button" which allows the user to move it physically, too:

Button to physix it

The user now clicks on the button "Physix it!" and the file should be moved to /wp-content/uploads/pdfs/subdir/Another-Doc.pdf. I have created the move process already: I read out all media files for this attachment (inclusive thumbnails for images) and use the php function rename($old_file, $new_file) together with WP function wp_mkdir_p(). The GUID in the wp_posts table and the meta data in wp_postmeta is changed, too. When all files are moved, i call the action:

do_action('RML/Physix/Moved', $meta, $id);
// $meta = Infos about the move process, see above screenshot
// $id = The attachment ID

$meta is an array:

enter image description here

The key "rename" contains all the rename processes (for example here can be the thumbnail files for images).

The problem: Guarantee plugin compatibility.

The main problem (if it is) of WordPress media library is, that many plugins save the references to images with full URLs instead of the attachment ID. That means, there are MySQL tables with columns that contains a URL to the given file. How can i guarantee that ALL references are up-to-date with the physical folders? I think it is impossible.

One possible approach.

I hook into the action and update the standard tables like wp_post->post_content, ... with a recursive REPLACE-statement in SQL.

 * When a attachment is moved.
 * @hooked RML/Physix/Moved
function physix_moved($meta, $id) {
    $rename = $meta["rename"];

    // Prepare array for recursive REPLACE
    $arr = array();
    foreach ($rename as $value) {
        $arr[] = array($value["old_url"], $value["new_url"]);
    $rec = $this->recReplace($arr, "post_content"); // function is already finished

The $rec variable is now a REPLACE-Statement:

REPLACE(post_content, 'https://example.io/wp-content/uploads/Another-Doc.pdf', 'https://example.io/wp-content/uploads/pdfs/subdir/Another-Doc.pdf')

By the way: For an image (testimage.jpg) with all thumbnail files it can look like this:

REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(post_content, 'https://example.io/wp-content/uploads/testimage-750x350.jpg', 'https://example.io/wp-content/uploads/pdfs/subdir/testimage-750x350.jpg'), 'https://example.io/wp-content/uploads/testimage-1170x855.jpg', 'https://example.io/wp-content/uploads/pdfs/subdir/testimage-1170x855.jpg'), 'https://example.io/wp-content/uploads/testimage-256x187.jpg', 'https://example.io/wp-content/uploads/pdfs/subdir/testimage-256x187.jpg'), 'https://example.io/wp-content/uploads/testimage-1024x748.jpg', 'https://example.io/wp-content/uploads/pdfs/subdir/testimage-1024x748.jpg'), 'https://example.io/wp-content/uploads/testimage-300x219.jpg', 'https://example.io/wp-content/uploads/pdfs/subdir/testimage-300x219.jpg'), 'https://example.io/wp-content/uploads/testimage-150x150.jpg', 'https://example.io/wp-content/uploads/pdfs/subdir/testimage-150x150.jpg'), 'https://example.io/wp-content/uploads/testimage.jpg', 'https://example.io/wp-content/uploads/pdfs/subdir/testimage.jpg')

But what happens, if it is a serialized string (JSON) in the database table? So it looks like { "image": "http:\/\/example.io\/wp-content\/uploads\/Another-Doc.pdf" }. What must i add to the REPLACE-Statement?

The REPLACE-Statement can now be used through all MySQL tables which contains image URLs. I thought about to create a filter array where plugins can add their tables and my extension do the rest:

$tables = apply_filters("RML/Physix/Moved/Tables", array( // TODO: use $wpdb->prefix
    "wp_posts" => array("post_excerpt", "post_content"),
    "wp_postmeta" => array("meta_value")

The "move" log

I want to create a "log" where users can undo moves. If a user see, a image is broken (for example in Slider Revolution plugin), he can undo the move to the original folder.

What do you think about that idea? Is there a better solution? I hope i have explained all in a nice way!

  • 9
    You're not meant to see the folder structure underlying attachments, in a lot of cases there is none ( perhaps the files aren't even on the server? S3 AWS CDN etc ), WordPress deals in attachment posts, not attachment files, and moving them around on a server is counterproductive. You would be better doing this with a custom taxonomy and rewrite rules that trigger a redirect
    – Tom J Nowell
    May 15, 2016 at 13:44
  • 5
    Whilst this is an excellent question in terms of clarity/quality (+1 for effort), ultimately we're dealing with a 3rd party plugin here, which is considered off-topic - I don't think anyone is going to be able to "quickly" help you without getting seriously invested in RML. May 15, 2016 at 14:26
  • @TheDeadMedic Yes that is true. But i asked the question the way, that you know how it works with the actions in RML. This question is not RML specific, it is more Database specific - how to solve the problem with the url replacement. May 15, 2016 at 14:30
  • 2
    And another +1 for effort – wish we would have more of such questions … like we had in the early days. Anyway, the main problems are outlined above. To make your point: Could you please file an edit and explain the reasoning for what you are trying? So far it does not make any sense to perform those filesystem tasks.
    – kaiser
    May 17, 2016 at 22:32
  • How did you go with this @MatthiasGünter? Have you managed to find a solution?
    – Tim Malone
    Jun 29, 2016 at 7:48

1 Answer 1


Free solution extension "Physical Custom Upload Folder"

A long time ago I started to open this thread and now there is a usable extension plugin for Real Media Library which allows you to physically manage your uploads folder.

enter image description here

Check out this plugin: https://wordpress.org/plugins/physical-custom-upload-folder/

Do you know the wp-content/uploads folder? There, the files are stored in year/month based folders. This can be a very complicated and mass process, especially when you are working with a FTP client like FileZilla.

Moving already uploaded files: This plugin does not allow to move the files physically when you move a file in the Real Media Library because WordPress uses the URL's in different places. It is very hard to maintain such a process. So this only works for new uploads.

Not the answer you're looking for? Browse other questions tagged or ask your own question.