Add ACF fields to taxonomy by submitting post - wordpress

Lets say i have products based on woocommerce, and I want some specific functionality.
For example: inside product I created two ACF input fields:
Manufacter
Model
Then i have taxonomy named - "klb_make"
There must add Manufacter and Model values: Manufactur -> parent, Model -> child
Parent(some manufacter)
Child (some model)
Parent2(some manufacter2)
Child2(some modal2)
and so on..
i have tryed some code
$get_posts = new WP_Query;
add_action( 'init', function() {
$post_id = $get_posts;
$field_id = 'klb_make_type';
$value = 'My custom value';
rwmb_set_meta( $post_id, $field_id, $value );
}, 99 );`
or:
add_action( 'init', function() {
$post_id = $get_posts;
$field_id = 'klb_make_type';
$value = [
[
'parent' => 'Manufacter',
'child' => 'model',
],
[
'parent' => 'Manufacter2',
'child' => 'model2',
],
];
rwmb_set_meta( $post_id, $field_id, $value );
}, 99 );`
But didin't worked

Related

Add custom field to product inventory tab and display value on single product page where meta ends

I'm using the following code in my theme functions.php file to add a additional data field to the product inventory tab:
// Add Custom Field to woocommerce inventory tab for product
add_action('woocommerce_product_options_inventory_product_data', function() {
woocommerce_wp_text_input([
'id' => '_number_in_package',
'label' => __('Number of Pages', 'txtdomain'),
'type' => 'number',
]);
});
add_action('woocommerce_process_product_meta', function($post_id) {
$product = wc_get_product($post_id);
$num_package = isset($_POST['_number_in_package']) ? $_POST['_number_in_package'] : '';
$product->update_meta_data('_number_in_package', sanitize_text_field($num_package));
$product->save();
});
add_action('woocommerce_product_meta_start', function() {
global $post;
$product = wc_get_product($post->ID);
$num_package = $product->get_meta('_number_in_package');
if (!empty($num_package)) {
printf('<div class="custom-sku">%s: %s</div>', __('Number of Pages', 'txtdomain'), $num_package);
}
});
add_filter('woocommerce_product_data_tabs', function($tabs) {
$tabs['additional_info'] = [
'label' => __('Additional info', 'txtdomain'),
'target' => 'additional_product_data',
'class' => ['hide_if_external'],
'priority' => 25
];
return $tabs;
});
However, on the single product page, the custom field is added before category and ISBN. I want to place the custom field at the end after the product ISBN. Any advice?
Some comments/suggestions regarding your code attempt
To save fields you can use the woocommerce_admin_process_product_object hook, opposite the outdated woocommerce_process_product_meta hook
WooCommerce contains by default no ISBN field, but it looks like the woocommerce_product_meta_end hook will answer your question
So you get:
// Add custom field
function action_woocommerce_product_options_inventory_product_data() {
woocommerce_wp_text_input( array(
'id' => '_number_in_package',
'label' => __( 'Number of Pages', 'woocommerce' ),
'description' => __( 'This is a custom field, you can write here anything you want.', 'woocommerce' ),
'desc_tip' => 'true',
'type' => 'number'
) );
}
add_action( 'woocommerce_product_options_inventory_product_data', 'action_woocommerce_product_options_inventory_product_data' );
// Save custom field
function action_woocommerce_admin_process_product_object( $product ) {
// Isset
if ( isset( $_POST['_number_in_package'] ) ) {
// Update
$product->update_meta_data( '_number_in_package', sanitize_text_field( $_POST['_number_in_package'] ) );
}
}
add_action( 'woocommerce_admin_process_product_object', 'action_woocommerce_admin_process_product_object', 10, 1 );
// Display on single product page
function action_woocommerce_product_meta_end() {
global $product;
// Is a WC product
if ( is_a( $product, 'WC_Product' ) ) {
// Get meta
$number = $product->get_meta( '_number_in_package' );
// NOT empty
if ( ! empty ( $number ) ) {
echo '<p>' . $number . '</p>';
}
}
}
add_action( 'woocommerce_product_meta_end', 'action_woocommerce_product_meta_end', 10 );

Woocommerce not saving form field

