• So I am working on a beer site, where I want to present beer with pictures of the beer, in the correct sizes. So found some code on the internet that gets me halfway there, but hoping someone can get me all the way there (I’ve crashed my site 50+ times trying to create it myself).

    So I want the checked terms under ‘unit’ to generate an select picture link.


      /**
         * Register a taxonomy for units.
         *
         * @link https://codex.www.ads-software.com/Function_Reference/register_taxonomy
         */
        protected function register_taxonomy_unit()
        {
            $labels = array(
                'name'                       => __('Units', '$textdomain'),
                'singular_name'              => __('Unit', '$textdomain'),
                'menu_name'                  => __('Units', '$textdomain'),
                'edit_item'                  => __('Edit Unit', '$textdomain'),
                'update_item'                => __('Update Unit', '$textdomain'),
                'add_new_item'               => __('Add New Unit', '$textdomain'),
                'new_item_name'              => __('New Unit Name', '$textdomain'),
                'parent_item'                => __('Parent Unit', '$textdomain'),
                'parent_item_colon'          => __('Parent Unit:', '$textdomain'),
                'all_items'                  => __('All Units', '$textdomain'),
                'search_items'               => __('Search Units', '$textdomain'),
                'popular_items'              => __('Popular Units', '$textdomain'),
                'separate_items_with_commas' => __('Separate Units with commas', '$textdomain'),
                'add_or_remove_items'        => __('Add or remove Units', '$textdomain'),
                'choose_from_most_used'      => __('Choose from the most used Units', '$textdomain'),
                'not_found'                  => __('No Units found.', '$textdomain'),
            );
    
            $args = array(
                'labels'            => $labels,
                'public'            => true,
                'show_in_nav_menus' => true,
                'show_ui'           => true,
                'show_tagcloud'     => true,
                'hierarchical'      => true,
                'rewrite'           => array( 'slug' => 'unit' ),
                'show_admin_column' => true,
                'query_var'         => true,
            );
    
            $args = apply_filters('beer_post_type_unit_arg', $args);
    
            register_taxonomy($this->taxonomies[3], $this->post_type, $args);
        }

    The code for more pictures
    Upload multiple featured images in a custom post (WordPress) – Stack Overflow

    It gives me this metabox:

    But what i am looking for is, if unit looks look this:

    And then the picture chooser look like this:

    I really hope someone can help me with this.

    Thanks in advance

    • This topic was modified 5 months, 3 weeks ago by Foley. Reason: Pictures failed to load when copy pasted into the textbox
