WordPress.org

Ready to get started?Download WordPress

Forums

Foreach loop inside widget update function? (4 posts)

  1. bronzehedwick
    Member
    Posted 1 year ago #

    I'm working on a widget that gets all available post types from the database and displays them as a list of checkboxes on the widget settings form. Checking each post type would filter the widget's output by that type.

    The number of checkbox elements is dynamic, so I'm using a foreach loop inside the update() function to save the settings, but this doesn't work. The same issue has been reported on stackoverflow with no answers.

    This is my code:

    function form($instance) {
    		$defaults   = array( 'num_posts' => 5 );
    		$instance   = wp_parse_args( (array) $instance, $defaults );
    		$num_posts  = $instance['num_posts'];
    
    		foreach ( get_post_types() as $post_type ) {
    			$post_types_array[$post_type] = $post_type;
    		}
    
    		$instance['post_types'] = $post_types_array;
    		$post_types = $instance['post_types'];
    
    		echo '
    <pre>';
    		print_r($instance);
    		echo '</pre>
    ';
    		?>
    
    			<p>Number of posts to show: <input class="widefat" name="<?php echo $this->get_field_name( 'num_posts' ); ?>" type="number" value="<?php echo esc_attr( $num_posts ); ?>" /></p>
    			<p>Filter by Post Type:
    <ul>
    			<?php foreach ( $post_types as $post_type ) { ?>
    
    <li><input name="<?php echo $this->get_field_name( $post_type ); ?>" type="checkbox" <?php checked( $this->get_field_name( $post_type ) ); ?> /><label for="<?php echo $this->get_field_name( $post_type ); ?>" /><?php echo $post_type; ?></label></li>
    <?php
    ?>
    			<?php
    		   } ?>
    			</ul>
    </p>
    
    		<?php
    	}
    
    	// save the widget settings
    	function update($new_instance, $old_instance) {
    		$instance = $old_instance;
    		$instance['num_posts'] = strip_tags( $new_instance['num_posts'] );
    
    		foreach ( $instance['post_types'] as $post_type ) {
    			$instance['post_types'][$post_type] = strip_tags( $new_instance['post_types'][$post_type] );
    		}
    
    		return $instance;
    	}

    This seems like something trivial I'm overlooking. Anyone have any leads? Thanks!

  2. Chris
    Member
    Posted 1 year ago #

    For example when post types 'post' and 'page' are checked $new_instance will be

    array
      'num_posts' => string '5' (length=1)
      'post' => string 'on' (length=2)
      'page' => string 'on' (length=2)

    and in line

    $instance['post_types'][$post_type] = strip_tags( $new_instance['post_types'][$post_type] );

    $new_instance['post_types'][$post_type] simply does not exist.

    Maybe that's a start

  3. bronzehedwick
    Member
    Posted 1 year ago #

    Thanks Chris!

    You're right, $new_instance['post_types'][$post_type] did not exist. I hacked around a bit and revised my code and I think I made progress; however, when running the update function the values still aren't being saved for $instance['post_type']. Not sure why this is happening, as $instance['num_posts'] works fine.

    // build the widget settings form
    	function form( $instance ) {
    		$defaults   = array( 'num_posts' => 5 );
    		$instance   = wp_parse_args( (array) $instance, $defaults );
    		$num_posts  = $instance['num_posts'];
    
        foreach ( get_post_types() as $post_type ) {
          $instance['post_types'] .= $post_type . ',';
        }
        $post_types = $instance['post_types'];
    		//echo '<pre>';
        //print_r($instance);
    		//echo '</pre>';
    
    		?>
    
    			<p>Number of posts to show: <input class="widefat" name="<?php echo $this->get_field_name( 'num_posts' ); ?>" type="number" value="<?php echo esc_attr( $num_posts ); ?>" /></p>
    			<p>Filter by Post Type: <ul>
    			<?php foreach ( get_post_types() as $post_type ) { ?>
    				<li><input name="<?php echo $this->get_field_name( $post_type ); ?>" type="checkbox" <?php checked( $this->get_field_name( $post_type ) ); ?> /><label for="<?php echo $this->get_field_name( $post_type ); ?>" /><?php echo $post_type; ?></label></li>
    			<?php
    		   } ?>
    			</ul></p>
    
    		<?php
        echo '<pre>';
        print_r($instance);
        echo '</pre>';
    	}
    
    	// save the widget settings
    	function update( $new_instance, $old_instance ) {
    		$instance = $old_instance;
    		$instance['num_posts'] = strip_tags( $new_instance['num_posts'] );
        $instance['post_types'] = strip_tags( $new_instance['post_types'] );
    
    		return $instance;
    	}
  4. Chris
    Member
    Posted 1 year ago #

    I have another but maybe "not so nice" solution :)

    function form( $instance ) {
    
        $defaults   = array( 'num_posts' => 5 );
    
        $num_posts = ( isset( $instance['num_posts'] ) && !empty( $instance['num_posts'] ) ) ? (int) $instance['num_posts'] : $defaults['num_posts'];
    
        echo '<p>Number of posts to show: <input class="widefat" name="' . $this->get_field_name( 'num_posts' ) . '" type="number" value="' . $num_posts . '" /></p>' . "\n";
        echo '<p>Filter by Post Type:' . "\n";
        echo "<ul>\n";
    
        foreach( get_post_types() as $post_type ) {
    
          echo '  <li><input name="' . $this->get_field_name( $post_type ) . '" type="checkbox"';
    
          if( isset( $instance[$post_type] ) && $instance[$post_type] == 'on' ) {
    
            echo ' checked="checked"';
    
          }
    
          echo ' /> <label>' . $post_type . "</label></li>\n";
    
        }
    
        echo "</ul>\n";
    
      }
    
      function update( $new_instance, $old_instance ) {
    
        /**
         * Of course you should do some validation before saving but the general
         * idea is not to use $old_instance but $new_instance.
         *
         * This would only work if don't have to "stack" some other options, I guess.
         */
        return $new_instance;
    
      }
    
      function widget( $args, $instance ) {
    
        /**
         * Match all existing post types against the widget options/$instance
         */
        $allPostTypes = get_post_types();
    
        /**
         * $post_types will be an array of all selected post types.
         */
        $post_types = array();
    
        foreach( $allPostTypes as $type ) {
    
          if( array_key_exists( $type, $instance ) ) {
            $post_types[] = $type;
          }
    
        }
    
        // var_dump( $post_types );
    
      }

Topic Closed

This topic has been closed to new replies.

About this Topic