i cannot figure out what i am missing.
I created a custom textfield at the woocommerce checkout with a predefined value. Function is pretty standard:
function one_more_field(){
$product_name='';
global $product;
foreach( WC()->cart->get_cart() as $cart_item ){
$productvariation = $cart_item['variation_id'];
}
woocommerce_form_field( 'variatie', array(
'type' => 'text',
'value' => $productvariation,
),
$productvariation );
}
add_action( 'woocommerce_after_checkout_billing_form', 'one_more_field' );
I can see the field in the checkout and the variation ID is nicely inserted.
Then step 2: saving the value to the user meta data:
function reigel_woocommerce_checkout_update_user_meta( $customer_id, $posted ) {
$dob4 = 'test';
if (isset($posted['variatie'])) {
$dob4 = $posted['variatie'];
update_user_meta( $customer_id, 'variatie', $dob4);
}
add_action( 'woocommerce_checkout_update_user_meta', 'reigel_woocommerce_checkout_update_user_meta', 10, 2 );
However, the value is not saved to the user meta data.
What am i missing here?
Oh it turns out to be very straightforward: just add required => yes to the array of field arguments and it is saved. Cant really understand why though...
So new code (step 1) is:
function one_more_field(){
$product_name='';
global $product;
foreach( WC()->cart->get_cart() as $cart_item ){
$productvariation = $cart_item['variation_id'];
}
woocommerce_form_field( 'variatie', array(
'type' => 'text',
'value' => $productvariation,
'required' => 'true'
),
$productvariation );
}
add_action( 'woocommerce_after_checkout_billing_form', 'one_more_field' );

Wordpress REST API reading post meta but not updating

I am trying to create a PowerApp in which I want to integrate the post meta fields. I inserted this code in the functions.php file. But I can read and write the data for default WordPress fields, but I am not able to update the post custom fields.
add_action( 'rest_api_init', 'create_api_posts_meta_field' );
function create_api_posts_meta_field() {
// register_rest_field ( 'name-of-post-type', 'name-of-field-to-return', array-of-callbacks-and-schema() )
register_rest_field( 'post', 'post-meta-fields', array(
'get_callback' => 'get_post_meta_for_api',
'update_callback' => 'get_post_meta_update_for_api',
'schema' => null,
)
);
}
function get_post_meta_for_api( $object ) {
//get the id of the post object array
$post_id = $object['id'];
//return the post meta
return get_post_meta( $post_id );
}
function get_post_meta_update_for_api( $value, $object, $field_name ) {
return update_post_meta( $object[ 'id' ], $field_name, $value );
}

How to Populate a Drop-down field in WP

I have a gravity form form on my WP site and I recently changed a free text field into a drop down field.
The website is a store which hold several categories of goods and I want my drop-down to show the user all the possible categories he can choose from.
Please assist in how to "pull" the categories into the drop-down list.
Thanks in advance.
You can do using some filters of gravity form, code is following
// Here 1 is form id
add_filter( 'gform_pre_render_1', 'populate_category' );
add_filter( 'gform_pre_validation_1', 'populate_category' );
add_filter( 'gform_pre_submission_filter_1', 'populate_category' );
add_filter( 'gform_admin_pre_render_1', 'populate_category' );
function populate_category( $form ) {
foreach ( $form['fields'] as &$field ) {
if ( $field->type != 'select' || strpos( $field->cssClass, 'populate-category' ) === false ) {
continue;
}
// Get category list
$categories = get_categories( array(
'orderby' => 'name',
'order' => 'ASC'
) );
$choices = array();
foreach( $categories as $category ) {
$choices[] = array( 'text' => $category->name, 'value' => $category->name );
}
$field->placeholder = 'Select a Category';
$field->choices = $choices;
}
return $form;
}
This is working perfectly its tested code.

How to order categories in WordPress?

I use wp_list_categories() to get the list of all the categories and generate the navigation bar. Is there a way to order these categories in a particular order other than alphabetical ordering.
eg: Connect, News & Views, Q&A, Hello Startup, Startup 101...
Most themes don't use the description of the category for anything. Easy workaround I did was to use numbers in description. The top post here currently has some jQuery hack from here, it's unneeded.
You can add custom order fields I suppose as well.
Just
$categories = get_categories( array(
'orderby' => 'description',
'order' => 'ASC'
) );
Technical approach
The problem in wordpress core is that the table wp_terms has no term_order column. That means, standard wordpress does not support the custom term order. If you look at this WP database structure you can find the table wp_term_relationships. This table is responsible for the relationships between posts and the taxonomy (your categories) AND this table has a term_order column.
Now, with a simple SQL statement ALTER TABLE wp_terms ADD term_order INT(11) NOT NULL DEFAULT 0 (not forget the $wpdb->wp_terms variable) you can add a column to the table, which is responsible for your custom category order. Then you can put your custom category order in this two columns of wp_term_relationships and wp_terms. When all is finished, you can hook into the filter of get_terms_args and change the orderby to term_order.
Here a list of all relevant links for the technical approach:
https://codex.wordpress.org/Database_Description for the wp database structure
https://codex.wordpress.org/Class_Reference/wpdb for the $wpdb->wp_terms
https://developer.wordpress.org/reference/hooks/get_terms_args/ for the WP filter
A plugin can do the job for you
Check my plugin to solve this: WordPress Real Categories Management. WP RCM creates an extra field term_order on the wp terms table. It also brings a lot of other useful features as you can see in the screenshot below. It allows you to organize your wordpress categories in a nice way. It is easy to use, just drag&drop your categories and move it to a specific order. The plugin works in all Custom post types.
From the product description i can quote. If you want to try the plugin, there is also a demo on the plugin page.
There are a lot of free plugins
This can be solved with a lot of free plugins available within the wordpress.org plugin repository. Simply search for "category order" in your Wordpress Dashboard > Plugins > Install.
This is inbuilt in wordpress_wp_list_categories
wp_list_categories('orderby=name');
I think that would help you out
I did it generating several term lists. I call it later by my own order. I'm a PHP beginner.
First, I store, in a different variable, the ID for each category term:
$terms = get_terms('my_taxonomy', 'hide_empty=0');
foreach ( $terms as $term ) {
${$term->slug} = get_term_by('slug', $term->slug, 'product_cat');
${$term->slug.'_array'} = (array)${$term->slug};
${$term->slug.'_array_id'} =${$term->slug.'_array'}['term_id'];
};
Then, I create several args for each wp_list_categories() excluding, with this variable the terms I want to:
$args = array(
'taxonomy' => 'my_taxonomy',
'orderby' => 'name',
'show_count' => true,
'pad_counts' => false,
'hierarchical' => true,
'title_li' => '',
'hide_empty' => 0,
'show_option_all' => 'Show all',
'exclude' => array( $term1_array_id, $term2_array_id )
);
$args_1 = array(
'taxonomy' => 'my_taxonomy',
'orderby' => 'name',
'show_count' => true,
'pad_counts' => false,
'hierarchical' => true,
'title_li' => '',
'hide_empty' => 0,
'exclude' => array( $term3_array_id, $term4_array_id, $term1_array_id )
);
$args_2 = array(
'taxonomy' => 'my_taxonomy',
'orderby' => 'name',
'show_count' => true,
'pad_counts' => false,
'hierarchical' => true,
'title_li' => '',
'hide_empty' => 0,
'exclude' => array( $term1_array_id, $term4_array_id, $term5_array_id )
);
Finally, I can call separately each term list:
<ul>
<?php wp_list_categories( $args ); ?>
<?php wp_list_categories( $args_1 ); ?>
<?php wp_list_categories( $args_2 ); ?>
</ul>
Use Category Order and Taxonomy Terms Order free plugin
I didn't find anything so I constructed my own method. I abstracted it away in an abstract class for my plugin, hence the extra code, but you can pull the methods.
The main method to look at is format_hierarchy()
// The parent class
abstract class Taxonomy {
protected bool $_terms_loaded;
protected array $terms;
protected array $formatted_terms;
public function __get( $property ) {
if ( $property === 'formatted_terms' ) {
if ( !isset( $this->formatted_terms ) ) $this->format_hierarchy();
return $this->formatted_terms;
}
if ( substr( $property, 0, 1 ) === '_' ) die( 'Cannot get private properties' );
if ( property_exists( $this, $property ) )
return $this->$property;
}
/**
* Formats the taxonomy's terms into a hierarchy of term_blocks and saves the value as a property to the class
*
* #return array an array of `[term_taxonomy_id:number] => term_block` like:
* array(
* array( // parent $term_block
* 'term' => WP_Term,
* 'children' => array( $term_blocks… )
* ),
* …$term_blocks…
* )
*/
public function format_hierarchy():array {
if ( !$this->_load_terms() ) return [];
// Holds a reference to every category, parents and children
$term_blocks = [];
// Holds a reference to every top most level category
$parents = [];
foreach ( $this->terms as $term ) {
// Add itself to the list of all categories
$term_block = [
'children' => [],
'term' => $term
];
// Add itself to the array of all categories
if ( !isset( $term_blocks[ $term->term_taxonomy_id ] ) )
$term_blocks[ $term->term_taxonomy_id ] =& $term_block;
// If it's a child category…
if ( $term->parent !== 0 ) {
// If the parent hasn't been created yet, create it
if ( !isset( $term_blocks[ $term->parent ] ) )
$term_blocks[ $term->parent ] = [
'children' => [],
'term' => null
];
$term_blocks[ $term->parent ][ 'children' ][] =& $term_block;
} else
// Otherwise it's a parent
$parents[ $term->term_taxonomy_id ] =& $term_blocks[ $term->term_taxonomy_id ];
// set the term block's WP_Term property
$term_blocks[ $term->term_taxonomy_id ][ 'term' ] =& $term;
// This is needed so that the loop doesn't readd the same reference over and over again
unset( $term ); unset( $term_block );
}
return $this->formatted_terms = $parents;
}
/**
* Given a WP_Term property value, and a property key, recursively searches through all of the terms for it
*
* #property $term_val mixed The property value to find
* #property $prop string The property key for the value
* #property $with_parent ?boolean Whether to return the top level parent as well
* #property $term_blocks ?array Array of term blocks
* #return array If $with_parent is true, returns an [ $found_term_block, $top_level_parent ]
* Otherwise returns only the found term block
*/
public function find_term_by(
$term_val,
string $prop,
bool $with_parent = false,
$term_blocks = null
):?array {
if ( is_null( $term_blocks ) ) $term_blocks = $this->formatted_terms;
foreach ( $term_blocks as $term_block ) {
if ( $term_block[ 'term' ]->{$prop} === $term_val ) return $term_block;
if ( count( $term_block[ 'children' ] ) &&
( $found = $this->find_term_by( $term_val, $prop, false, $term_block[ 'children' ] ) )
) return $with_parent ? [ $found, $term_block ] : $found;
}
return null;
}
/**
* Loads the taxonomy terms once from the DB
*/
protected function _load_terms():bool {
if ( isset( $this->_terms_loaded ) ) return $this->_terms_loaded;
$this->terms = get_terms(
array(static::$taxonomy),
array(
'hide_empty' => false,
)
);
if ( !$this->terms ) {
ClassErrorHandler::handle_exception(
new \WP_Error( 500, 'Failed to load category terms: \'' . static::$taxonomy . '\'' )
);
}
return $this->_terms_loaded = !!$this->terms;
}
}
// The Implementation
class TaxonomyProductService extends Taxonomy {
public static string $taxonomy;
public static string $slug;
/**
* To be called upon taxonomy registration long before any instance is required
*/
public static function define_taxonomy( string $slug, string $taxonomy ) {
static::$slug = $slug;
static::$taxonomy = $taxonomy;
}
}
Right after registering the custom taxonomy I call
TaxonomyProductService::define_taxonomy( 'url-slug', 'product-service' );
And finally how it's used
$tax = new TaxonomyProductService();
$terms = $tax->formatted_terms;
// search for a term whose slug === `my-term`, and return the parent category
list( $current_term, $parent_term ) = $tax->find_term_by( 'my-term', 'slug', true );
For the benefit of future visitors, here’s the easy solution to this problem:
There are now a number of plugins that allow you to order categories or other custom taxonomies in WordPress. You can see some of them in the WordPress plugin directory’s “category order” tag page. I can personally confirm that Custom Taxonomy Order NE plugin does the job.

Resources