For anyone who needs it, my error was that I had to use
get_term_link(term-slug, taxonomy-slug)
with the term slug and the taxonomy slug, while I was using the ID and did not use the taxonomy slug.
So the final code I used is:
$terms = get_field('acf_tax_fieldname');
if( $terms ) {
foreach( $terms as $term ) {
$term_name = get_term( $term )->name;
$term_slug = get_term( $term )->slug;
$term_link = get_term_link( $term_slug , 'wp_tax_slug' );
echo "<a href='" . $term_link . "'>" . $term_name . "</a>";
}
}
Thanks for the advice, I’ve tried the following based on the example to no avail.
Featured is set at True / False field as mentioned in example 2.
function custom_post_type_archive_jobs($query) {
if ($query->is_post_type_archive(‘jobs’)) {
$query->set(‘orderby’, ‘meta_value’);
$query->set(‘meta_key’, ‘featured’);
$query->set(‘posts_per_page’, ‘-1’);
$query->set(‘order’, ‘ASC’);
}
}
add_action(‘pre_get_posts’, ‘custom_post_type_archive_jobs’, 9999);
It works lke a charm !
And donโt forget reset your query to avoid errors in future queries.
Indeed !
Thank you so much for your time celestial.
Hi, Jeremy!
You don’t need to use an ID because you are using a loop and get the current post every time.
But you need to change the value of the href attribute like this
$the_query = new WP_Query( $args );
if ( $the_query->have_posts() ) :
while ( $the_query->have_posts() ) : $the_query->the_post();
$url = parse_url( get_field( 'vibe_url') );
$btn_url = $url['host'] . $url['path'];
?>
<a class="wp-block-button__link" href="<?php the_field('vibe_url'); ?>"><?php echo $btn_url; ?></a>
<?php endwhile; ?>
<?php endif;
wp_reset_postdata(); // reset query
And don’t forget reset your query to avoid errors in future queries.
Let me know if it works correctly or not.
Hi celestial,
Thanks for your help !
I’ve tried your proposition and the text into the button is correctly displayed but the url return https://domain-name.com/vibes/Array
for every button I’ve created.
I’m using these buttons into a custom query :
<?php
$the_query = new WP_Query( $args );
if ( $the_query->have_posts() ) :
?>
<?php
while ( $the_query->have_posts() ) : $the_query->the_post();
$url = parse_url( get_field( 'vibe_url', get_the_ID()) );
$btn_url = $url['host'] . $url['path'];
?>
<a class="wp-block-button__link" href="<?php echo $url; ?>"><?php echo $btn_url; ?></a>
<?php endwhile; ?>
<?php endif;?>
so I’ve guessed it could be a scoping issue but adding get_the_ID()
in second parameter doesn’t help ๐
What do you think?
Thanks again,
J
I was going through my plugins and ACF Pro said it needed to be updated. But when I called up the New Version 5.9.3 details, it had a warning at the top:
Warning: This plugin has not been tested with your current version of WordPress.
…and also said it’s compatible up to WP 5.5.1 (we’re on 5.5.2 now, no way to change either).
Please keep your plugins up to date/compatible with the latest WP version.
Hey, the function outputs this:
Array
(
[post] => post
[page] => page
[attachment] => attachment
[revision] => revision
[nav_menu_item] => nav_menu_item
[custom_css] => custom_css
[customize_changeset] => customize_changeset
[oembed_cache] => oembed_cache
[user_request] => user_request
[wp_block] => wp_block
[polylang_mo] => polylang_mo
[acf-field-group] => acf-field-group
[acf-field] => acf-field
[projects] => projects
[flatfiles] => flatfiles
[clients] => clients
[quotes] => quotes
[presentations] => presentations
[modules] => modules
[work] => work
[typefaces] => typefaces
)
Work and typefaces are the ones that don’t show up in the page link select field when I add 1 other post type.
I looked at all the settings for those two post types and they’re exactly the same as for the other post types. Also I changed the name of the field from Post to Post Link, because I thought maybe that interfered, but the issue remains.
Hope you might have another hunch!
Hi @hube2 i already fix the error i mentioned above and your code work like a charm. Thank you so much for your amazing help your such a big help to this community. I might need more help in the future because mostly e use ACF on our website.
Once again thank you so much.
Here the final code
`add_filter(‘acf/fields/relationship/query/name=related_tracks_certificate’, ‘remove_already_selected’, 10, 3);
function remove_already_selected($args, $field, $post_id) {
$query = new WP_Query(array(
‘post_type’ => ‘Tracks’, // my assumption
‘post_status’ => ‘publish’,
‘posts_per_page’ => -1
));
$selected = array();
if (count($query->posts)) {
foreach ($query->posts as $post) {
$tracks = get_field(‘related_tracks_certificate’, $post->ID, false);
if (!empty($tracks)) {
foreach ($tracks as $track) {
$track = intval($track);
if ($track && !in_array($track, $selected)) {
$selected[] = $track;
}
} // end foreach track
} // end if tracks
} // end foreach post
} // end if posts
if (!empty($selected)) {
$args[‘post__not_in’] = $selected;
}
return $args;
} // end function
Hi @hube2 Thank you so much for your response, I appreciate it
Upon using your code.
add_filter(‘acf/fields/relationship/query/name=related_tracks’, ‘remove_already_selected’, 10, 3);
function remove_already_selected($args, $field, $post_id) {
$query = new WP_Query(array(
‘post_type’ => ‘album’, // my assumption
‘post_status’ => ‘publish’,
‘posts_per_page’ => -1
));
$selected = array();
if (count($query->posts)) {
foreach ($query->posts as $post) {
$tracks = get_field(‘related_tracks’, $post->ID, false);
if (!empty($tracks)) {
foreach ($tracks as $track) {
$track = intval($track);
if ($track && !in_array($track, $selected) {
$selected[] = $track;
}
} // end foreach track
} // end if tracks
} // end foreach post
} // end if posts
if (!empty($selected)) {
$args[‘post__not_in’] = $selected;
}
return $args;
} // end function
There is error on this line ‘$selected[] = $track;’
the error is syntax error, unexpected ‘;’
Sorry im very newbie on coding.
I’ve also got this issue which has been triggered since 5.9.2
It affects my Select2 fields which are dynamically populated with custom data using custom JS. It seems to be trying to always populate using ajax even though not required.
I’ve had to revert to 5.9.1 for now.
This worked for me too. However, I ran into issues with the gallery field. After the first submission, if you get back to the same form, it won’t set the selected media. So, I am use the following code.
add_filter( 'ajax_query_attachments_args', 'wpb_show_current_user_attachments' );
function wpb_show_current_user_attachments( $query ) {
$user_id = get_current_user_id();
if ( $user_id && !current_user_can('activate_plugins') && !current_user_can('edit_others_posts
') ) {
$query['author'] = $user_id;
}
return $query;
}
Thank you @hube2
I managed to remove the commas, but now it returns the values x 5…
This is the code:
`<p class=”shop-link”>
<?php $values = get_field(‘shop’);if ($values) {
foreach ($values as $value) {
echo implode(‘<br />’, $values);
}
} ?></p>
`
https://www.advancedcustomfields.com/resources/acf-fields-relationship-query/
This could very likely time out the field and stop it from showing results.
The only way that I can thing to do this (well, the only way without querying the db directly) is to build a filter as suggested by @csaborio and in the filter get all other posts of the same time and look at what’s already been selected.
add_filter('acf/fields/relationship/query/name=related_tracks', 'remove_already_selected', 10, 3);
function remove_already_selected($args, $field, $post_id) {
$query = new WP_Query(array(
'post_type' => 'album', // my assumption
'post_status' => 'publish',
'posts_per_page' => -1
));
$selected = array();
if (count($query->posts)) {
foreach ($query->posts as $post) {
$tracks = get_field('related_tracks', $post->ID, false);
if (!empty($tracks)) {
foreach ($tracks as $track) {
$track = intval($track);
if ($track && !in_array($track, $selected) {
$selected[] = $track;
}
} // end foreach track
} // end if tracks
} // end foreach post
} // end if posts
if (!empty($selected)) {
$args['post__not_in'] = $selected ;
}
return $args;
} // end function
As I said, depending on the number of “Album” posts that exist this will eventually time out the AJAX request for the relationship field and would not be very scale-able.
You could potentially query the post meta table directly to get the acf field value for published posts.
Another possibility would be to create and acf/save_post. In this filter, when saving an “Album” post you could set an option (get_option()/update_option()) and store a list of selected tracks.
Yet another option would be to make the relationship bidirectional with a relationship on the Album side and a post object field on the track site. Then you could do something like this.
add_filter('acf/fields/relationship/query/name=related_tracks', 'remove_already_selected', 10, 3);
function remove_already_selected($args, $field, $post_id) {
$args['meta_query'] = array(
'relation' => 'OR'
array(
'key' => 'bidirectional_post_object_field_name',
'value' => ''
),
array(
'key' => 'bidirectional_post_object_field_name',
'compare' => 'NOT EXISTS'
)
);
return $args;
} // end function
FYI, hotfix appears also to work fine with WordPress 4.9.16.
Thanks everybody for reports, investigation and quick support.
Hi there!
If I understand correctly, you want to filter all tracks that have a certain condition already defined on the select.
I did something similar using: acf/fields/post_object/query (https://www.advancedcustomfields.com/resources/acf-fields-post_object-query/).
You need to a filter that will call the function that will narrow down the choices using a query.
In my case (this is OOP code but you should get the gist), I added the filter:
$action_filter_register->add_filter( 'acf/fields/post_object/query/name=client_match_object_field', Match::class, 'filter_participant_options', 10, 3 );
And then defined the function that did the trick:
public function filter_participant_options( $args, $field, $post_id ) {
$allowed_states = EntityStates::get_allowed_states_for_matching();
$args['numberposts'] = -1;
$args['meta_query'] = array(
array(
'key' => '_state',
'value' => implode( ',', array_keys( $allowed_states ) ),
'compare' => 'IN',
),
);
return $args;
}
Hope this helps!
Sounds good, thanks for the quick response!
I ended up diagnosing the issue by doing a diff of all changes between 5.9.1 and 5.9.2, and slowly reverting changes back to 5.9.1 until I saw the problem disappear. Here’s the gist of just the relevant changes, if needed:
https://gist.github.com/figureone/66fb7004596dc611ae7b3165193461ac
It looks like you were refactoring to better split up changes to options
vs. meta
, by relying on the existence of "update_{$type}_meta
to determine whether to do a meta update or an options update.
If you want to keep that style, you can maybe use if ( get_meta_table( $type ) )
instead, and then follow with a call to update_metadata( $type, ... )
if it’s true, and update_option()
if not. (Similar for the get and delete variants.)
Looks like that’s how core does the check in update_metadata()
:
https://developer.wordpress.org/reference/functions/update_metadata/#source
Aloha Elliot,
I have traced the issue (on vanilla WordPress) to a change in version 5.9.2 to includes/acf-meta-functions.php
. The result is that ACF postmeta does not get created for revision IDs in the database. This happens whether you are saving a draft, or updating a published page. This means:
* if you try to preview an unpublished revision, you won’t see any ACF fields (the original problem in this thread);
* if you try to browse revisions, you will see empty ACF postmeta for all the revisions
* if you try to restore a revision, it won’t have any ACF postmeta associated with it, causing the post’s ACF fields to be deleted.
Because of that 3rd point, this is probably higher severity. Here’s the diff that causes the issue in acf_update_metadata()
:
@@ -240,17 +238,14 @@ function acf_update_metadata( $post_id = 0, $name = '', $value = '', $hidden = f
return false;
}
- // Update option.
- if( $type === 'option' ) {
-
+ // Determine CRUD function.
+ if( function_exists("update_{$type}_meta") ) {
+ return call_user_func("update_{$type}_meta", $id, "{$prefix}{$name}", $value);
+ } else {
// Unslash value to match update_metadata() functionality.
$value = wp_unslash( $value );
$autoload = (bool) acf_get_setting('autoload');
return update_option( "{$prefix}{$id}_{$name}", $value, $autoload );
-
- // Update meta.
- } else {
- return update_metadata( $type, $id, "{$prefix}{$name}", $value );
}
}
I can confirm that reverting the change above restores functionality (i.e., ACF saves postmeta to revision IDs when saving/updating a post).
These are related changes (to acf_get_metadata() and acf_delete_metadata()), just in case they are relevant:
diff --git a/includes/acf-meta-functions.php b/includes/acf-meta-functions.php
index 1d26f03..9e8c81a 100644
--- a/includes/acf-meta-functions.php
+++ b/includes/acf-meta-functions.php
@@ -196,14 +196,12 @@ function acf_get_metadata( $post_id = 0, $name = '', $hidden = false ) {
return null;
}
- // Check option.
- if( $type === 'option' ) {
- return get_option( "{$prefix}{$id}_{$name}", null );
-
- // Check meta.
- } else {
- $meta = get_metadata( $type, $id, "{$prefix}{$name}", false );
+ // Determine CRUD function.
+ if( function_exists("get_{$type}_meta") ) {
+ $meta = call_user_func("get_{$type}_meta", $id, "{$prefix}{$name}", false);
return isset($meta[0]) ? $meta[0] : null;
+ } else {
+ return get_option( "{$prefix}{$id}_{$name}", null );
}
}
@@ -286,14 +281,12 @@ function acf_delete_metadata( $post_id = 0, $name = '', $hidden = false ) {
return false;
}
- // Update option.
- if( $type === 'option' ) {
+ // Determine CRUD function.
+ if( function_exists("delete_{$type}_meta") ) {
+ return call_user_func("delete_{$type}_meta", $id, "{$prefix}{$name}");
+ } else {
$autoload = (bool) acf_get_setting('autoload');
return delete_option( "{$prefix}{$id}_{$name}" );
-
- // Update meta.
- } else {
- return delete_metadata( $type, $id, "{$prefix}{$name}" );
}
}
Aloha Elliot,
I have traced the issue (on vanilla WordPress) to a change in version 5.9.2 to includes/acf-meta-functions.php
. The result is that ACF postmeta does not get created for revision IDs in the database. This happens whether you are saving a draft, or updating a published page. This means:
* if you try to preview an unpublished revision, you won’t see any ACF fields (the original problem in this thread);
* if you try to browse revisions, you will see empty ACF postmeta for all the revisions
* if you try to restore a revision, it won’t have any ACF postmeta associated with it, causing the post’s ACF fields to be deleted.
Because of that 3rd point, this is probably higher severity. Here’s the diff that causes the issue in acf_update_metadata()
:
@@ -240,17 +238,14 @@ function acf_update_metadata( $post_id = 0, $name = '', $value = '', $hidden = f
return false;
}
- // Update option.
- if( $type === 'option' ) {
-
+ // Determine CRUD function.
+ if( function_exists("update_{$type}_meta") ) {
+ return call_user_func("update_{$type}_meta", $id, "{$prefix}{$name}", $value);
+ } else {
// Unslash value to match update_metadata() functionality.
$value = wp_unslash( $value );
$autoload = (bool) acf_get_setting('autoload');
return update_option( "{$prefix}{$id}_{$name}", $value, $autoload );
-
- // Update meta.
- } else {
- return update_metadata( $type, $id, "{$prefix}{$name}", $value );
}
}
I can confirm that reverting the change above restores functionality (i.e., ACF saves postmeta to revision IDs when saving/updating a post).
These are related changes (to acf_get_metadata() and acf_delete_metadata()), just in case they are relevant:
diff --git a/includes/acf-meta-functions.php b/includes/acf-meta-functions.php
index 1d26f03..9e8c81a 100644
--- a/includes/acf-meta-functions.php
+++ b/includes/acf-meta-functions.php
@@ -196,14 +196,12 @@ function acf_get_metadata( $post_id = 0, $name = '', $hidden = false ) {
return null;
}
- // Check option.
- if( $type === 'option' ) {
- return get_option( "{$prefix}{$id}_{$name}", null );
-
- // Check meta.
- } else {
- $meta = get_metadata( $type, $id, "{$prefix}{$name}", false );
+ // Determine CRUD function.
+ if( function_exists("get_{$type}_meta") ) {
+ $meta = call_user_func("get_{$type}_meta", $id, "{$prefix}{$name}", false);
return isset($meta[0]) ? $meta[0] : null;
+ } else {
+ return get_option( "{$prefix}{$id}_{$name}", null );
}
}
@@ -286,14 +281,12 @@ function acf_delete_metadata( $post_id = 0, $name = '', $hidden = false ) {
return false;
}
- // Update option.
- if( $type === 'option' ) {
+ // Determine CRUD function.
+ if( function_exists("delete_{$type}_meta") ) {
+ return call_user_func("delete_{$type}_meta", $id, "{$prefix}{$name}");
+ } else {
$autoload = (bool) acf_get_setting('autoload');
return delete_option( "{$prefix}{$id}_{$name}" );
-
- // Update meta.
- } else {
- return delete_metadata( $type, $id, "{$prefix}{$name}" );
}
}
i solved by accident mine question. But it isn’t, is it possible to switch it back?
Hello, i am struggeling with the repeater field in a gutenberg field. Can some on give me advice of tell me what i am doing wrong? Or is this even possible?
When i use @if(have_row() etc.. i am not getting the information i want. But i am receiving the information from a else statement.
I am using sage10 en acf pro.
blocks/content-sellingpoint.blade.php
{{--
Title: SellingPoint
Description: Selling Points
Category: formatting
Icon: table-row-after
Keywords: sellingpoint quote
Mode: edit
Align: left
PostTypes: page post
SupportsAlign: left right
SupportsMode: false
SupportsMultiple: false
EnqueueStyle: styles/style.css
EnqueueScript: scripts/script.js
EnqueueAssets: path/to/asset
--}}
@php
$title = get_sub_field('title');
$subtext = get_sub_field('subtext');
$sellingpoint = get_field('sellingpoint');
@endphp
<section class="sellingpoint">
<div class="container">
<div class="row">
@if (have_rows('sellingpoint'))
@while(have_rows('sellingpoint')) @php (the_row());
{!! $subtext !!}
@endwhile
@else test
@endif
</div>
</div>
</section>
functions.php
add_action('acf/init', 'my_acf_init');
function my_acf_init() {
// check function exists
if( function_exists('acf_register_block') ) {
acf_register_block(array(
'name' => 'sellingpoint',
'title' => __('Sellingpoint'),
'description' => __('A custom sellingpoint block.'),
'render_callback' => 'my_acf_block_render_callback',
'category' => 'formatting',
'icon' => 'table-row-after',
'keywords' => array( 'Sellingpoint', 'selling', 'point' ),
));
}
}
I just noticed this on the register_block_type()
page:
acf_register_block_type( $settings );
$settings
(array) (Required) Array of arguments for registering a block type. Any argument from the JavaScript registerBlockType() function may also be used.
So if you normally add your props in registerBlockType()
, you should be able to add them when you register the ACF block.
However, as a person with very limited JS experience, I just add any additional classes in the block template code.
I have same question.
Reading in 10k posts and then looping over them will likely cause other issues with performance due to the data returned in the query and memory.
The biggest issue to speed is that regex on the date and the number of fields your using to filter.
If I needed to do something similar to this and knew it before I started I would have a separate field (not in ACF, just your standard WP custom meta field). I would create and acf/save_post filter. In this filter I would get the date field, extract the year and save just the year into this other field. The I could do a simple ‘==’ compare on this field. This would greatly improve the performance of the query.
But with 10k posts to look at it might still be a little slow. If it was I would likely use WP transients to store the results of the query for a time. This would mean the query would only need to be run once every few days.
You could also have a taxonomy for the year, as in one of the points you listed, with the right settings you can actually hide this taxonomy. Instead of saving the year in another fields as in my first suggestion the acf/save_post filter would set the correct term in the year taxonomy.
Post meta can be used for filtering, however, the filtering needs to be limited and the use of things like “LIKE” and “REGEXP” are going to cause performance issues.
I also have one site, this site has “Products” and there are (no lie) 18 different filters used on this site. Trying to filter by 18 custom fields would simply time out the load of the page. In this case, when a new “Product” is saved a CRON is triggered. This CRON runs through all of the possible values for every filter and stores the results. On the front end of the site I use this information to query the posts.
Use a WP option, lets call this option “birth_years”. This option would be an array with this architecture.
$birth_years = array (
// each element of this array is "YEAR" => array()
"2020" => array (
// each element of this array is a post ID of a person in this year
1, 2, 3, 4, 5
)
);
Create an acf/save_post filter with a priority of 1 so that it runs before ACF saves the value of the date field. See the doc for this filter. In this filter I would compare the old value with the new value. If it is the same I would do nothing. If it is different I would get the option, remove this person’s post ID from the old year and add it to the new year in my array.
Then when doing the query for people in the same year I would get the option add this to my query
'post__in' => $birth_year['2020']
completely eliminating the meta query.
Hope some of this information helps you
In the meantime I found these statements:
– Using meta queries to find posts is super expensive
– Post meta isn’t built for filtering
– Taxonomies were built for filtering, and they’re significantly faster for this
– Post meta is designed for when you already know which posts, so get_post_meta is a fast function
Someone suggested, to read out all entries with get_posts without filtering, and then do an extra loop with this output, to filter the entries.
Is this really the only solution? And if so, could anyone help me to do this?
I’m working on a relaunch of my old website. In the old website I read the data โโof the people with SQL directly from a mysql database (with a cache plugin). Here’s an example of a similar query, I did in the old website, to output 4 persons at the end of the page:
SELECT id, name, image, birthday, url, imageurl, license, author FROM Persons WHERE Day(birthday) = '{$birthday}' AND Month(birthday) = '{$month}' AND id != '{$id}' ORDER BY RAND() LIMIT 4
The charging time is only 0.007 seconds (!) in contrast to over 1 second, when I do the query with get_posts and custom fields as shown above.
I can’t understand this, what am I doing wrong ๐
Welcome to the Advanced Custom Fields community forum.
Browse through ideas, snippets of code, questions and answers between fellow ACF users
Helping others is a great way to earn karma, gain badges and help ACF development!
We use cookies to offer you a better browsing experience, analyze site traffic and personalize content. Read about how we use cookies and how you can control them in our Privacy Policy. If you continue to use this site, you consent to our use of cookies.