0

I am developing a site that uses WooCommerce & WordPress to show a fair amount (10,000+) products, and can't accommodate the size of all the images for the products. So, I'm leaving the images on their CDN, and making all the image attachments references to the external URLs.

This required a bit of hacking, as WooCommerce/WordPress will try to take the images and upload them and set the attachment URL to a local relative path (eg, 2018/02/), and then when the images are called later on the site, the wp_get_attachment_url will add the uploads directory to the base image, giving something like site.com/wp-content/uploads/2018/02/whatever.jpg.

Basically what I've done to make this all pan out is

  1. Stop WordPress from running the wp_generate_attachment_metadata by setting it to return true as soon as the function is called, which prevents the image from being downloaded and from being copied into the uploads directory.
  2. Upload the products from a CSV
  3. Run a MySQL query to copy the woocommerce source image URL on to the attachment location
  4. Override wp_get_attachment_url to not append the uploads directory to attachment images

Essentially, a couple of 1 line changes to the WordPress core. Which is bad, because any time in the future when the site updates it'll just bork the changes.

Is there a healthier way to approach this?

  • Do you want to prevent any attachments from being uploaded to your WP installation? Do you want to allow uploads and have the attachments sent to some remote URL? Do you want to keep new images/attachments both on the remote repository and on the WP uploads dir? – filipecsweb Mar 1 at 18:40
  • Do you want to prevent any attachments from being uploaded to your WP installation? In the case for this site, that's fine, yes. Do you want to allow uploads and have the attachments sent to some remote URL? It isn't necessary, no. I just need the attachments to be external URLs. Do you want to keep new images/attachments both on the remote repository and on the WP uploads dir? I don't need that, no. Just the remote repository is fine. If I want anything I can just use the theme itself for image uploads. – Brettins Mar 1 at 18:46
  • Well, I'm not sure, but it seems the most reasonable thing to do is just make use of wp_get_attachment_image_src filter (developer.wordpress.org/reference/hooks/…). You could make this work as long as your hacking is only preventing new images from being uploaded to the uploads dir (I mean, the file itself). The wp media library should still list new posts of the post type attachment. Did you get it? If you think it's a good idea I can add an answer. – filipecsweb Mar 1 at 19:02
  • Potentially. You're saying modify all the WooCommerce templates where an image shows to use wp_get_attachment_image_src instead of using the wp_get_attachment_url? Definitely would be time consuming but would be a safer approach than modifying the core files. – Brettins Mar 2 at 22:59
  • No need for replacements. wp_get_attachment_url also has a filter - codex.wordpress.org/Plugin_API/Filter_Reference/…. – filipecsweb Mar 3 at 0:01
0

Pay attention to the comments along the snippet.

<?php
/**
 * Filters the attachment URL.
 *
 * @param   string $url    URL for the given attachment.
 * @param   int    $att_id Attachment post ID.
 *
 * @return  string  $url Custom URL for the given attachment.
 */
function wp_get_attachment_url_callback( $url, $att_id ) {
    // Instead of keeping full path we actually need just 'wp-content/uploads'.
    // And we do this the right way, dynamically, calling functions and constants.
    $uploads_dir         = wp_get_upload_dir()['basedir'];
    $partial_uploads_dir = str_replace( ABSPATH, '', $uploads_dir );

    // Check if attachment file is in WordPress uploads directory.
    if ( strpos( $url, $partial_uploads_dir ) === false ) {
        return $url;
    }

    // Just for reference, until now, the $url is still something like:
    // http://example.com/wp-content/uploads/2019/03/image.jpg

    /**
     * @TODO    Define the right CDN URL here.
     */
    $new_site_url = 'http://cdn-domain.com';
    $pattern      = get_site_url();
    $url          = preg_replace( "#$pattern#", $new_site_url, $url );

    // Again, just for reference, now the $url looks like:
    // http://cdn-domain.com/wp-content/uploads/2019/03/image.jpg

    return $url;
}

add_filter( 'wp_get_attachment_url', 'wp_get_attachment_url_callback', 999, 2 );

I hope it enlightens you so you can achieve your goal.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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