I'm using Pods to set up Custom Post Types in WordPress.
I have two custom post types: Car and Garage. In Car I have set up a relationship field with Garage, so when editing a Car post I can select one of the Garage posts available from the drop-down.
When viewing a Car post, I would like to display the name and the link to the garage post selected. How would I do that?
Below is an example from http://pods.io/tutorials/get-values-from-a-custom-relationship-field
//get Pods object for current post
$pod = pods( 'pod_name', get_the_id() );
//get the value for the relationship field
$related = $pod->field( 'relationship_field' );
//loop through related field, creating links to their own pages
//only if there is anything to loop through
if ( ! empty( $related ) ) {
foreach ( $related as $rel ) {
//get id for related post and put in ID
//for advanced content types use $id = $rel[ 'id' ];
$id = $rel[ 'ID' ];
//show the related post name as link
echo ''.get_the_title( $id ).'';
//get the value for some_field in related post and echo it
} //end of foreach
} //endif ! empty ( $related )
Instead of a permalink to a Garage post, I'm getting several permalinks to the Car post I'm viewing.
Any Ideas?
Related
There's a number of posts on here attempting to solve this however, I haven't been able to find a solution that works.
I'm attempting to get the URL of the thumbnail image, associated with the product attribute term of the product displayed on a single-product page, and then display the thumbnail below the product meta, with a URL to the term's archive.
The hook that I'm using is as follows:
add_action('woocommerce_product_meta_end','product_brand_image');
Then I'm defining the function used in the hook:
function product_brand_image() {
}
The attribute name is "Brand", and the slug is "brand".
I've managed to get as far as getting the term ID using the following:
function product_brand_image() {
global $product;
$attributes = $product->get_attributes();
$attr_id = $attributes['pa_brand']['options'][0];
}
I've prnt'd this and it returns the term ID, which I've confirmed to be correct.
I'm struggling to now use this to get the associated term thumbnail URL, and term archive slug to be able to insert the thumbnail and then link it to the archive.
Looking to solve this programmatically without using another plugin.
UPDATE:
Ok, so using #Barrie Dawson comment as a guide, I am now up to this point:
function product_brand_image() {
global $product;
$attributes = $product->get_attributes();
$attr_id = $attributes['pa_brand']['options'][0];
$termMeta = get_term_meta($attr_id);
if (is_array($termMeta) && array_key_exists('product_search_image_id', $termMeta)) {
$post_id = $termMeta['product_search_image_id'][0];
$postData = get_post($post_id);
}
}
I have found that attribute term thumbnails are stored in table wp_posts. The 'product_search_image_id' field links to the ID field in wp_posts table. The URL of the thumbnail associated to the term is then listed under the 'guid' column in this same table. I need some assistance with the PHP to extract this.
<?php
function product_brand_image() {
global $product;
$attributes = $product->get_attributes();
$attr_id = $attributes['pa_brand']['options'][0];
$termMeta = get_term_meta($attr_id);
if (is_array($termMeta) && array_key_exists('thumbnail_id', $termMeta)) {
$termThumbnail = get_the_post_thumbnail_url($termMeta['thumbnail_id']);
}
}
you can also request available sizes see: https://developer.wordpress.org/reference/functions/get_the_post_thumbnail_url/
And here is the final solution I arrived at:
add_action('woocommerce_product_meta_end','product_brand_image');
function product_brand_image() {
global $product;
$attributes = $product->get_attributes();
$attr_id = $attributes['pa_brand']['options'][0];
$term = get_term($attr_id);
$termSlug = $term->slug;
$termMeta = get_term_meta($attr_id);
if (is_array($termMeta) && array_key_exists('product_search_image_id', $termMeta)) {
$post_id = $termMeta['product_search_image_id'][0];
$postData = get_post($post_id);
$prod_image_url = $postData->guid;
echo '<span class="product_brand_image"><img src="'.$prod_image_url.'" /></span>';
}
}
This displays the thumbnail of the term of the product attribute below the product meta, and links it to the archive page for that term. In this instance, it links to a shop page (archive) with all products associated to a particular 'brand'. See screenshot below.
Screenshot
I'm trying to display an image in a custom field on child category archive pages.
The current setup is:
<?php
$term_id = get_queried_object()->term_id;
$post_id = 'product_cat_'.$term_id;
$custom_field = get_field('brand_background', $post_id);
?>
<div id="brandHeader" class="brand-header-logo" style="background-image: url('<?php the_field('brand_background', $post_id); ?>');">
This obviously gets the 'background image' field from the category archive it's currently on.
If the category is a child category I want to be able to pull the 'background image' from the parent category. I've tried a few things but doesn't seem to be working - can anyone help?
You could use the get_ancestors function to get the parent id and use that id to get your field:
get_ancestors
So let's say your categories looks like this:
-Parent (id = 24)
--Child (id = 42)
$term_id = get_queried_object()->term_id;
$term_ancestor_ids = get_ancestors($term_id, 'product_cat');
// if you do a print_r on $term_ancestor_ids
// you'll see this:
// Array ( [0] => 24 )
$post_id = 'product_cat_'.$term_ancestor_ids[0];
$custom_field = get_field('brand_background', $post_id);
Tested and works, let me know if you were able to get it to work too!
I'm having trouble finding documentation for displaying the relationship fields between two custom post types.
Essentially I have a stores post type that holds store names and images. Then I have a product post type where each product will have fields where you can select what stores it is available at and a section for a link to the product within that store.
Setup:
I have two custom post types 1: Stores, 2: Products
The fields for "products" are
[repeater] product_stores
[sub field] store_name (RELATIONSHIP)
[sub field] store_link (URL)
The fields for "stores" are
title (WP DEFAULT TITLE)
image (IMAGE)
I'm able to display the custom field type for the retailer link but having trouble pulling the retailer name and image into the page.
What I have so far
<?php
if( have_rows('product_stores') ): ?>
<?php while( have_rows('product_stores') ): the_row(); ?>
<?php the_sub_field('store_link'); ?>
<?php endwhile; ?>
<?php endif; ?>
You don't need to use a Repeater field with a Relationship field inside it - just use a single Relationship field. The field will return an array of post objects which you can pull the title and link from.
<?php
$stores = get_field('product_stores'); // your Relationship field
if( $stores ) {
foreach( $stores as $post) {
setup_postdata($post);
the_title();
the_permalink(); // pull whatever you need from the post.
}
wp_reset_postdata();
}
?>
Thanks for your help in advance. Here's what I'm trying to achieve:
I have a custom post type called 'Campaigns' and I have a custom taxonomy called 'Countries' that is related to the campaign custom post type. When a user adds a new country to a campaign a new campaign post is generated that is the child of the current campaign. I'm duplicating the ACF fields that are assigned to the parent campaign and replicating the values in the child post, however I've run into an issue using the ACF flexible content fields. Here'a snippet of my code that is retrieving the parent post fields and updating the newly created ACF field in the child post with that value.
$action_text = get_post_meta($parent_id, 'action_text', true);
update_field('action_text', $action_text, $post_id);
I've tried doing this with flexible content, but I know I need to loop through and find what content blocks have been created. What is the best way to go about this?
// About Fields
$about_fields = get_post_meta($parent_id, 'content');
var_dump($about_fields);
$meta_key = // How to retrieve the flexible content keys
$meta_value_of_flexible_content = get_post_meta($parent_id, $meta_key);
if($about_fields) {
}
For clarification 'content' is the flexible container name. 'text_and_image' is an example name of one of the flexible content blocks I've created.
Thanks again for any insights.
I've tried doing this with flexible content, but I know I need to loop
through and find what content blocks have been created.
You could just use the get_field() and update_field() functions to duplicate any ACF fields, including Flexible Content fields.
So for example, to clone the whole content field:
$about_fields = get_field( 'content', $parent_id );
if ( $about_fields ) {
update_field( 'content', $about_fields, $post_id );
}
// How to retrieve the flexible content keys
foreach ( $about_fields as $arr ) {
echo 'Layout: ' . $arr['acf_fc_layout']; // e.g. "Layout: text_and_image"
// The rest of items in `$arr` are the SUB-fields of that specific layout as
// identified by the `$arr['acf_fc_layout']`, which is the layout's name. So
// if you have two SUB-fields named `text1` and `image1` respectively, then
// these items are set: `$arr['text1']` and `$arr['image1']`
}
Additional Code
To clone all ACF fields:
$fields = get_fields( $parent_id );
foreach ( $fields as $name => $value ) {
update_field( $name, $value, $post_id );
}
Additional Note
I'd change this to use the get_field() function:
$action_text = get_post_meta($parent_id, 'action_text', true);
So:
$action_text = get_field('action_text', $parent_id);
I'm working with a wordpress site where posts havn't been attached correctly, visibly it makes sense and all posts are in order but in the database there is no reference of any post connection. There are thousands of posts here, so I'll just show an example of what I'm working with, and what I would like to achieve via an action hook, or function. Or even just an update_post method.
Example list of posts currently
Post Title 1 (Category = Folder)
Post Title 2 (Category = Item)
Post Title 3 (Category = Item)
Post Title 4 (Category = Item)
Post Title 5 (Category = Item)
Post Title 6 (Category = Folder)
Post Title 7 (Category = Item)
Post Title 8 (Category = Item)
Post Title 9 (Category = Item)
Post Title 10 (Category = Item)
What I would like to achieve is:
Any posts in category 'item' that are below a post in category 'folder' to then become children of the above Folder post, so my posts would become something like this:
Post Title 1 (Category = Folder)
- Post Title 2 (Category = Item Post_parent = Post Title 1)
- Post Title 3 (Category = Item Post_parent = Post Title 1)
- Post Title 4 (Category = Item Post_parent = Post Title 1)
- Post Title 5 (Category = Item Post_parent = Post Title 1)
Post Title 6 (Category: Folder)
- Post Title 7 (Category = Item Post_parent = Post Title 6)
- Post Title 8 (Category = Item Post_parent = Post Title 6)
- Post Title 9 (Category = Item Post_parent = Post Title 6)
- Post Title 10 (Category = Item Post_parent = Post Title 6)
I'm wondering if someone can just put me on the right track of how I could do this writing a script myself. Something along the lines of:
For each post in category link > that is below a post in category folder > make this post a child of post in folder category above
What I am struggling to reference is the 'that is a below a post'. Could this be referenced by using published post date?
First of all, wordpresss post aren't hierarchical so you might want to eanble hierarchy support so you can see them on the back-end, you can add something like this
add_action('registered_post_type', '_enable_post_hierarchy', 10, 2 );
function _enable_post_hierarchy( $post_type ) {
if ($post_type !== 'post') return;
global $wp_post_types;
$wp_post_types['post']->hierarchical = 1;
add_post_type_support( 'post', 'page-attributes' );
}
Regarding about your main concern, you can achieve what you want by;
First;
create custom WP_Query, query all the post (though I think you should implement paging as you have a lot of posts) with ITEM category and make sure the order is the same as what you stated above, I believe its orderby=date and order=DESC
Then;
After you get the results, loop through each result and do another query, this time, it must only need one result, with the category FOLDER and/or not in category ITEM, and the most important part is that the POST_DATE must be greater than the current item POST_DATE (from your loop ), you can either create custom SQL query or try using WP_Query
the other method is to use get_adjacent_post built-in function, this is use on wordpress next and previous post, though this won't work if you have other category than ITEM and FOLDER. check it out https://codex.wordpress.org/Function_Reference/get_adjacent_post
Here's some NOT FULLY tested code I've come up with
First lets try getting the data and displaying the array on the front-end to verify if our new data array is built properly
// spit the data to verify the order and hierarchy
add_action('wp_head', function() {
echo '<pre>', print_r( _check_data_post(), 1), '</pre>';
});
function _check_data_post( $display = 'data' ) {
// ID of the item category
$item_id = 29;
//create query argument
$args = [
'post_type' => 'post',
'post_status' => 'publish',
'orderby' => 'date',
'order' => 'DESC',
'cat' => $item_id,
// lets add some limit not to kill the server
'post_per_page' => 50,
];
//build new query
$q = new WP_Query( $args );
//get all query result
$posts = $q->get_posts();
//new data holder
$data = [];
// loop through each result
foreach ($posts as $key => $new_post) {
// the global $post is needed for get_adjacent_post to work
global $post;
// assign each result to $post
$post = $new_post;
// get the next post, the parameters is as follows
// false - must not be only in same terms, meaning its not gonna query in ITEM category only but rather query all category
// $item_id - exclude the specified ID, we must not include the ITEM category
// false - (true means previous) NEXT to the current $post which is the current item of our loop, meaning it must have greater date than our current item
// This will not work if you have categories other then Folder and Item
// You should write your own custom SQL to be more specific and adjust on your need
$parent = get_adjacent_post( false, $item_id , false );
if( $display == 'ids' ) {
// lets return each post ID with additional "parent" ID
$data[$key]['id'] = $post->ID;
$data[$key]['parent'] = $parent->ID;
} else {
// Display Title and Category instead of the ID to verify the result
$data[$key]['cat'] = get_the_category( $post->ID )[0]->name;
$data[$key]['title'] = $post->post_title;
$data[$key]['parent'] = [
'cat' => get_the_category( $parent->ID )[0]->name,
'title' => $parent->post_title,
];
}
}
return $data;
}
Once its verified, we will then loop through each item and update each item with new parent post ID, you can call this function somewhere safe and run only once, its also better to add a bunch of conditional verification and error messages
function _update_data_post() {
// get the all the item, must be IDs only
$list_items = _check_data_post('ids');
// loop through each item
foreach ( $list_items as $items ) {
//assign item data
$data = [
'ID' => $items['id'],
'post_parent' => $items['parent'],
];
//update item with assigning post_parent value
wp_update_post( $data );
}
}