How to Get Shared Media in Code
If you’re a developer and using my Multisite Shared Media Library plugin on a website you’re developing, or you just want to create an integration between your WordPress plugin and mine, either way this guide should be helpful for you.
How shared media are stored on sub-sites
| Where shared media is used | How it is stored |
|---|---|
| Post content | When you insert a global media file into the post content, usually it is just an HTML tag <img /> which points to the original file on the network library site. |
| Featured images / Product Images | A placeholder ID that points to the original file. |
| Custom fields | If a custom field stores a media file ID, it is not going to be an original shared media file ID but its placeholder ID that points to the original file. |
| Options (settings pages) | If an option stores a media file ID, it is going to be a placeholder ID, not an original file ID. |
What is a placeholder anyway?
There are a lot of functions in WordPress that rely on the information about the attachments they get directly from the wp_posts database table. Most of these functions can not be hooked with switch_to_blog()/ restore_current_blog() functions.
That’s why we use placeholders – a copy of a minimum of the attachment information in the wp_posts table which points to the original file on the network library site.
When I created this logic, I was inspired by the WooCommerce plugin which uses the same idea for orders when you migrate to HPOS.
How to Get a Global Media ID?
Let’s assume that you have created a custom field or an option (on a WordPress settings page) that stores a media ID in it.
For example, a custom field like that:

But the thing is that 52 is not a global media ID – it is just a placeholder on a current sub-site that points to the global media. Of course, when you’re using get_post_meta() or get_field() functions, then you’re getting a value that is stored in the database, which, we just figured, is a placeholder ID, not an actual global media ID.
So, how to get a global media ID that we can use in the code?
Since the plugin version 1.4, you can use a rudr_sml_network_media_id filter hook in order to do that.
Below are the code examples:
echo apply_filters( 'rudr_sml_network_media_id', get_post_meta( $post_id, 'my_image', true ) );The same code with a little bit more explanation:
// let's get a current post ID
$post_id = get_the_ID();
// a placeholder of a global media file which is stored in a custom field
$placeholder_id = get_post_meta( $post_id, 'my_image', true );
// just pass the placeholder ID into the filter hook and get a global media ID
$global_media_id = apply_filters( 'rudr_sml_network_media_id', $placeholder_id );How to Get Global Media Information and/or Display the Media
Using WordPress functions
Some WordPress functions can recognize whether a placeholder or a real attachment ID is passed to them, and return an appropriate media file, below is the list of these functions:
get_attached_file(),wp_get_attachment_image(),wp_get_attachment_url(),wp_get_attachment_image_src().
Using switch_to_blog()
But in some cases, you need to switch to the network library website manually in order to get all the media information you need. One of these cases – when working with attachment custom fields.
// use the 'rudr_sml_network_media_id' hook if it is a placeholder ID
$global_media_id = 123;
// for example, let's say it is ID = 1
$network_media_library_id = 1;
// switch to the network library site
switch_to_blog( $network_media_library_id );
// do everything you need to do here, for example let's get attachment alt text
$alt = get_post_meta( $global_media_id, '_wp_attachment_image_alt', true );
// return to the current site
restore_current_blog();
// display (or whatever) the information you got
echo 'Alt text is: ' . $alt; // probably using the esc_html() function won't hurt