So actually, for posts of the type attachment
, you should use the edit_attachment
(action) hook and not save_post_attachment
:
add_action( 'edit_attachment', 'save_image_link' ); // use edit_attachment
//add_action( 'save_post_attachment', 'save_image_link' ); // not save_post_attachment
Secondly, your meta box is not currently displaying the meta value, so you should display the value in the input field, and you can use get_post_meta()
to retrieve the meta value:
<input type="text" name="image_link" id="image-link" class="postbox" value="<?php // wrapped
echo esc_attr( get_post_meta( $post->ID, 'image_link_url', true ) ); ?>">
PS: You should always sanitize/escape user-supplied and untrusted data; e.g. above I use esc_attr()
to escape the value, and you can use sanitize_text_field()
to sanitize the submitted value: sanitize_text_field( $_POST['image_link'] )
.
Sample Implementation Using get_post_gallery()
(for the [gallery]
shortcode)
This is based on the example here. And as I've mentioned before, you can use get_post_meta()
to retrieve the custom field's value (which in your case is an URL address).
// Get the gallery data (attachment IDs and URLs).
$gallery = get_post_gallery( get_the_ID(), false );
if ( $gallery ) {
foreach ( wp_parse_id_list( $gallery['ids'] ) as $i => $att_id ) {
// Get the custom link URL.
$url = get_post_meta( $att_id, 'image_link_url', true );
// Display the image. You can add other attributes later..
echo '<a href="' . esc_url( $url ) . '"><img src="' . // wrapped
esc_url( $gallery['src'][ $i ] ). '" alt=""></a> ';
}
}
UPDATE
A Better (Non-Metabox) Solution
If you want to be able to edit the custom field via the Attachment Details dialog, then you should just forget about using the meta box and instead try the following:
This part adds the custom field to the dialog:
add_filter( 'attachment_fields_to_edit', function ( $form_fields, $post ) {
$form_fields['image_link'] = array(
'label' => 'Link to image URL',
'value' => get_post_meta( $post->ID, 'image_link_url', true ),
);
return $form_fields;
}, 10, 2 );
This part saves the field as a meta data:
add_filter( 'attachment_fields_to_save', function ( $post, $attachment ) {
if ( isset( $attachment['image_link'] ) ) {
$meta_input = isset( $post['meta_input'] ) ?
(array) $post['meta_input'] : [];
$meta_input['image_link_url'] = $attachment['image_link'];
$post['meta_input'] = $meta_input;
}
return $post;
}, 10, 2 );
Note that image_link
is the form field (input
) name, whereas image_link_url
is the meta key.
And this solution also works well with the standard "Edit Media" page — from the Attachment Details dialog, you can get to that page by clicking on the "Edit more details" link.
Full code I used for testing here.
get_post_meta()
in your<input>
.get_post_meta()
but the supposed values are not loaded.