Support Forum
Support › Meta Box Group › Trouble getting file url of file attachment in cloneable groupResolved
Hi I am trying to make an attached files drop down button for WooCommerce Products. Everything is working fine but I am having trouble getting the file url to place in a link. Here are my registered fields:
add_filter( 'rwmb_meta_boxes', 'prefix_register_file_attachments' );
function prefix_register_file_attachments( $meta_boxes ) {
$meta_boxes[] = array(
'id' => 'File_Attachments',
'title' => esc_html__( 'File Attachments' ),
'post_types' => array( 'product' ),
'context' => 'advanced',
'priority' => 'default',
'autosave' => 'true',
'fields' => array(
array(
'id' => 'file_attachments',
'type' => 'group',
'group_title' => 'Attachment {#}',
'collapsible' => true,
'save_state' => true,
'clone' => true,
'sort_clone' => true,
'fields' => array(
array(
'id' => 'file_name',
'type' => 'text',
'name' => 'File Name',
),
array(
'id' => 'attachment',
'type' => 'file_advanced',
'name' => esc_html__( 'Attach File' ),
'desc' => esc_html__( 'Upload your pdf files to show on single product page' ),
'force_delete' => false,
),
),
),
),
);
return $meta_boxes;
}
These work fine in the backend. Here is my code to display the results:
add_action( 'woocommerce_after_add_to_cart_button', 'product_download_button', 5 );
function product_download_button() { ?>
<div class="dropdown">
<button class="product-downloads-button" onclick="return false;">DOWNLOADS
<i class="fa fa-caret-down"></i>
</button>
<div class="dropdown-content"> <?php
$file_attachments = rwmb_meta( 'file_attachments' );
if ( ! empty( $file_attachments ) ) {
foreach ( $file_attachments as $file_attachment ) {
$file_name = isset( $file_attachment['file_name'] ) ? $file_attachment['file_name'] : '';
$file_info = get_attached_file( $file_attachment['attachment'] );
echo '<a href="' . $file_info['url'] . '" target="_blank" rel="noopener noreferrer">' . $file_name . '</a>';
}
} ?>
</div>
</div>
<?php }
The $file_name returns just fine but when I turned on WP_DEBUG it returns:
Notice: Undefined index: attachment
for this line:
$file_info = get_attached_file( $file_attachment['attachment'] );
Could you please advise?
sorry here is the code:
add_filter( 'rwmb_meta_boxes', 'prefix_register_file_attachments' );
function prefix_register_file_attachments( $meta_boxes ) {
$meta_boxes[] = array(
'id' => 'File_Attachments',
'title' => esc_html__( 'File Attachments' ),
'post_types' => array( 'product' ),
'context' => 'advanced',
'priority' => 'default',
'autosave' => 'true',
'fields' => array(
array(
'id' => 'file_attachments',
'type' => 'group',
'group_title' => 'Attachment {#}',
'collapsible' => true,
'save_state' => true,
'clone' => true,
'sort_clone' => true,
'fields' => array(
array(
'id' => 'file_name',
'type' => 'text',
'name' => 'File Name',
),
array(
'id' => 'attachment',
'type' => 'file_advanced',
'name' => esc_html__( 'Attach File' ),
'desc' => esc_html__( 'Upload your pdf files to show on single product page' ),
'force_delete' => false,
),
),
),
),
);
return $meta_boxes;
}
add_action( 'woocommerce_after_add_to_cart_button', 'product_download_button', 5 );
function product_download_button() { ?>
<div class="dropdown">
<button class="product-downloads-button nectar-button large regular accent-color regular-button" onclick="return false;">DOWNLOADS
<i class="fa fa-caret-down"></i>
</button>
<div class="dropdown-content"> <?php
$file_attachments = rwmb_meta( 'file_attachments' );
if ( ! empty( $file_attachments ) ) {
foreach ( $file_attachments as $file_attachment ) {
$file_name = isset( $file_attachment['file_name'] ) ? $file_attachment['file_name'] : '';
$file_info = get_attached_file( $file_attachment[‘attachment’] );
echo '<a href="' . $file_info['url'] . '" target="_blank">' . $file_name . '</a>';
}
} ?>
</div>
</div>
<?php }
Hi, you need to check if the file is uploaded in your group, like this:
if ( isset( $file_attachment['attachment'] ) ) {
$file_info = get_attached_file( $file_attachment[‘attachment’] );
echo ...
}
Hi thanks for the response. The if statement is a nice touch. I tried that out and now I am not getting a php error, but the url is still not returning. Here is the updated code:
add_action( 'woocommerce_after_add_to_cart_button', 'product_download_button', 5 );
function product_download_button() { ?>
<div class="dropdown">
<button class="product-downloads-button nectar-button large regular accent-color regular-button" onclick="return false;">DOWNLOADS
<i class="fa fa-caret-down"></i>
</button>
<div class="dropdown-content"> <?php
$file_attachments = rwmb_meta( 'file_attachments' );
if ( ! empty( $file_attachments ) ) {
foreach ( $file_attachments as $file_attachment ) {
$file_name = isset( $file_attachment['file_name'] ) ? $file_attachment['file_name'] : '';
if ( isset( $file_attachment['attachment'] ) ) {
$file_info = get_attached_file( $file_attachment['attachment'] );
echo '<a href="' . $file_info['url'] . '" target="_blank">' . $file_name . '</a>';
}
}
} ?>
</div>
</div>
<?php }
and here is what the resulting link is on the frontend:
<a href="" target="_blank" rel="noopener noreferrer">Spec Sheet</a>
When I echo $file_info;
nothing is returned so I'm guessing $file_info = get_attached_file( $file_attachment['attachment'] );
is not actually retrieving anything for some reason...
Hi,
The function you use get_attached_file
is not correct. It returns the file path instead of array, see the docs.
To get the file URL, you can use wp_get_attachment_url
file.
if ( isset( $file_attachment['attachment'] ) ) {
$file_url = wp_get_attachment_url( $file_attachment['attachment'] );
echo '<a href="' . $file_url . '" target="_blank">' . $file_name . '</a>';
}
Hi Thanks again, unfortunately this is still not returning anything for $file_url
. echo $file_url;
also returns nothing, but it passes the if loop and outputs the html and the file name fine, so it does know that there is an attachment, it just can't get any info from it. Even if get_attached_file()
was the wrong use case in the previous example, it still should have returned a value, but it didn't, correct?
If it outputs nothing, probably the file is already deleted from the WordPress admin (maybe someone has deleted the file in the Media Library). If that's the case, you can make a better check with this:
if ( isset( $file_attachment['attachment'] ) && get_attached_file( $file_attachment['attachment'] ) ) {
$file_url = wp_get_attachment_url( $file_attachment['attachment'] );
echo '<a href="' . $file_url . '" target="_blank">' . $file_name . '</a>';
}
Unfortunately that is not working either. When I tried that nothing shows up in the dropdown. The file is attached and it exists in the media library. I tried removing it and re-attaching it also.
I did a test with the code using the file attachment only not in a group like this and it works fine:
add_action( 'woocommerce_after_add_to_cart_button', 'product_download_button_test', 5 );
function product_download_button_test() { ?>
<div class="dropdown">
<button class="product-downloads-button nectar-button large regular accent-color regular-button" onclick="return false;">DOWNLOADS
<i class="fa fa-caret-down"></i>
</button>
<div class="dropdown-content"> <?php
$file_attachments = rwmb_meta( 'attachment_test' );
if ( ! empty( $file_attachments ) ) {
foreach ( $file_attachments as $file_attachment ) {
if ( isset( $file_attachment ) ) {
$file_url = ( $file_attachment['url'] ); ?>
<a href="<?php echo $file_url; ?>" target="_blank"><?php echo $file_attachment['name']; ?> </a>
<?php }
}
} ?>
</div>
</div>
<?php }
But when it seems as soon as the file attachment is in a group, I can return any info from it. This is the same only with the file attachment in a group:
add_action( 'woocommerce_after_add_to_cart_button', 'product_download_button_test', 5 );
function product_download_button_test() { ?>
<div class="dropdown">
<button class="product-downloads-button nectar-button large regular accent-color regular-button" onclick="return false;">DOWNLOADS
<i class="fa fa-caret-down"></i>
</button>
<div class="dropdown-content"> <?php
$file_attachments = rwmb_meta( 'attachment_test' );
if ( ! empty( $file_attachments ) ) {
foreach ( $file_attachments as $file_attachment ) {
if ( isset( $file_attachment ) ) {
$file_url = ( $file_attachment['url'] ); ?>
<a href="<?php echo $file_url; ?>" target="_blank"><?php echo $file_attachment['name']; ?> </a>
<?php }
}
} ?>
</div>
</div>
<?php }
I get an error "undefined index url" and when I try to use wp_get_attachment_url()
or get_attached_file()
it returns nothing.
It seems like whatever I try to do to get info from $file_attachment['attachment']
, or when a file attachment is in a group, it is always empty.
Sorry I repeated that code block, Here is the second one properly:
add_action( 'woocommerce_after_add_to_cart_button', 'product_download_button', 5 );
function product_download_button() { ?>
<div class="dropdown">
<button class="product-downloads-button nectar-button large regular accent-color regular-button" onclick="return false;">DOWNLOADS
<i class="fa fa-caret-down"></i>
</button>
<div class="dropdown-content"> <?php
$file_attachments = rwmb_meta( 'file_attachments' );
if ( ! empty( $file_attachments ) ) {
foreach ( $file_attachments as $file_attachment ) {
$file_name = isset( $file_attachment['file_name'] ) ? $file_attachment['file_name'] : '';
if ( isset( $file_attachment['attachment'] ) ) {
$file_url = $file_attachment['attachment']; ?>
<a href="<?php echo $file_url['url']; ?>" target="_blank"><?php echo $file_name; ?> </a> <?php
}
}
} ?>
</div>
</div>
<?php }
I got it. We forget that the returned value of the file_advanced
field is an array! So we need to get only the first file ID.
if ( isset( $file_attachment['attachment'] ) ) {
$file_id = reset( $file_attachment['attachment']; // Get the first file only.
$file_url = wp_get_attachment_url( $file_id );
echo '<a href="' . $file_url . '" target="_blank">' . $file_name . '</a>';
}
That did it! I was wracking my brain on this trying so many different things. Thank you very much for your help!
Hi Anh,
Just following up on this. When using the code you helped fix here:
add_action( 'woocommerce_after_add_to_cart_button', 'product_download_button', 5 );
function product_download_button() {
$file_attachments = rwmb_meta( 'file_attachments' );
if ( ! empty( $file_attachments ) ) { ?>
<div class="dropdown">
<button class="product-downloads-button nectar-button large regular accent-color regular-button" onclick="return false;">DOWNLOADS
<i class="fa fa-caret-down"></i>
</button>
<div class="dropdown-content"> <?php
foreach ( $file_attachments as $file_attachment ) {
$file_name = isset( $file_attachment['file_name'] ) ? $file_attachment['file_name'] : '';
if ( isset( $file_attachment['attachment'] ) ) {
$file_id = reset( $file_attachment['attachment'] ); // Get the first file only.
$file_url = wp_get_attachment_url( $file_id );
echo '<a href="' . $file_url . '" target="_blank">' . $file_name . '</a>';
}
}
} ?>
</div>
</div>
<?php }
Even if there is no name or attachment for the file, the download button still shows on the product page even though there is nothing in it. I made another similar custom group field with a text and color picker and when I use this:
$special_colours = rwmb_meta( 'special_colours' );
if ( ! empty( $special_colours ) ) {
When there is nothing in the fields for the product nothing displays, as it should correctly. Is this maybe because as you mentioned previously that the file_advanced
is array and so if ( ! empty( $file_attachments ) ) {
still sees that the attachment
item in the group is not empty? Is there a way around this so that the download button is not displayed if there is nothing in the fields for that product?
Hi,
Because you've enabled the attribute save_state
so the file attachments always return an array $file_attachments = rwmb_meta( 'file_attachments' );
This attribute means when you add more groups but not put any name or file, it will save the last state when publishing the product. Take a look at my screenshot https://cl.ly/e883f5d356f2
Change the attribute 'save_state' => false
and refresh your site, the button will not display if there are empty fields in the first group.
Hi Long,
Thanks for the reply I gave that a shot and unfortunately it didn't work. I also took a look at some products and it looks like some are showing the special colour content while others are not even when there is no name or colour selected. Here is the colour code for reference:
add_filter( 'rwmb_meta_boxes', 'prefix_register_special_colours' );
function prefix_register_special_colours( $meta_boxes ) {
$meta_boxes[] = array(
'id' => 'Special_Colours',
'title' => esc_html__( 'Special Order Colours' ),
'post_types' => array( 'product' ),
'context' => 'advanced',
'priority' => 'default',
'autosave' => 'true',
'fields' => array(
array(
'id' => 'special_colours',
'type' => 'group',
'group_title' => 'Colour {#}',
'collapsible' => true,
'save_state' => true,
'clone' => true,
'sort_clone' => true,
'fields' => array(
array(
'id' => 'colour_name',
'type' => 'text',
'name' => 'Colour Name',
),
array(
'id' => 'special_colour',
'type' => 'color',
'name' => esc_html__( 'Special Colour' ),
'desc' => esc_html__( 'Select a colour to appear on the product page as a special order colour' ),
),
),
),
),
);
return $meta_boxes;
}
add_action( 'woocommerce_before_add_to_cart_button', 'product_special_colours', 5 );
function product_special_colours() {
$special_colours = rwmb_meta( 'special_colours' );
if ( ! empty( $special_colours ) ) {
echo '<table class="variations" cellspacing="0">
<tbody>
<tr>
<td class="label">
<label for="so_color">Special Order Colours</label>
</td>
<td class="value woo-variation-items-wrapper">
<ul class="variable-items-wrapper color-variable-wrapper">';
foreach ( $special_colours as $special_colour ) {
$colour_name = isset( $special_colour['colour_name'] ) ? $special_colour['colour_name'] : '';
if ( isset( $special_colour['special_colour'] ) ) {
$colour = isset( $special_colour['special_colour'] ) ? $special_colour['special_colour'] : '';
echo '<li class="special_colour" style="background-color: ' . $colour . ' ">
<span class="tooltip">' . $colour_name . '</span>
</li>';
}
}
echo '</ul>
</td>
<td>
<p>To order one of our special special order colours please <a href="/contact/">contact us</a>. <br> Please note that shipping of special orders can take up to 12 weeks.</p>
</td>
</tr>
</tbody>
</table>';
}
}