Viewing 10 replies - 1 through 10 (of 10 total)
  • Moderator bcworkz

    (@bcworkz)

    This is what determines the add image button labels:
    <?php _e('add image','yourdomain'); ?>

    You need to conditionally use a different label based on the current value of $meta_key, which comes from $meta_keys:
    $meta_keys = array('second_featured_image','third_featured_image');
    Instead of hardcoding values like this, you need to get the selections from the units meta box. As this is PHP based, the units selections need to first be saved, then the page reloaded for the selected image buttons to appear.

    A more interactive approach would mean a more JavaScript oriented approach that’s a significant departure from the current code.

    Thread Starter Foley

    (@foley)

    @bcworkz, thanks, i know that part. The part I am struggling with is

    Instead of hardcoding values like this, you need to get the selections from the units meta box. As this is PHP based, the units selections need to first be saved, then the page reloaded for the selected image buttons to appear.

    I haven’t been able to find a good solution. I am aware there is a PHP approach and javascript approach, and even though the javascript might be sexier, the PHP is the one i am looking for, and tried several approaches found, but nothing happens. Or the site breaks… ??

    Moderator bcworkz

    (@bcworkz)

    I don’t think JS is avoidable because for a solely PHP solution to work the page needs to reload. That means needing to save the entire editor context in order to see the correct featured image buttons. When making meta box selections the user would not expect to need to save everything just to see the right buttons.

    For this to work in the expected editor paradigm, you need to add JS listeners to the unit options. The related callback then adds or removes buttons as appropriate.

    Thread Starter Foley

    (@foley)

    I have no issue with doing a new post, setting in the info i can put in, then push save, and then get the product picture box up, where i can add pictures in the boxes showing up. And if a beer changes size I don’ have any issues with changing the size, click ‘update’ and set a new picture.

    So no need for a JS ??

    Thread Starter Foley

    (@foley)

    I am getting very much closer. The Name of the terms in use on the post is now generated:

    But I want to utilize the slugs as well as the names for the taxonomies. And when i click the button to add the pictures, I get the regular popup that shows images, and i choose a picture and click select picture, and the box closes, but no picture has been added. Which is related to the name with spaces being part of the code. So would love to $product_size and $product_size_name.

    //init the meta box for product images
    add_action( 'after_setup_theme', 'product_image_setup' );
    function product_image_setup(){
        add_action( 'add_meta_boxes', 'product_image_meta_box' );
        add_action( 'save_post', 'product_image_meta_box_save' );
    }
    
    function product_image_meta_box(){
    
        //on which post types should the box appear?
        $post_types = array('beer','other');
        foreach($post_types as $pt){
            add_meta_box('product_image_meta_box',__( 'Product Images', 'yourdomain'),'product_image_meta_box_func',$pt);
        }
    }
    
    function product_image_meta_box_func($post){
    
        //an array with all the images (ba meta key). The same array has to be in product_image_meta_box_save($post_id) as well.
        $product_sizes = wp_get_object_terms( $post->ID, 'unit', array( 'fields' => 'names','slug' ) );
        foreach($product_sizes as $product_size) {
    
         $image_meta_val=get_post_meta( $post->ID, $product_size, true);
            ?>
            <div class="product_image_wrapper" id="<?php echo $product_size; ?>_wrapper" style="margin-bottom:20px;">
                <img src="<?php echo ($image_meta_val!=''?wp_get_attachment_image_src( $image_meta_val)[0]:''); ?>" style="width:100%;display: <?php echo ($image_meta_val!=''?'block':'none'); ?>" alt="">
                <a class="addimage button" onclick="product_image_add_image('<?php echo $product_size; ?>');"><?php _e($product_size,'yourdomain'); ?></a><br>
                <a class="removeimage" style="color:#a00;cursor:pointer;display: <?php echo ($image_meta_val!=''?'block':'none'); ?>" onclick="product_image_remove_image('<?php echo $product_size; ?>');"><?php _e('remove image','yourdomain'); ?></a>
                <input type="hidden" name="<?php echo $product_size; ?>" id="<?php echo $product_size; ?>" value="<?php echo $image_meta_val; ?>" />
                <?php echo $product_size; ?>
    
            </div>
        <?php } ?>
    
        
        <script>
        function product_image_add_image(key){
    
            var $wrapper = jQuery('#'+key+'_wrapper');
    
            product_image_uploader = wp.media.frames.file_frame = wp.media({
                title: '<?php _e('select image','yourdomain'); ?>',
                button: {
                    text: '<?php _e('select image','yourdomain'); ?>'
                },
                multiple: true
            });
            product_image_uploader.on('select', function() {
    
                var attachment = product_image_uploader.state().get('selection').first().toJSON();
                var img_url = attachment['url'];
                var img_id = attachment['id'];
                $wrapper.find('input#'+key).val(img_id);
                $wrapper.find('img').attr('src',img_url);
                $wrapper.find('img').show();
                $wrapper.find('a.removeimage').show();
            });
            product_image_uploader.on('open', function(){
                var selection = product_image_uploader.state().get('selection');
                var selected = $wrapper.find('input#'+key).val();
                if(selected){
                    selection.add(wp.media.attachment(selected));
                }
            });
            product_image_uploader.open();
            return false;
        }
    
        function product_image_remove_image(key){
            var $wrapper = jQuery('#'+key+'_wrapper');
            $wrapper.find('input#'+key).val('');
            $wrapper.find('img').hide();
            $wrapper.find('a.removeimage').hide();
            return false;
        }
        </script>
        <?php
        wp_nonce_field( 'product_image_meta_box', 'product_image_meta_box_nonce' );
    }
    
    function product_image_meta_box_save($post_id){
    
        if ( ! current_user_can( 'edit_posts', $post_id ) ){ return 'not permitted'; }
    
        if (isset( $_POST['product_image_meta_box_nonce'] ) && wp_verify_nonce($_POST['product_image_meta_box_nonce'],'product_image_meta_box' )){
    
            //same array as in product_image_meta_box_func($post)
            $product_sizes = wp_get_object_terms( $post->ID, 'unit', array( 'fields' => 'names','slug' ) );
            foreach($product_sizes as $product_size){
                if(isset($_POST[$product_size]) && intval($_POST[$product_size])!=''){
                    update_post_meta( $post_id, $product_size, intval($_POST[$product_size]));
                }else{
                    update_post_meta( $post_id, $product_size, '');
                }
            }
        }
    }
    
    
    

    Hopefully someone got a tip for that.
    Next part is to create a list of all Units sizes not in use by this post to make sure those are cleared out as well ??

    Thread Starter Foley

    (@foley)

    So now I am superclose, I get the correct sizes up, i can choose a picture, but saving fails.
    I get the following error of the code “Attempt to read property “ID” on null”.
    This related to the second codesnippet:

    $product_sizes = wp_get_object_terms( $post->ID, 'unit', array( 'fields' => 'slugs' ));

    This second entry can be found on line 113 in the code underneath, while the first one is on 20:

    //init the meta box for product images
    add_action( 'after_setup_theme', 'product_image_setup' );
    function product_image_setup(){
    add_action( 'add_meta_boxes', 'product_image_meta_box' );
    add_action( 'save_post', 'product_image_meta_box_save' );
    }

    function product_image_meta_box(){

    //on which post types should the box appear?
    $post_types = array('beer','other');
    foreach($post_types as $pt){
    add_meta_box('product_image_meta_box',__( 'Product Images', 'yourdomain'),'product_image_meta_box_func',$pt);
    }
    }

    function product_image_meta_box_func($post){

    //an array with all the images (ba meta key). The same array has to be in product_image_meta_box_save($post_id) as well.
    $product_sizes = wp_get_object_terms( $post->ID, 'unit', array( 'fields' => 'slugs' ));
    echo "<pre>". json_encode($product_sizes, JSON_PRETTY_PRINT) . "</pre>";
    ?>

    <style>
    .product_images_container {
    display: flex;
    flex-wrap: wrap;
    gap: 20px;
    }

    .product_image_wrapper {
    flex: 1 1 calc(20% - 20px);
    box-sizing: border-box;
    margin-bottom: 20px;
    align-content: end;
    text-align: center;
    }

    .product_image_wrapper img {
    width: auto;
    max-height: 300px;
    }
    </style>

    <div class="product_images_container">
    <?php
    foreach($product_sizes as $product_size) {
    $image_meta_val=get_post_meta( $post->ID, $product_size, true);
    ?>
    <div class="product_image_wrapper" id="<?php echo $product_size; ?>_wrapper" style="margin-bottom:20px;">
    <div><img src="<?php echo ($image_meta_val!=''?wp_get_attachment_image_src( $image_meta_val)[0]:''); ?>" style="display: <?php echo ($image_meta_val!=''?'block':'none'); ?>" alt=""></div>
    <a class="addimage button" onclick="product_image_add_image('<?php echo $product_size; ?>');"><?php _e($product_size,'yourdomain'); ?></a><br>
    <a class="removeimage" style="color:#a00;cursor:pointer;display: <?php echo ($image_meta_val!=''?'block':'none'); ?>" onclick="product_image_remove_image('<?php echo $product_size; ?>');"><?php _e('remove image','yourdomain'); ?></a><br>
    <input type="hidden" name="<?php echo $product_size; ?>" id="<?php echo $product_size; ?>" value="<?php echo $image_meta_val; ?>" />
    <?php echo $product_size; ?>

    </div>
    <?php } ?>
    </div>

    <script>
    function product_image_add_image(key){

    var $wrapper = jQuery('#'+key+'_wrapper');

    product_image_uploader = wp.media.frames.file_frame = wp.media({
    title: '<?php _e('select image','yourdomain'); ?>',
    button: {
    text: '<?php _e('select image','yourdomain'); ?>'
    },
    multiple: true
    });
    product_image_uploader.on('select', function() {

    var attachment = product_image_uploader.state().get('selection').first().toJSON();
    var img_url = attachment['url'];
    var img_id = attachment['id'];
    $wrapper.find('input#'+key).val(img_id);
    $wrapper.find('img').attr('src',img_url);
    $wrapper.find('img').show();
    $wrapper.find('a.removeimage').show();
    });
    product_image_uploader.on('open', function(){
    var selection = product_image_uploader.state().get('selection');
    var selected = $wrapper.find('input#'+key).val();
    if(selected){
    selection.add(wp.media.attachment(selected));
    }
    });
    product_image_uploader.open();
    return false;
    }

    function product_image_remove_image(key){
    var $wrapper = jQuery('#'+key+'_wrapper');
    $wrapper.find('input#'+key).val('');
    $wrapper.find('img').hide();
    $wrapper.find('a.removeimage').hide();
    return false;
    }
    </script>
    <?php
    wp_nonce_field( 'product_image_meta_box', 'product_image_meta_box_nonce' );
    }

    function product_image_meta_box_save($post_id){

    if ( ! current_user_can( 'edit_posts', $post_id ) ){ return 'not permitted'; }

    if (isset( $_POST['product_image_meta_box_nonce'] ) && wp_verify_nonce($_POST['product_image_meta_box_nonce'],'product_image_meta_box' )){

    //same array as in product_image_meta_box_func($post)
    $product_sizes = wp_get_object_terms( $post->ID, 'unit', array( 'fields' => 'slugs' ));
    foreach($product_sizes as $product_size){
    if(isset($_POST[$product_size]) && intval($_POST[$product_size])!=''){
    update_post_meta( $post_id, $product_size, intval($_POST[$product_size]));
    }else{
    update_post_meta( $post_id, $product_size, '');
    }
    }
    }
    }

    Any ideas on how i can fix this? In powershell i would have written som $GetData = wp_get_object_terms( $post->ID, ‘unit’, array( ‘fields’ => ‘slugs’ ));
    Then cleanuped that $GetData with $Getdataclean, and then used $product_sizes = $GetdataClean.

    But I don’t know howto do that in PHP. Anyone out there with a good tip?

    Moderator bcworkz

    (@bcworkz)

    I think the error relates to line 113, not 20. In that function $post is out of scope, instead the post’s ID is passed, so the line should be:
    $product_sizes = wp_get_object_terms( $post_id, 'unit', array( 'fields' => 'slugs' ));

    I’m not sure what you’re asking with “I don’t know howto do that in PHP”. Do you wish to clear out a variable’s value to free up memory? If so you can use unset() or simply assign null to the variable.

    Next time you post a large amount of code like that, please use pastebin.com or gist.github.com and just provide the resulting link here. Doing so makes you code easier for others to read due line numbering and syntax highlighting. It’s OK to post short snippets in the forums, please refrain from posting large amounts of code here.

    Thread Starter Foley

    (@foley)

    Thanks for all your help @bcworkz! It’s working!:)

    Thread Starter Foley

    (@foley)

    No trying to get the front-end to work. On a post with a picture saved I cant find any metadata:

    I’ve added to small code lines, first comes up with false, second shows nothing:

    <?php
    $Extract = get_post_meta($post_id);
    echo "<pre>". json_encode($Extract, JSON_PRETTY_PRINT) . "</pre>";
    ?>

    <?php
    $myvals = get_post_meta($post_id);
    foreach($myvals as $key=>$val)
    {
    echo $key . ' : ' . $val[0] . '<br/>';
    }
    ?>

    Any other suggestions for troubleshooting?

    Moderator bcworkz

    (@bcworkz)

    What’s assigning the value of $post_id in that context? Getting false means the value of $post_id is invalid.

    FYI, for a single post page, one way to obtain the post’s ID is with get_queried_object_id(). Another way, assuming you’re within a traditional WP loop context, is with get_the_ID()

Viewing 10 replies - 1 through 10 (of 10 total)
  • You must be logged in to reply to this topic.