/** * Navigation Menu functions * * @package WordPress * @subpackage Nav_Menus * @since 3.0.0 */ /** * Returns a navigation menu object. * * @since 3.0.0 * * @param int|string|WP_Term $menu Menu ID, slug, name, or object. * @return WP_Term|false Menu object on success, false if $menu param isn't supplied or term does not exist. */ function wp_get_nav_menu_object( $menu ) { $menu_obj = false; if ( is_object( $menu ) ) { $menu_obj = $menu; } if ( $menu && ! $menu_obj ) { $menu_obj = get_term( $menu, 'nav_menu' ); if ( ! $menu_obj ) { $menu_obj = get_term_by( 'slug', $menu, 'nav_menu' ); } if ( ! $menu_obj ) { $menu_obj = get_term_by( 'name', $menu, 'nav_menu' ); } } if ( ! $menu_obj || is_wp_error( $menu_obj ) ) { $menu_obj = false; } /** * Filters the nav_menu term retrieved for wp_get_nav_menu_object(). * * @since 4.3.0 * * @param WP_Term|false $menu_obj Term from nav_menu taxonomy, or false if nothing had been found. * @param int|string|WP_Term $menu The menu ID, slug, name, or object passed to wp_get_nav_menu_object(). */ return apply_filters( 'wp_get_nav_menu_object', $menu_obj, $menu ); } /** * Determines whether the given ID is a navigation menu. * * Returns true if it is; false otherwise. * * @since 3.0.0 * * @param int|string|WP_Term $menu Menu ID, slug, name, or object of menu to check. * @return bool Whether the menu exists. */ function is_nav_menu( $menu ) { if ( ! $menu ) { return false; } $menu_obj = wp_get_nav_menu_object( $menu ); if ( $menu_obj && ! is_wp_error( $menu_obj ) && ! empty( $menu_obj->taxonomy ) && 'nav_menu' === $menu_obj->taxonomy ) { return true; } return false; } /** * Registers navigation menu locations for a theme. * * @since 3.0.0 * * @global array $_wp_registered_nav_menus * * @param string[] $locations Associative array of menu location identifiers (like a slug) and descriptive text. */ function register_nav_menus( $locations = array() ) { global $_wp_registered_nav_menus; add_theme_support( 'menus' ); foreach ( $locations as $key => $value ) { if ( is_int( $key ) ) { _doing_it_wrong( __FUNCTION__, __( 'Nav menu locations must be strings.' ), '5.3.0' ); break; } } $_wp_registered_nav_menus = array_merge( (array) $_wp_registered_nav_menus, $locations ); } /** * Unregisters a navigation menu location for a theme. * * @since 3.1.0 * * @global array $_wp_registered_nav_menus * * @param string $location The menu location identifier. * @return bool True on success, false on failure. */ function unregister_nav_menu( $location ) { global $_wp_registered_nav_menus; if ( is_array( $_wp_registered_nav_menus ) && isset( $_wp_registered_nav_menus[ $location ] ) ) { unset( $_wp_registered_nav_menus[ $location ] ); if ( empty( $_wp_registered_nav_menus ) ) { _remove_theme_support( 'menus' ); } return true; } return false; } /** * Registers a navigation menu location for a theme. * * @since 3.0.0 * * @param string $location Menu location identifier, like a slug. * @param string $description Menu location descriptive text. */ function register_nav_menu( $location, $description ) { register_nav_menus( array( $location => $description ) ); } /** * Retrieves all registered navigation menu locations in a theme. * * @since 3.0.0 * * @global array $_wp_registered_nav_menus * * @return string[] Associative array of registered navigation menu descriptions keyed * by their location. If none are registered, an empty array. */ function get_registered_nav_menus() { global $_wp_registered_nav_menus; return $_wp_registered_nav_menus ?? array(); } /** * Retrieves all registered navigation menu locations and the menus assigned to them. * * @since 3.0.0 * * @return int[] Associative array of registered navigation menu IDs keyed by their * location name. If none are registered, an empty array. */ function get_nav_menu_locations() { $locations = get_theme_mod( 'nav_menu_locations' ); return ( is_array( $locations ) ) ? $locations : array(); } /** * Determines whether a registered nav menu location has a menu assigned to it. * * @since 3.0.0 * * @param string $location Menu location identifier. * @return bool Whether location has a menu. */ function has_nav_menu( $location ) { $has_nav_menu = false; $registered_nav_menus = get_registered_nav_menus(); if ( isset( $registered_nav_menus[ $location ] ) ) { $locations = get_nav_menu_locations(); $has_nav_menu = ! empty( $locations[ $location ] ); } /** * Filters whether a nav menu is assigned to the specified location. * * @since 4.3.0 * * @param bool $has_nav_menu Whether there is a menu assigned to a location. * @param string $location Menu location. */ return apply_filters( 'has_nav_menu', $has_nav_menu, $location ); } /** * Returns the name of a navigation menu. * * @since 4.9.0 * * @param string $location Menu location identifier. * @return string Menu name. */ function wp_get_nav_menu_name( $location ) { $menu_name = ''; $locations = get_nav_menu_locations(); if ( isset( $locations[ $location ] ) ) { $menu = wp_get_nav_menu_object( $locations[ $location ] ); if ( $menu && $menu->name ) { $menu_name = $menu->name; } } /** * Filters the navigation menu name being returned. * * @since 4.9.0 * * @param string $menu_name Menu name. * @param string $location Menu location identifier. */ return apply_filters( 'wp_get_nav_menu_name', $menu_name, $location ); } /** * Determines whether the given ID is a nav menu item. * * @since 3.0.0 * * @param int $menu_item_id The ID of the potential nav menu item. * @return bool Whether the given ID is that of a nav menu item. */ function is_nav_menu_item( $menu_item_id = 0 ) { return ( ! is_wp_error( $menu_item_id ) && ( 'nav_menu_item' === get_post_type( $menu_item_id ) ) ); } /** * Creates a navigation menu. * * Note that `$menu_name` is expected to be pre-slashed. * * @since 3.0.0 * * @param string $menu_name Menu name. * @return int|WP_Error Menu ID on success, WP_Error object on failure. */ function wp_create_nav_menu( $menu_name ) { // expected_slashed ($menu_name) return wp_update_nav_menu_object( 0, array( 'menu-name' => $menu_name ) ); } /** * Deletes a navigation menu. * * @since 3.0.0 * * @param int|string|WP_Term $menu Menu ID, slug, name, or object. * @return bool|WP_Error True on success, false or WP_Error object on failure. */ function wp_delete_nav_menu( $menu ) { $menu = wp_get_nav_menu_object( $menu ); if ( ! $menu ) { return false; } $menu_objects = get_objects_in_term( $menu->term_id, 'nav_menu' ); if ( ! empty( $menu_objects ) ) { foreach ( $menu_objects as $item ) { wp_delete_post( $item ); } } $result = wp_delete_term( $menu->term_id, 'nav_menu' ); // Remove this menu from any locations. $locations = get_nav_menu_locations(); foreach ( $locations as $location => $menu_id ) { if ( $menu_id === $menu->term_id ) { $locations[ $location ] = 0; } } set_theme_mod( 'nav_menu_locations', $locations ); if ( $result && ! is_wp_error( $result ) ) { /** * Fires after a navigation menu has been successfully deleted. * * @since 3.0.0 * * @param int $term_id ID of the deleted menu. */ do_action( 'wp_delete_nav_menu', $menu->term_id ); } return $result; } /** * Saves the properties of a menu or create a new menu with those properties. * * Note that `$menu_data` is expected to be pre-slashed. * * @since 3.0.0 * * @param int $menu_id The ID of the menu or "0" to create a new menu. * @param array $menu_data The array of menu data. * @return int|WP_Error Menu ID on success, WP_Error object on failure. */ function wp_update_nav_menu_object( $menu_id = 0, $menu_data = array() ) { // expected_slashed ($menu_data) $menu_id = (int) $menu_id; $_menu = wp_get_nav_menu_object( $menu_id ); $args = array( 'description' => $menu_data['description'] ?? '', 'name' => $menu_data['menu-name'] ?? '', 'parent' => ( isset( $menu_data['parent'] ) ? (int) $menu_data['parent'] : 0 ), 'slug' => null, ); // Double-check that we're not going to have one menu take the name of another. $_possible_existing = get_term_by( 'name', $menu_data['menu-name'], 'nav_menu' ); if ( $_possible_existing && ! is_wp_error( $_possible_existing ) && isset( $_possible_existing->term_id ) && $_possible_existing->term_id !== $menu_id ) { return new WP_Error( 'menu_exists', sprintf( /* translators: %s: Menu name. */ __( 'The menu name %s conflicts with another menu name. Please try another.' ), '' . esc_html( $menu_data['menu-name'] ) . '' ) ); } // Menu doesn't already exist, so create a new menu. if ( ! $_menu || is_wp_error( $_menu ) ) { $menu_exists = get_term_by( 'name', $menu_data['menu-name'], 'nav_menu' ); if ( $menu_exists ) { return new WP_Error( 'menu_exists', sprintf( /* translators: %s: Menu name. */ __( 'The menu name %s conflicts with another menu name. Please try another.' ), '' . esc_html( $menu_data['menu-name'] ) . '' ) ); } $_menu = wp_insert_term( $menu_data['menu-name'], 'nav_menu', $args ); if ( is_wp_error( $_menu ) ) { return $_menu; } /** * Fires after a navigation menu is successfully created. * * @since 3.0.0 * * @param int $term_id ID of the new menu. * @param array $menu_data An array of menu data. */ do_action( 'wp_create_nav_menu', $_menu['term_id'], $menu_data ); return (int) $_menu['term_id']; } if ( ! $_menu || ! isset( $_menu->term_id ) ) { return 0; } $menu_id = (int) $_menu->term_id; $update_response = wp_update_term( $menu_id, 'nav_menu', $args ); if ( is_wp_error( $update_response ) ) { return $update_response; } $menu_id = (int) $update_response['term_id']; /** * Fires after a navigation menu has been successfully updated. * * @since 3.0.0 * * @param int $menu_id ID of the updated menu. * @param array $menu_data An array of menu data. */ do_action( 'wp_update_nav_menu', $menu_id, $menu_data ); return $menu_id; } /** * Saves the properties of a menu item or create a new one. * * The menu-item-title, menu-item-description and menu-item-attr-title are expected * to be pre-slashed since they are passed directly to APIs that expect slashed data. * * @since 3.0.0 * @since 5.9.0 Added the `$fire_after_hooks` parameter. * * @param int $menu_id The ID of the menu. If 0, makes the menu item a draft orphan. * @param int $menu_item_db_id The ID of the menu item. If 0, creates a new menu item. * @param array $menu_item_data The menu item's data. * @param bool $fire_after_hooks Whether to fire the after insert hooks. Default true. * @return int|WP_Error The menu item's database ID or WP_Error object on failure. */ function wp_update_nav_menu_item( $menu_id = 0, $menu_item_db_id = 0, $menu_item_data = array(), $fire_after_hooks = true ) { $menu_id = (int) $menu_id; $menu_item_db_id = (int) $menu_item_db_id; // Make sure that we don't convert non-nav_menu_item objects into nav_menu_item objects. if ( ! empty( $menu_item_db_id ) && ! is_nav_menu_item( $menu_item_db_id ) ) { return new WP_Error( 'update_nav_menu_item_failed', __( 'The given object ID is not that of a menu item.' ) ); } $menu = wp_get_nav_menu_object( $menu_id ); if ( ! $menu && 0 !== $menu_id ) { return new WP_Error( 'invalid_menu_id', __( 'Invalid menu ID.' ) ); } if ( is_wp_error( $menu ) ) { return $menu; } $defaults = array( 'menu-item-db-id' => $menu_item_db_id, 'menu-item-object-id' => 0, 'menu-item-object' => '', 'menu-item-parent-id' => 0, 'menu-item-position' => 0, 'menu-item-type' => 'custom', 'menu-item-title' => '', 'menu-item-url' => '', 'menu-item-description' => '', 'menu-item-attr-title' => '', 'menu-item-target' => '', 'menu-item-classes' => '', 'menu-item-xfn' => '', 'menu-item-status' => '', 'menu-item-post-date' => '', 'menu-item-post-date-gmt' => '', ); $args = wp_parse_args( $menu_item_data, $defaults ); if ( 0 === $menu_id ) { $args['menu-item-position'] = 1; } elseif ( 0 === (int) $args['menu-item-position'] ) { $menu_items = array(); if ( 0 !== $menu_id ) { $menu_items = (array) wp_get_nav_menu_items( $menu_id, array( 'post_status' => 'publish,draft' ) ); } $last_item = array_pop( $menu_items ); if ( $last_item && isset( $last_item->menu_order ) ) { $args['menu-item-position'] = 1 + $last_item->menu_order; } else { $args['menu-item-position'] = count( $menu_items ); } } $original_parent = 0 < $menu_item_db_id ? get_post_field( 'post_parent', $menu_item_db_id ) : 0; if ( 'custom' === $args['menu-item-type'] ) { // If custom menu item, trim the URL. $args['menu-item-url'] = trim( $args['menu-item-url'] ); } else { /* * If non-custom menu item, then: * - use the original object's URL. * - blank default title to sync with the original object's title. */ $args['menu-item-url'] = ''; $original_title = ''; if ( 'taxonomy' === $args['menu-item-type'] ) { $original_object = get_term( $args['menu-item-object-id'], $args['menu-item-object'] ); if ( $original_object instanceof WP_Term ) { $original_parent = get_term_field( 'parent', $args['menu-item-object-id'], $args['menu-item-object'], 'raw' ); $original_title = get_term_field( 'name', $args['menu-item-object-id'], $args['menu-item-object'], 'raw' ); } } elseif ( 'post_type' === $args['menu-item-type'] ) { $original_object = get_post( $args['menu-item-object-id'] ); if ( $original_object instanceof WP_Post ) { $original_parent = (int) $original_object->post_parent; $original_title = $original_object->post_title; } } elseif ( 'post_type_archive' === $args['menu-item-type'] ) { $original_object = get_post_type_object( $args['menu-item-object'] ); if ( $original_object instanceof WP_Post_Type ) { $original_title = $original_object->labels->archives; } } if ( wp_unslash( $args['menu-item-title'] ) === $original_title ) { $args['menu-item-title'] = ''; } // Hack to get wp to create a post object when too many properties are empty. if ( '' === $args['menu-item-title'] && '' === $args['menu-item-description'] ) { $args['menu-item-description'] = ' '; } } // Populate the menu item object. $post = array( 'menu_order' => $args['menu-item-position'], 'ping_status' => 0, 'post_content' => $args['menu-item-description'], 'post_excerpt' => $args['menu-item-attr-title'], 'post_parent' => $original_parent, 'post_title' => $args['menu-item-title'], 'post_type' => 'nav_menu_item', ); $post_date = wp_resolve_post_date( $args['menu-item-post-date'], $args['menu-item-post-date-gmt'] ); if ( $post_date ) { $post['post_date'] = $post_date; } $update = 0 !== $menu_item_db_id; // New menu item. Default is draft status. if ( ! $update ) { $post['ID'] = 0; $post['post_status'] = 'publish' === $args['menu-item-status'] ? 'publish' : 'draft'; $menu_item_db_id = wp_insert_post( $post, true, $fire_after_hooks ); if ( ! $menu_item_db_id || is_wp_error( $menu_item_db_id ) ) { return $menu_item_db_id; } /** * Fires immediately after a new navigation menu item has been added. * * @since 4.4.0 * * @see wp_update_nav_menu_item() * * @param int $menu_id ID of the updated menu. * @param int $menu_item_db_id ID of the new menu item. * @param array $args An array of arguments used to update/add the menu item. */ do_action( 'wp_add_nav_menu_item', $menu_id, $menu_item_db_id, $args ); } /* * Associate the menu item with the menu term. * Only set the menu term if it isn't set to avoid unnecessary wp_get_object_terms(). */ if ( $menu_id && ( ! $update || ! is_object_in_term( $menu_item_db_id, 'nav_menu', (int) $menu->term_id ) ) ) { $update_terms = wp_set_object_terms( $menu_item_db_id, array( $menu->term_id ), 'nav_menu' ); if ( is_wp_error( $update_terms ) ) { return $update_terms; } } if ( 'custom' === $args['menu-item-type'] ) { $args['menu-item-object-id'] = $menu_item_db_id; $args['menu-item-object'] = 'custom'; } $menu_item_db_id = (int) $menu_item_db_id; // Reset invalid `menu_item_parent`. if ( (int) $args['menu-item-parent-id'] === $menu_item_db_id ) { $args['menu-item-parent-id'] = 0; } update_post_meta( $menu_item_db_id, '_menu_item_type', sanitize_key( $args['menu-item-type'] ) ); update_post_meta( $menu_item_db_id, '_menu_item_menu_item_parent', (string) ( (int) $args['menu-item-parent-id'] ) ); update_post_meta( $menu_item_db_id, '_menu_item_object_id', (string) ( (int) $args['menu-item-object-id'] ) ); update_post_meta( $menu_item_db_id, '_menu_item_object', sanitize_key( $args['menu-item-object'] ) ); update_post_meta( $menu_item_db_id, '_menu_item_target', sanitize_key( $args['menu-item-target'] ) ); $args['menu-item-classes'] = array_map( 'sanitize_html_class', explode( ' ', $args['menu-item-classes'] ) ); $args['menu-item-xfn'] = implode( ' ', array_map( 'sanitize_html_class', explode( ' ', $args['menu-item-xfn'] ) ) ); update_post_meta( $menu_item_db_id, '_menu_item_classes', $args['menu-item-classes'] ); update_post_meta( $menu_item_db_id, '_menu_item_xfn', $args['menu-item-xfn'] ); update_post_meta( $menu_item_db_id, '_menu_item_url', sanitize_url( $args['menu-item-url'] ) ); if ( 0 === $menu_id ) { update_post_meta( $menu_item_db_id, '_menu_item_orphaned', (string) time() ); } elseif ( get_post_meta( $menu_item_db_id, '_menu_item_orphaned' ) ) { delete_post_meta( $menu_item_db_id, '_menu_item_orphaned' ); } // Update existing menu item. Default is publish status. if ( $update ) { $post['ID'] = $menu_item_db_id; $post['post_status'] = ( 'draft' === $args['menu-item-status'] ) ? 'draft' : 'publish'; $update_post = wp_update_post( $post, true ); if ( is_wp_error( $update_post ) ) { return $update_post; } } /** * Fires after a navigation menu item has been updated. * * @since 3.0.0 * * @see wp_update_nav_menu_item() * * @param int $menu_id ID of the updated menu. * @param int $menu_item_db_id ID of the updated menu item. * @param array $args An array of arguments used to update a menu item. */ do_action( 'wp_update_nav_menu_item', $menu_id, $menu_item_db_id, $args ); return $menu_item_db_id; } /** * Returns all navigation menu objects. * * @since 3.0.0 * @since 4.1.0 Default value of the 'orderby' argument was changed from 'none' * to 'name'. * * @param array $args Optional. Array of arguments passed on to get_terms(). * Default empty array. * @return WP_Term[] An array of menu objects. */ function wp_get_nav_menus( $args = array() ) { $defaults = array( 'taxonomy' => 'nav_menu', 'hide_empty' => false, 'orderby' => 'name', ); $args = wp_parse_args( $args, $defaults ); /** * Filters the navigation menu objects being returned. * * @since 3.0.0 * * @see get_terms() * * @param WP_Term[] $menus An array of menu objects. * @param array $args An array of arguments used to retrieve menu objects. */ return apply_filters( 'wp_get_nav_menus', get_terms( $args ), $args ); } /** * Determines whether a menu item is valid. * * @link https://core.trac.wordpress.org/ticket/13958 * * @since 3.2.0 * @access private * * @param object $item The menu item to check. * @return bool False if invalid, otherwise true. */ function _is_valid_nav_menu_item( $item ) { return empty( $item->_invalid ); } /** * Retrieves all menu items of a navigation menu. * * Note: Most arguments passed to the `$args` parameter – save for 'output_key' – are * specifically for retrieving nav_menu_item posts from get_posts() and may only * indirectly affect the ultimate ordering and content of the resulting nav menu * items that get returned from this function. * * @since 3.0.0 * * @param int|string|WP_Term $menu Menu ID, slug, name, or object. * @param array $args { * Optional. Arguments to pass to get_posts(). * * @type string $order How to order nav menu items as queried with get_posts(). * Will be ignored if 'output' is ARRAY_A. Default 'ASC'. * @type string $orderby Field to order menu items by as retrieved from get_posts(). * Supply an orderby field via 'output_key' to affect the * output order of nav menu items. Default 'menu_order'. * @type string $post_type Menu items post type. Default 'nav_menu_item'. * @type string $post_status Menu items post status. Default 'publish'. * @type string $output How to order outputted menu items. Default ARRAY_A. * @type string $output_key Key to use for ordering the actual menu items that get * returned. Note that that is not a get_posts() argument * and will only affect output of menu items processed in * this function. Default 'menu_order'. * @type bool $nopaging Whether to retrieve all menu items (true) or paginate * (false). Default true. * @type bool $update_menu_item_cache Whether to update the menu item cache. Default true. * } * @return array|false Array of menu items, otherwise false. */ function wp_get_nav_menu_items( $menu, $args = array() ) { $menu = wp_get_nav_menu_object( $menu ); if ( ! $menu ) { return false; } if ( ! taxonomy_exists( 'nav_menu' ) ) { return false; } $defaults = array( 'order' => 'ASC', 'orderby' => 'menu_order', 'post_type' => 'nav_menu_item', 'post_status' => 'publish', 'output' => ARRAY_A, 'output_key' => 'menu_order', 'nopaging' => true, 'update_menu_item_cache' => true, 'tax_query' => array( array( 'taxonomy' => 'nav_menu', 'field' => 'term_taxonomy_id', 'terms' => $menu->term_taxonomy_id, ), ), ); $args = wp_parse_args( $args, $defaults ); if ( $menu->count > 0 ) { $items = get_posts( $args ); } else { $items = array(); } $items = array_map( 'wp_setup_nav_menu_item', $items ); if ( ! is_admin() ) { // Remove invalid items only on front end. $items = array_filter( $items, '_is_valid_nav_menu_item' ); } if ( ARRAY_A === $args['output'] ) { $items = wp_list_sort( $items, array( $args['output_key'] => 'ASC', ) ); $i = 1; foreach ( $items as $k => $item ) { $items[ $k ]->{$args['output_key']} = $i++; } } /** * Filters the navigation menu items being returned. * * @since 3.0.0 * * @param array $items An array of menu item post objects. * @param object $menu The menu object. * @param array $args An array of arguments used to retrieve menu item objects. */ return apply_filters( 'wp_get_nav_menu_items', $items, $menu, $args ); } /** * Updates post and term caches for all linked objects for a list of menu items. * * @since 6.1.0 * * @param WP_Post[] $menu_items Array of menu item post objects. */ function update_menu_item_cache( $menu_items ) { $post_ids = array(); $term_ids = array(); foreach ( $menu_items as $menu_item ) { if ( 'nav_menu_item' !== $menu_item->post_type ) { continue; } $object_id = get_post_meta( $menu_item->ID, '_menu_item_object_id', true ); $type = get_post_meta( $menu_item->ID, '_menu_item_type', true ); if ( 'post_type' === $type ) { $post_ids[] = (int) $object_id; } elseif ( 'taxonomy' === $type ) { $term_ids[] = (int) $object_id; } } if ( ! empty( $post_ids ) ) { _prime_post_caches( $post_ids, false ); } if ( ! empty( $term_ids ) ) { _prime_term_caches( $term_ids ); } } /** * Decorates a menu item object with the shared navigation menu item properties. * * Properties: * - ID: The term_id if the menu item represents a taxonomy term. * - attr_title: The title attribute of the link element for this menu item. * - classes: The array of class attribute values for the link element of this menu item. * - db_id: The DB ID of this item as a nav_menu_item object, if it exists (0 if it doesn't exist). * - description: The description of this menu item. * - menu_item_parent: The DB ID of the nav_menu_item that is this item's menu parent, if any. 0 otherwise. * - object: The type of object originally represented, such as 'category', 'post', or 'attachment'. * - object_id: The DB ID of the original object this menu item represents, e.g. ID for posts and term_id for categories. * - post_parent: The DB ID of the original object's parent object, if any (0 otherwise). * - post_title: A "no title" label if menu item represents a post that lacks a title. * - target: The target attribute of the link element for this menu item. * - title: The title of this menu item. * - type: The family of objects originally represented, such as 'post_type' or 'taxonomy'. * - type_label: The singular label used to describe this type of menu item. * - url: The URL to which this menu item points. * - xfn: The XFN relationship expressed in the link of this menu item. * - _invalid: Whether the menu item represents an object that no longer exists. * * @since 3.0.0 * * @param object $menu_item The menu item to modify. * @return object The menu item with standard menu item properties. */ function wp_setup_nav_menu_item( $menu_item ) { /** * Filters whether to short-circuit the wp_setup_nav_menu_item() output. * * Returning a non-null value from the filter will short-circuit wp_setup_nav_menu_item(), * returning that value instead. * * @since 6.3.0 * * @param object|null $modified_menu_item Modified menu item. Default null. * @param object $menu_item The menu item to modify. */ $pre_menu_item = apply_filters( 'pre_wp_setup_nav_menu_item', null, $menu_item ); if ( null !== $pre_menu_item ) { return $pre_menu_item; } if ( isset( $menu_item->post_type ) ) { if ( 'nav_menu_item' === $menu_item->post_type ) { $menu_item->db_id = (int) $menu_item->ID; $menu_item->menu_item_parent = ! isset( $menu_item->menu_item_parent ) ? get_post_meta( $menu_item->ID, '_menu_item_menu_item_parent', true ) : $menu_item->menu_item_parent; $menu_item->object_id = ! isset( $menu_item->object_id ) ? get_post_meta( $menu_item->ID, '_menu_item_object_id', true ) : $menu_item->object_id; $menu_item->object = ! isset( $menu_item->object ) ? get_post_meta( $menu_item->ID, '_menu_item_object', true ) : $menu_item->object; $menu_item->type = ! isset( $menu_item->type ) ? get_post_meta( $menu_item->ID, '_menu_item_type', true ) : $menu_item->type; if ( 'post_type' === $menu_item->type ) { $object = get_post_type_object( $menu_item->object ); if ( $object ) { $menu_item->type_label = $object->labels->singular_name; // Denote post states for special pages (only in the admin). if ( function_exists( 'get_post_states' ) ) { $menu_post = get_post( $menu_item->object_id ); if ( $menu_post instanceof WP_Post ) { $post_states = get_post_states( $menu_post ); if ( $post_states ) { $menu_item->type_label = wp_strip_all_tags( implode( ', ', $post_states ) ); } } } } else { $menu_item->type_label = $menu_item->object; $menu_item->_invalid = true; } if ( 'trash' === get_post_status( $menu_item->object_id ) ) { $menu_item->_invalid = true; } $original_object = get_post( $menu_item->object_id ); if ( $original_object ) { $menu_item->url = get_permalink( $original_object->ID ); /** This filter is documented in wp-includes/post-template.php */ $original_title = apply_filters( 'the_title', $original_object->post_title, $original_object->ID ); } else { $menu_item->url = ''; $original_title = ''; $menu_item->_invalid = true; } if ( '' === $original_title ) { /* translators: %d: ID of a post. */ $original_title = sprintf( __( '#%d (no title)' ), $menu_item->object_id ); } $menu_item->title = ( '' === $menu_item->post_title ) ? $original_title : $menu_item->post_title; } elseif ( 'post_type_archive' === $menu_item->type ) { $object = get_post_type_object( $menu_item->object ); if ( $object ) { $menu_item->title = ( '' === $menu_item->post_title ) ? $object->labels->archives : $menu_item->post_title; $post_type_description = $object->description; } else { $post_type_description = ''; $menu_item->_invalid = true; } $menu_item->type_label = __( 'Post Type Archive' ); $post_content = wp_trim_words( $menu_item->post_content, 200 ); $post_type_description = ( '' === $post_content ) ? $post_type_description : $post_content; $menu_item->url = get_post_type_archive_link( $menu_item->object ); } elseif ( 'taxonomy' === $menu_item->type ) { $object = get_taxonomy( $menu_item->object ); if ( $object ) { $menu_item->type_label = $object->labels->singular_name; } else { $menu_item->type_label = $menu_item->object; $menu_item->_invalid = true; } $original_object = get_term( (int) $menu_item->object_id, $menu_item->object ); if ( $original_object && ! is_wp_error( $original_object ) ) { $menu_item->url = get_term_link( (int) $menu_item->object_id, $menu_item->object ); $original_title = $original_object->name; } else { $menu_item->url = ''; $original_title = ''; $menu_item->_invalid = true; } if ( '' === $original_title ) { /* translators: %d: ID of a term. */ $original_title = sprintf( __( '#%d (no title)' ), $menu_item->object_id ); } $menu_item->title = ( '' === $menu_item->post_title ) ? $original_title : $menu_item->post_title; } else { $menu_item->type_label = __( 'Custom Link' ); $menu_item->title = $menu_item->post_title; $menu_item->url = ! isset( $menu_item->url ) ? get_post_meta( $menu_item->ID, '_menu_item_url', true ) : $menu_item->url; } $menu_item->target = ! isset( $menu_item->target ) ? get_post_meta( $menu_item->ID, '_menu_item_target', true ) : $menu_item->target; /** * Filters a navigation menu item's title attribute. * * @since 3.0.0 * * @param string $item_title The menu item title attribute. */ $menu_item->attr_title = ! isset( $menu_item->attr_title ) ? apply_filters( 'nav_menu_attr_title', $menu_item->post_excerpt ) : $menu_item->attr_title; if ( ! isset( $menu_item->description ) ) { /** * Filters a navigation menu item's description. * * @since 3.0.0 * * @param string $description The menu item description. */ $menu_item->description = apply_filters( 'nav_menu_description', wp_trim_words( $menu_item->post_content, 200 ) ); } $menu_item->classes = ! isset( $menu_item->classes ) ? (array) get_post_meta( $menu_item->ID, '_menu_item_classes', true ) : $menu_item->classes; $menu_item->xfn = ! isset( $menu_item->xfn ) ? get_post_meta( $menu_item->ID, '_menu_item_xfn', true ) : $menu_item->xfn; } else { $menu_item->db_id = 0; $menu_item->menu_item_parent = 0; $menu_item->object_id = (int) $menu_item->ID; $menu_item->type = 'post_type'; $object = get_post_type_object( $menu_item->post_type ); $menu_item->object = $object->name; $menu_item->type_label = $object->labels->singular_name; if ( '' === $menu_item->post_title ) { /* translators: %d: ID of a post. */ $menu_item->post_title = sprintf( __( '#%d (no title)' ), $menu_item->ID ); } $menu_item->title = $menu_item->post_title; $menu_item->url = get_permalink( $menu_item->ID ); $menu_item->target = ''; /** This filter is documented in wp-includes/nav-menu.php */ $menu_item->attr_title = apply_filters( 'nav_menu_attr_title', '' ); /** This filter is documented in wp-includes/nav-menu.php */ $menu_item->description = apply_filters( 'nav_menu_description', '' ); $menu_item->classes = array(); $menu_item->xfn = ''; } } elseif ( isset( $menu_item->taxonomy ) ) { $menu_item->ID = $menu_item->term_id; $menu_item->db_id = 0; $menu_item->menu_item_parent = 0; $menu_item->object_id = (int) $menu_item->term_id; $menu_item->post_parent = (int) $menu_item->parent; $menu_item->type = 'taxonomy'; $object = get_taxonomy( $menu_item->taxonomy ); $menu_item->object = $object->name; $menu_item->type_label = $object->labels->singular_name; $menu_item->title = $menu_item->name; $menu_item->url = get_term_link( $menu_item, $menu_item->taxonomy ); $menu_item->target = ''; $menu_item->attr_title = ''; $menu_item->description = get_term_field( 'description', $menu_item->term_id, $menu_item->taxonomy ); $menu_item->classes = array(); $menu_item->xfn = ''; } /** * Filters a navigation menu item object. * * @since 3.0.0 * * @param object $menu_item The menu item object. */ return apply_filters( 'wp_setup_nav_menu_item', $menu_item ); } /** * Returns the menu items associated with a particular object. * * @since 3.0.0 * * @param int $object_id Optional. The ID of the original object. Default 0. * @param string $object_type Optional. The type of object, such as 'post_type' or 'taxonomy'. * Default 'post_type'. * @param string $taxonomy Optional. If $object_type is 'taxonomy', $taxonomy is the name * of the tax that $object_id belongs to. Default empty. * @return int[] The array of menu item IDs; empty array if none. */ function wp_get_associated_nav_menu_items( $object_id = 0, $object_type = 'post_type', $taxonomy = '' ) { $object_id = (int) $object_id; $menu_item_ids = array(); $query = new WP_Query(); $menu_items = $query->query( array( 'meta_key' => '_menu_item_object_id', 'meta_value' => $object_id, 'post_status' => 'any', 'post_type' => 'nav_menu_item', 'posts_per_page' => -1, ) ); foreach ( (array) $menu_items as $menu_item ) { if ( isset( $menu_item->ID ) && is_nav_menu_item( $menu_item->ID ) ) { $menu_item_type = get_post_meta( $menu_item->ID, '_menu_item_type', true ); if ( 'post_type' === $object_type && 'post_type' === $menu_item_type ) { $menu_item_ids[] = (int) $menu_item->ID; } elseif ( 'taxonomy' === $object_type && 'taxonomy' === $menu_item_type && get_post_meta( $menu_item->ID, '_menu_item_object', true ) === $taxonomy ) { $menu_item_ids[] = (int) $menu_item->ID; } } } return array_unique( $menu_item_ids ); } /** * Callback for handling a menu item when its original object is deleted. * * @since 3.0.0 * @access private * * @param int $object_id The ID of the original object being trashed. */ function _wp_delete_post_menu_item( $object_id ) { $object_id = (int) $object_id; $menu_item_ids = wp_get_associated_nav_menu_items( $object_id, 'post_type' ); foreach ( (array) $menu_item_ids as $menu_item_id ) { wp_delete_post( $menu_item_id, true ); } } /** * Serves as a callback for handling a menu item when its original object is deleted. * * @since 3.0.0 * @access private * * @param int $object_id The ID of the original object being trashed. * @param int $tt_id Term taxonomy ID. Unused. * @param string $taxonomy Taxonomy slug. */ function _wp_delete_tax_menu_item( $object_id, $tt_id, $taxonomy ) { $object_id = (int) $object_id; $menu_item_ids = wp_get_associated_nav_menu_items( $object_id, 'taxonomy', $taxonomy ); foreach ( (array) $menu_item_ids as $menu_item_id ) { wp_delete_post( $menu_item_id, true ); } } /** * Automatically add newly published page objects to menus with that as an option. * * @since 3.0.0 * @access private * * @param string $new_status The new status of the post object. * @param string $old_status The old status of the post object. * @param WP_Post $post The post object being transitioned from one status to another. */ function _wp_auto_add_pages_to_menu( $new_status, $old_status, $post ) { if ( 'publish' !== $new_status || 'publish' === $old_status || 'page' !== $post->post_type ) { return; } if ( ! empty( $post->post_parent ) ) { return; } $auto_add = get_option( 'nav_menu_options' ); if ( empty( $auto_add ) || ! is_array( $auto_add ) || ! isset( $auto_add['auto_add'] ) ) { return; } $auto_add = $auto_add['auto_add']; if ( empty( $auto_add ) || ! is_array( $auto_add ) ) { return; } $args = array( 'menu-item-object-id' => $post->ID, 'menu-item-object' => $post->post_type, 'menu-item-type' => 'post_type', 'menu-item-status' => 'publish', ); foreach ( $auto_add as $menu_id ) { $items = wp_get_nav_menu_items( $menu_id, array( 'post_status' => 'publish,draft' ) ); if ( ! is_array( $items ) ) { continue; } foreach ( $items as $item ) { if ( $post->ID === (int) $item->object_id ) { continue 2; } } wp_update_nav_menu_item( $menu_id, 0, $args ); } } /** * Deletes auto-draft posts associated with the supplied changeset. * * @since 4.8.0 * @access private * * @param int $post_id Post ID for the customize_changeset. */ function _wp_delete_customize_changeset_dependent_auto_drafts( $post_id ) { $post = get_post( $post_id ); if ( ! $post || 'customize_changeset' !== $post->post_type ) { return; } $data = json_decode( $post->post_content, true ); if ( empty( $data['nav_menus_created_posts']['value'] ) ) { return; } remove_action( 'delete_post', '_wp_delete_customize_changeset_dependent_auto_drafts' ); foreach ( $data['nav_menus_created_posts']['value'] as $stub_post_id ) { if ( empty( $stub_post_id ) ) { continue; } if ( 'auto-draft' === get_post_status( $stub_post_id ) ) { wp_delete_post( $stub_post_id, true ); } elseif ( 'draft' === get_post_status( $stub_post_id ) ) { wp_trash_post( $stub_post_id ); delete_post_meta( $stub_post_id, '_customize_changeset_uuid' ); } } add_action( 'delete_post', '_wp_delete_customize_changeset_dependent_auto_drafts' ); } /** * Handles menu config after theme change. * * @access private * @since 4.9.0 */ function _wp_menus_changed() { $old_nav_menu_locations = get_option( 'theme_switch_menu_locations', array() ); $new_nav_menu_locations = get_nav_menu_locations(); $mapped_nav_menu_locations = wp_map_nav_menu_locations( $new_nav_menu_locations, $old_nav_menu_locations ); set_theme_mod( 'nav_menu_locations', $mapped_nav_menu_locations ); delete_option( 'theme_switch_menu_locations' ); } /** * Maps nav menu locations according to assignments in previously active theme. * * @since 4.9.0 * * @param array $new_nav_menu_locations New nav menu locations assignments. * @param array $old_nav_menu_locations Old nav menu locations assignments. * @return array Nav menus mapped to new nav menu locations. */ function wp_map_nav_menu_locations( $new_nav_menu_locations, $old_nav_menu_locations ) { $registered_nav_menus = get_registered_nav_menus(); $new_nav_menu_locations = array_intersect_key( $new_nav_menu_locations, $registered_nav_menus ); // Short-circuit if there are no old nav menu location assignments to map. if ( empty( $old_nav_menu_locations ) ) { return $new_nav_menu_locations; } // If old and new theme have just one location, map it and we're done. if ( 1 === count( $old_nav_menu_locations ) && 1 === count( $registered_nav_menus ) ) { $new_nav_menu_locations[ key( $registered_nav_menus ) ] = array_pop( $old_nav_menu_locations ); return $new_nav_menu_locations; } $old_locations = array_keys( $old_nav_menu_locations ); // Map locations with the same slug. foreach ( $registered_nav_menus as $location => $name ) { if ( in_array( $location, $old_locations, true ) ) { $new_nav_menu_locations[ $location ] = $old_nav_menu_locations[ $location ]; unset( $old_nav_menu_locations[ $location ] ); } } // If there are no old nav menu locations left, then we're done. if ( empty( $old_nav_menu_locations ) ) { return $new_nav_menu_locations; } /* * If old and new theme both have locations that contain phrases * from within the same group, make an educated guess and map it. */ $common_slug_groups = array( array( 'primary', 'menu-1', 'main', 'header', 'navigation', 'top' ), array( 'secondary', 'menu-2', 'footer', 'subsidiary', 'bottom' ), array( 'social' ), ); // Go through each group... foreach ( $common_slug_groups as $slug_group ) { // ...and see if any of these slugs... foreach ( $slug_group as $slug ) { // ...and any of the new menu locations... foreach ( $registered_nav_menus as $new_location => $name ) { // ...actually match! if ( is_string( $new_location ) && false === stripos( $new_location, $slug ) && false === stripos( $slug, $new_location ) ) { continue; } elseif ( is_numeric( $new_location ) && $new_location !== $slug ) { continue; } // Then see if any of the old locations... foreach ( $old_nav_menu_locations as $location => $menu_id ) { // ...and any slug in the same group... foreach ( $slug_group as $slug ) { // ... have a match as well. if ( is_string( $location ) && false === stripos( $location, $slug ) && false === stripos( $slug, $location ) ) { continue; } elseif ( is_numeric( $location ) && $location !== $slug ) { continue; } // Make sure this location wasn't mapped and removed previously. if ( ! empty( $old_nav_menu_locations[ $location ] ) ) { // We have a match that can be mapped! $new_nav_menu_locations[ $new_location ] = $old_nav_menu_locations[ $location ]; // Remove the mapped location so it can't be mapped again. unset( $old_nav_menu_locations[ $location ] ); // Go back and check the next new menu location. continue 3; } } // End foreach ( $slug_group as $slug ). } // End foreach ( $old_nav_menu_locations as $location => $menu_id ). } // End foreach foreach ( $registered_nav_menus as $new_location => $name ). } // End foreach ( $slug_group as $slug ). } // End foreach ( $common_slug_groups as $slug_group ). return $new_nav_menu_locations; } /** * Prevents menu items from being their own parent. * * Resets menu_item_parent to 0 when the parent is set to the item itself. * For use before saving `_menu_item_menu_item_parent` in nav-menus.php. * * @since 6.2.0 * @access private * * @param array $menu_item_data The menu item data array. * @return array The menu item data with reset menu_item_parent. */ function _wp_reset_invalid_menu_item_parent( $menu_item_data ) { if ( ! is_array( $menu_item_data ) ) { return $menu_item_data; } if ( ! empty( $menu_item_data['ID'] ) && ! empty( $menu_item_data['menu_item_parent'] ) && (int) $menu_item_data['ID'] === (int) $menu_item_data['menu_item_parent'] ) { $menu_item_data['menu_item_parent'] = 0; } return $menu_item_data; } MandMmanufacturing https://mandmmanufacturing.com Tue, 28 Oct 2025 20:08:47 +0000 en-US hourly 1 https://wordpress.org/?v=7.0.1 https://mandmmanufacturing.com/wp-content/uploads/2025/09/cropped-logo_mm-scaled-1-32x32.png MandMmanufacturing https://mandmmanufacturing.com 32 32 The Reason You Should Never Use Breakaway or Bargain‑Basement Shims https://mandmmanufacturing.com/the-reason-you-should-never-use-breakaway-or-bargain%e2%80%91basement-shims/ https://mandmmanufacturing.com/the-reason-you-should-never-use-breakaway-or-bargain%e2%80%91basement-shims/#respond Tue, 28 Oct 2025 20:08:47 +0000 https://mandmmanufacturing.com/?p=950

Cheap shims are a false economy. They may save a few dollars at purchase but they create hidden costs, safety risks, and repeated repairs that quickly exceed any upfront savings. Treat shims as precision alignment parts and refuse to use inferior or unknown‑source plates in your shop.

Safety and reliability risks

  • Unpredictable compressive strength — Low‑quality shims commonly crush, deform, or cold‑flow under load causing sudden geometry shifts and loss of preload.
  • Material contamination and corrosion — Inferior alloys and poor finishes corrode rapidly in real world environments, changing thickness and fit and creating asymmetric loads.
  • Poor dimensional tolerance — Cheap shims often vary outside acceptable thickness tolerances and lack flatness, producing inconsistent alignment results and repeat failures.
  • Hardware and seat damage — Burrs, sharp edges, or out‑of‑round bores damage seats, fasteners, and mating surfaces, leading to accelerated wear and potential component failure.

Measurable shop costs and operational impacts

  • Increased comebacks and rework — Crushed or corroded shims produce alignment drift that sends vehicles back repeatedly for diagnosis and correction.
  • Higher parts and labor spend — Replacing damaged bearings, seals, or entire assemblies caused by shim failure multiplies cost compared with using the correct shim initially.
  • Warranty and liability exposure — Using nonstandard, low‑quality parts can complicate warranty claims and increase legal or safety exposure if a failure causes an incident.
  • Lost uptime for customers — Unplanned downtime from repeat failures reduces fleet availability and damages customer trust and retention.

Common failure modes you will see from cheap shims

  • Crushing at point loads — Thin, soft plates compress under concentrated loads unless paired with a proper spreader.
  • Stack creep and settling — Multiple thin, poorly finished plates settle over time changing angles and preload.
  • Shim migration and rotation — Poor fit or wrong slot geometry allows shims to shift under torque, altering alignment.
  • Galvanic attack and pitting — Low‑quality plating or mixed metals without isolation lead to rapid thinning and loss of tolerance.

Practical shop policy and alternatives

  • Policy: Never install unknown‑source or visibly damaged shims; require part verification before use and refuse breakaway or bargain‑basement plates on customer vehicles.
  • Stock smarter: Keep labeled shim kits with verified thickness tolerances and matched materials for your common truck families.
  • Use load spreaders: Where thin shims are required under concentrated loads, always install a properly sized spreader plate.
  • Prefer single‑piece shims: Where loads are high, use a single machined shim of the correct alloy rather than stacked thin plates.
  • Require documentation: Photograph shim seats with a ruler inset, log shim part numbers and thicknesses in the vehicle record, and note any nonstandard parts refused.

Technician checklist for preventing shim failures

  • Inspect shim faces for flatness, burrs, and corrosion before reuse.
  • Verify thickness with calipers; reject any shim outside your shop tolerance.
  • Use specified material and finish for exposed or high‑compressive locations.
  • Replace locking hardware and follow OEM torque sequences to prevent migration.
  • Recheck alignment and re‑torque after initial run‑in and again at 500–1,000 miles when critical shims were changed.

Refuse bargain‑basement shims. Use proven materials, single‑piece solutions or properly engineered stacks, and document every change. Small parts deserve precision treatment; doing so reduces comebacks, protects expensive components, and keeps fleets on the road.

]]>
https://mandmmanufacturing.com/the-reason-you-should-never-use-breakaway-or-bargain%e2%80%91basement-shims/feed/ 0
The benefits of Aluminum 6061 Caster Shims over Steel Bronze Manganese and Other Alloys https://mandmmanufacturing.com/the-benefits-of-aluminum-6061-caster-shims-over-steel-bronze-manganese-and-other-alloys/ https://mandmmanufacturing.com/the-benefits-of-aluminum-6061-caster-shims-over-steel-bronze-manganese-and-other-alloys/#respond Tue, 28 Oct 2025 20:03:47 +0000 https://mandmmanufacturing.com/?p=947

Aluminum 6061 caster shims deliver a balanced mix of strength, weight savings, corrosion resistance, and machinability that makes them an excellent choice for many suspension and alignment applications where predictable, stable shim behavior is required.

Quick comparison table

Attribute Aluminum 6061SteelBronzeManganese alloys Other alloys Density / Weight Low; lightweight improves unsprang mashing; heavier unsprang mass Heavy; adds weight Heavy; adds weight Varies; often heavier Corrosion resistance Excellent natural oxide protection; anodize able Moderate; needs plating or coating Very good in many environments Variable; can corrode without treatment Varies widely Machinability and tolerances Excellent; easy to mill, thin tolerances Good but harder to machine thin plates Moderate; casting/bronze machining required Difficult; work hardens Varies Dimensional stability under load Stable with proper thickness; resists creep when alloyed Very stable; can handle high compressive loads Good wear resistance; can gall May suffer creep/wear under repeated loads Depends on alloy Thermal expansion / fit Moderate expansion; predictable Lower expansion; predictable Moderate Variable Variable Cost and availability Moderate cost; widely available Often lower cost for raw steel Higher material cost; specialty Variable; sometimes costly Varies

Why choose 6061 for caster shims

  • Optimal strength-to-weight ratio 6061 offers structural stiffness sufficient for many caster and shim applications while keeping weight low, helping reduce unsprung mass and improve ride response.
  • Corrosion resistance and longevity The natural oxide layer and compatibility with anodizing or coatings mean 6061 holds up well in road environments and resists thickness‑loss that would change shim geometry.
  • Precision machining and consistent tolerances 6061 machines cleanly to thin, repeatable thicknesses and flatness, letting shops produce single‑piece shims instead of stacked thin plates and avoiding stack creep or settling.
  • Predictable, repairable behavior Aluminum shims are less likely to cold‑weld or gall mating steel seats, and damaged seats can be dress‑machined more easily without introducing hard, abrasive wear like bronze can.
  • Thermal and galvanic advantages The thermal conductivity and expansion of 6061 are predictable, reducing surprises in fit at operating temperatures; with proper isolation, galvanic corrosion against common axle materials is manageable.

When steel, bronze, or manganese still make sense

  • High compressive load points Where point compressive stress is extreme, hardened steel or specially engineered steel washers and load spreaders outperform thin aluminum unless a thicker 6061 part or spreader is used.
  • Severe wear or sliding applications Bronze or bearing alloys remain superior where continuous sliding wear is expected and a sacrificial bearing surface is required.
  • Extreme impact or fatigue environments Some manganese or specialty high‑strength alloys resist impact and fatigue better; use these only when site measurements justify the tradeoffs.

Practical shop guidelines for using 6061 caster shims

  • Use load‑spreading plates for thin shims near concentrated loads to prevent local crushing.
  • Prefer single‑piece shims manufactured to final thickness rather than stacking multiple thin plates.
  • Anodize or coat shims in corrosive locations for extra longevity.
  • Match seat finish: dress and deburr mating faces to avoid localized stress risers.
  • Document and photo shim thickness and seating with a ruler inset to keep repeatable records for future service.

Final recommendation

Aluminum 6061 caster shims are an excellent first choice for many caster and alignment applications because they combine light weight, corrosion resistance, machinability, and dimensional consistency. Use 6061 where compressive loads are moderate and pair it with load spreaders or thicker sections where stresses are high. Reserve steel, bronze, and specialty alloys for situations that specifically demand their superior compressive strength or wear characteristics.

]]>
https://mandmmanufacturing.com/the-benefits-of-aluminum-6061-caster-shims-over-steel-bronze-manganese-and-other-alloys/feed/ 0
Understanding Mini Drive Axle Shims: Light‑Duty vs Heavy‑Duty Trucks https://mandmmanufacturing.com/understanding-mini-drive-axle-shims-light%e2%80%91duty-vs-heavy%e2%80%91duty-trucks/ https://mandmmanufacturing.com/understanding-mini-drive-axle-shims-light%e2%80%91duty-vs-heavy%e2%80%91duty-trucks/#respond Tue, 28 Oct 2025 20:02:33 +0000 https://mandmmanufacturing.com/?p=945

Mini drive axle shims are small, precision spacers that control axle lateral position, bearing preload, pinion angle, and load sharing at the wheel end. Despite their size, the correct mini shim makes measurable differences in vibration, tire wear, bearing life, and service intervals. This guide explains what changes between light‑ and heavy‑duty applications, how to choose the right shim, and shop workflows to get repeatable, verifiable results.

How mini drive axle shims work

  • They change axial and lateral position in very small increments to adjust preload, pinion angle, and wheel centering.
  • They let technicians correct tolerance stacks and manufacturing variance without replacing major components.
  • Proper material, diameter, and seating preserve stack thickness under load so geometry remains stable over time.

Key differences: light‑duty vs heavy‑duty applications

  • Load and stress: Heavy‑duty trucks see larger compressive forces and repeated dynamic loads, so shims must resist crushing and creep; light‑duty applications tolerate thinner, softer alloys for lower cost.
  • Seat geometry and locating features: Heavy‑duty axles often use larger seats, keyed or slotted locating features, and wider shim widths; light‑duty hubs may use smaller diameters and simpler seating.
  • Material selection: Heavy‑duty work calls for hardened steel, plated alloys, or integrated load‑spreader designs; light‑duty shims can be aluminum or zinc alloys where compressive demand is low.
  • Tolerance sensitivity: Heavy‑duty drivetrains require tighter control of pinion angle and preload because driveline vibration and u‑joint life scale dramatically with error; light‑duty systems are more forgiving but still benefit from precision.
  • Frequency of verification: Heavy‑duty fleets should verify shim stacks after heavy runs and at shorter intervals; light‑duty vehicles can follow standard PM cycles.

Choosing the right mini drive shim

  • Match fit: Confirm outer diameter, inner bore, slot/key geometry, and thickness tolerance to the seat before reuse.
  • Pick the correct material: Use hardened or plated steel and load spreaders for heavy loads; choose corrosion‑resistant alloys for exposed locations.
  • Prefer single‑piece shims for high compressive points to avoid stacked‑plate creep.
  • Use conversion charts or simple math to predict angle or preload change per shim thickness; change the minimum amount required to reach spec.

Technician workflow for reliable results

  1. Document baseline: capture ruler‑inset photos of tread and shim seats, record pinion angle, bearing preload, and wheel end play.
  2. Inspect components: discard shims with burrs, nicks, or corrosion and machine/dress seats if not flat.
  3. Measure precisely: use calipers, dial indicators, and angle gauges to quantify the required change.
  4. Change one variable at a time: install the minimum shim change, torque to OEM values, re‑measure, and road‑test under representative load.
  5. Use load spreaders and new locking hardware where point loads or stretched bolts are present.
  6. Document outcomes: save before/after numbers and a ruler‑inset shim stack photo in the vehicle file.

Common failure modes and prevention

  • Crushed shims from point loads — fix with spreaders or thicker single‑piece shims.
  • Creep and settling from thin stacked plates — use specified alloys or custom single shims in heavy‑duty service.
  • Shim migration from reused, stretched hardware — always replace locking hardware and follow torque sequence.
  • Wrong profile or diameter — verify fit before install; small seat differences change outcomes drastically.

Quick shop best practices

  • Stock labeled shim kits by application and maintain a simple conversion chart at each alignment station.
  • Enforce the one‑variable‑change rule and require ruler‑inset photos for every shim adjustment.
  • Replace hardware and use load spreaders for heavy‑duty installs.
  • Re‑verify critical shim work after 500–1,000 miles for heavy‑duty trucks to ensure stack stability.

Small parts deliver big reliability gains when chosen and installed with discipline. Tailor shim material, design, and verification cadence to whether the vehicle is light‑ or heavy‑duty, and treat each shim change as a precision adjustment that should be measured, documented, and repeatable.

]]>
https://mandmmanufacturing.com/understanding-mini-drive-axle-shims-light%e2%80%91duty-vs-heavy%e2%80%91duty-trucks/feed/ 0
Spacer Blocks Explained: The Unsung Heroes of Proper Axle Alignment https://mandmmanufacturing.com/spacer-blocks-explained-the-unsung-heroes-of-proper-axle-alignment/ https://mandmmanufacturing.com/spacer-blocks-explained-the-unsung-heroes-of-proper-axle-alignment/#respond Tue, 28 Oct 2025 20:01:09 +0000 https://mandmmanufacturing.com/?p=943

Spacer blocks are small components that control axle height, pinion angle, and load distribution. Proper selection, installation, and load spreading with spacer blocks prevent misalignment, uneven tire wear, driveline vibration, and premature component failure.

Why spacer blocks matter

  • Spacer blocks change ride height in precise increments and directly affect toe, caster, and pinion angle.
  • Spacer-induced height differences shift contact patches and load paths across bearings and tires, creating measurable wear if not corrected.
  • Spacer blocks transfer concentrated compressive loads; without proper load spreaders, thin or improperly seated blocks crush and change geometry under service.

Common spacer block types and when to use them

  • Flat spacer blocks — used to raise or lower axle seats in small, repeatable steps.
  • Z blocks and keyed spacers — used where locating features prevent rotation and ensure repeatable centering.
  • Wedge or tapered spacers — used to fine‑tune caster or steering axis inclination where angular correction is required.
  • Support plates and load spreaders — used under thin spacers near point loads to prevent crushing and retain stack thickness under load.

Installation and verification workflow

  1. Document baseline: record ride height, alignment numbers, and take ruler‑inset photos of tire wear and spacer seats.
  2. Inspect seating surfaces: confirm seats are flat and free of burrs, rust, or deformation.
  3. Select spacer: choose diameter, profile, and thickness from the model‑specific chart; confirm locating features match the seat.
  4. Use load spreaders: place a properly sized plate or washer under thin spacers at concentrated load points.
  5. Install and torque: torque hardware to OEM values in the specified sequence; re‑check seating after initial torque.
  6. Measure and validate: re‑record toe, caster, thrust, and pinion angle; perform a road test under representative load and re‑measure after run‑in.
  7. Document results: save before/after measurements and ruler‑inset photos in the vehicle service record.

Common failures and how to prevent them

  • Crushed spacers — prevent by using support plates or thicker single‑piece spacers at concentrated load points.
  • Shim or spacer migration — prevent by replacing stretched or worn locking hardware and using correct torque sequence.
  • Incorrect profile selection — prevent by verifying wedge angle, slot orientation, and seat diameter before installation.
  • Progressive alignment drift — prevent by changing only one variable between measurements and logging every stack combination.

Shop best practices

  • Stock labeled kits: keep model‑specific spacer kits clearly labeled by thickness and profile.
  • Conversion charts at each station: post quick charts that map spacer thickness or wedge degree to expected angle or ride‑height change.
  • One‑variable‑change rule: modify a single spacer stack between checks to isolate results.
  • Ruler‑inset photo protocol: require photos of spacer seats, final stacks, and tire tread for every alignment job.
  • Follow‑up verification: re‑check critical spacer installations after 500–1,000 miles and re‑torque fasteners as required.

Spacer blocks are precision alignment components. Treat them with the same measurement discipline, load‑spreading practice, and documentation standards you apply to bearings and gear patterns to protect tires, driveline components, and fleet uptime.

]]>
https://mandmmanufacturing.com/spacer-blocks-explained-the-unsung-heroes-of-proper-axle-alignment/feed/ 0
Peterbilt & Freightliner Shims: Compatibility, Performance, and Installation Tips https://mandmmanufacturing.com/peterbilt-freightliner-shims-compatibility-performance-and-installation-tips-2/ https://mandmmanufacturing.com/peterbilt-freightliner-shims-compatibility-performance-and-installation-tips-2/#respond Tue, 28 Oct 2025 19:54:19 +0000 https://mandmmanufacturing.com/?p=939

Attribute Freightliner Kenworth Practical impact Seat geometry Larger seat diameters; specific wedge profiles Varied seat diameters; different slot/key patterns Fit must be confirmed before reuse Wedge vs flat usage Common use of factory wedge/caster shims Mix of wedge and flat shims across models Choose correct profile to correct caster/camber Typical materials Hardened steel or plated alloys Stainless and plated steels common Material affects corrosion and creep resistance Common failure modes Shim crushing at point loads; wrong wedge angle Shims shifting with reused hardware; stacking errors Use spreaders and fresh locking hardware Inter changeability Limited without checking fit and spec Limited; some aftermarket cross fits exist Always verify diameter, slot, and locating features

Why shims matter for fleets

Shims control tiny geometry changes that create big effects on tire wear, steering, and driveline load sharing. Choosing the correct shim for Freightliner or Kenworth models prevents uneven wear, reduces comebacks, and protects expensive components.

Key compatibility essentials

  • Verify fit: Confirm outer diameter, locating hole position, slot width, and keying before reusing or substituting shims.
  • Match profile: Freightliner often requires specific wedge angles; Kenworth models may accept different tapers or flat shims—use the correct profile for the seat.
  • Material choice: Use corrosion‑resistant alloys for exposed locations and hardened steel where compressive loads are high.
  • Avoid blind swaps: Do not assume interchangeability between manufacturers; small differences in seat geometry change outcome.

Performance differences and what to watch for

  • Freightliner: Factory wedge shims can precisely correct caster and pinion angle when used correctly; failure usually comes from crushed thin plates or incorrect wedge orientation.
  • Kenworth: Many models rely on careful stacking and correct slot orientation; failures often stem from reused hardware allowing shim migration or incorrect stack sequencing.
  • Both: Incorrect material or lack of load spreaders leads to creep, crushing, and progressive alignment drift.

Installation tips for reliable results

  • One‑change rule: Change only one shim stack between measurements; re‑measure and document before proceeding.
  • Use load spreaders: Install properly sized plates or washers under thin shims at concentrated load areas to prevent crushing.
  • Replace locking hardware: Always replace stretched U‑bolts, nuts, or locking washers; torque to OEM sequence and re‑check after run‑in.
  • Document precisely: Photograph shim stacks with a ruler inset, record before/after alignment numbers, and log shim thicknesses in the vehicle file.

Shop best practices

  • Stock labeled kits: Keep model‑specific shim kits by truck family and post a simple conversion chart at each alignment station.
  • Training: Teach techs to read wedge orientation, recognize seat geometry differences, and follow the one‑variable‑change workflow.
  • QA protocol: Require ruler‑inset photos, torque verification after initial run‑in, and a 500–1,000 mile follow‑up inspection for major shim changes.
  • Standardize documentation: Store shim stack composition, measured results, and photos in the service record for future reference and warranty defense.

Final recommendation

Treat Freightliner and Kenworth shims as precision components: confirm fit and profile, use proper materials and spreaders, change one variable at a time, and document every step. These disciplined practices reduce tire and component wear, lower comebacks, and protect fleet uptime.

]]>
https://mandmmanufacturing.com/peterbilt-freightliner-shims-compatibility-performance-and-installation-tips-2/feed/ 0
How Torque Arm Shims Improve Ride Stability and Alignment https://mandmmanufacturing.com/how-torque-arm-shims-improve-ride-stability-and-alignment/ https://mandmmanufacturing.com/how-torque-arm-shims-improve-ride-stability-and-alignment/#respond Tue, 28 Oct 2025 19:47:46 +0000 https://mandmmanufacturing.com/?p=937

Small adjustments at torque arm mounts translate into big gains in ride stability, steering return, and even tire life. This post gives a technician‑ready explanation of what torque arm shims do, when to use them, a step‑by‑step installation workflow, common failure modes, and a concise QA checklist your shop can adopt immediately.

What torque arm shims do and why they matter

Torque arm shims precisely control lateral position, angular preload, and seating relationship at torque arm and rod mounts, restoring designed axle reaction geometry and minimizing axle wind‑up during acceleration and braking. They reduce unwanted lateral movement that causes steering wander, uneven tire wear, and transient toe changes during load shiftsBrake & Front End.

How shims affect ride stability and alignment

  • Control lateral and rotational preload: Proper shim stacks keep torque arms aligned so the axle resists twisting under torque rather than shifting and creating driveline vibration.
  • Restore steering geometry: Small shim thickness changes alter toe, caster, and thrust angle enough to correct steering pull or return‑to‑center problems without replacing major components.
  • Tune damping interaction: In systems where shims also influence subcomponent seating, the right shim material and thickness help maintain consistent damping response and load sharing.

Diagnostic signs that indicate torque arm shimming is needed

  • Repeating clunks or axle wind‑up during hard acceleration or braking.
  • Steering pull or driver needing constant correction on a straight road.
  • Rapid or asymmetric tire shoulder wear with otherwise healthy tires.
  • Alignment numbers that move out of spec after short road tests or under load changes.

If these symptoms point to torque arm or centering location play, shimming is often the precise corrective action.

Technician workflow — step‑by‑step

  1. Document baseline: take ruler‑inset photos of tire wear and current shim seats; record toe, caster, thrust, and torque arm geometry.
  2. Reproduce the symptom on a road test with representative load to confirm dynamic behavior.
  3. Static inspection: lift vehicle, check torque arm bushing play, inspect mount faces and shims for crushing or corrosion.
  4. Measure: use dial indicators and alignment rack numbers to determine required lateral or angular correction.
  5. Select shims: choose diameter, thickness, and material from your labeled shim kit; prefer corrosion‑resistant alloys in exposed locations.
  6. Install one change at a time: clean seats, fit shims or a single stack, use load spreaders where contact area is small, torque hardware to OEM spec.
  7. Verify: re‑measure alignment and driveline geometry, perform a road test under the same load, then re‑photograph shim stack and alignment numbers for the vehicle file.

Common failure modes and how to prevent them

  • Crushed or flattened thin shims under point loads — prevent by using load‑spreading plates or thicker single‑piece shims.
  • Incorrect stacking that compounds angle errors — follow the one‑variable‑change rule and document each stack.
  • Creep or corrosion changing stack thickness over time — specify proper alloy and finish when the job requires durability.
  • Shifted stacks from reused, stretched hardware — replace locking hardware and follow correct torque sequence.

QA checklist for consistent, verifiable results

  • Visual: shim faces are clean and flat; no burrs or corrosion.
  • Measurement: caliper‑checked shim thickness and dial indicator alignment values within target.
  • Torque: fasteners torqued to OEM sequence and values; re‑checked after initial run‑in.
  • Documentation: ruler‑inset photos of shim stack, before/after alignment numbers, and a short note describing the single change performed.

Treat torque arm shimming as precision alignment work: small, measured changes produce lasting stability gains, reduce tire wear, and prevent driveline complaints. Standardize shim kits, one‑change procedures, and ruler‑inset photo documentation at each alignment station to turn this simple fix into a high‑value shop service

]]>
https://mandmmanufacturing.com/how-torque-arm-shims-improve-ride-stability-and-alignment/feed/ 0
Understanding Axle Shims: Why Precision Matters for Your Truck’s Performance https://mandmmanufacturing.com/understanding-axle-shims-why-precision-matters-for-your-trucks-performance/ https://mandmmanufacturing.com/understanding-axle-shims-why-precision-matters-for-your-trucks-performance/#respond Tue, 28 Oct 2025 19:43:48 +0000 https://mandmmanufacturing.com/?p=935

Axle shims are thin, precision spacers that fine‑tune axle position, pinion angle, and bearing preload. Though small, they directly affect tire wear, driveline vibration, steering geometry, and component life. Treating shims as engineering components rather than throwaway hardware saves fleets time, money, and downtime.

What axle shims do

  • Set pinion angle to reduce u‑joint binding and driveline vibration.
  • Adjust axle height to restore ride geometry after wear, lifting, or frame repairs.
  • Control bearing preload and endplay where shims are used between bearing faces or at hub seats.
  • Correct minor manufacturing or repair tolerances without replacing heavy assemblies.

Signs you may need shim precision

  • Driveline vibration at cruise speeds or vibration that changes with load.
  • U‑joint or carrier noise and premature bearing wear indicating poor pinion angle or preload.
  • Uneven tire wear or steering pull after suspension repair or aftermarket height changes.
  • Repeated adjustments that don’t hold pointing to crushed, corroded, or incorrect shims.

Technician workflow for precision shimming

  1. Document baseline: capture ruler‑inset photos of tire wear and shim seats; record ride height, pinion angle, and alignment numbers.
  2. Inspect seating surfaces: replace shims with nicks, burrs, corrosion, or crushing marks; machine or dress seats if they are not flat.
  3. Measure precisely: use calipers for shim thickness and a pinion angle gauge or dial indicator for geometric checks.
  4. Plan one change at a time: calculate the required shim thickness from your conversion chart and install the minimum change to reach spec.
  5. Use load spreaders: place a properly sized plate or washer under thin shims at concentrated loads to prevent crushing.
  6. Torque and verify: torque hardware to OEM values, re‑measure preload and angles, then road test under representative load.
  7. Document results: save before/after numbers and ruler‑inset photos in the vehicle file for future reference.

QA checklist and common failure modes

  • QA checklist
    • Visual: shim faces flat, no burrs, no corrosion.
    • Measurement: caliper‑verified thickness; dial indicator or gauge confirms angles and preload within spec.
    • Hardware: new or serviceable lock hardware; correct torque and sequence.
    • Documentation: ruler‑inset photos and recorded shim stack in service history.
  • Common failure modes
    • Crushed shims under point loads when no spreader is used; fix with thicker shims or integrated spreaders.
    • Creep or settling from wrong alloy or thin stacked plates; use specified materials or a single custom shim.
    • Stacking errors that over‑correct angles; change one shim at a time and re‑measure.
    • Shifted stacks from reused stretched bolts or incorrect torque sequence; replace hardware and follow OEM torque procedure.

Shop best practices to guarantee consistency

  • Maintain labeled shim kits and a simple conversion chart at each alignment station.
  • Enforce the one‑variable‑change rule to isolate cause and effect.
  • Require ruler‑inset photos for shim seats, stacks, and final alignment checks on every job.
  • Stock load spreaders and common custom part numbers for repeat fleet models to shorten repair time.
  • Track outcomes: log tire life, driveline complaints, and rework rates to measure the ROI of precision shimming.

Precision shimming turns a small part into a big reliability win. Accurate measurement, correct materials, disciplined installation, and clear documentation keep trucks smoother, tires longer, and shops more profitable.

]]>
https://mandmmanufacturing.com/understanding-axle-shims-why-precision-matters-for-your-trucks-performance/feed/ 0
Special Orders, Custom Shims, and the Importance of Precision Engineering https://mandmmanufacturing.com/special-orders-custom-shims-and-the-importance-of-precision-engineering/ https://mandmmanufacturing.com/special-orders-custom-shims-and-the-importance-of-precision-engineering/#respond Tue, 28 Oct 2025 19:38:12 +0000 https://mandmmanufacturing.com/?p=933

Small tolerance parts drive big outcomes. Special‑order and custom shims correct fitment gaps, restore engineered geometry, and prevent progressive wear across suspension, driveline, and bearing systems. This post gives a technician‑ready guide to when to use custom shims, how to specify them, and shop practices that turn precision into measurable savings.

Why precision matters

  • Match design intent: Accurate shim thickness and geometry restore OEM or application‑specific clearances so bearings, seals, and gearsets share load as designed.
  • Prevent cascading failures: Even a fraction of a millimeter off at a shim seat amplifies into uneven wear, heat, and component fatigue down the line.
  • Reduce labor and parts cost: A correct custom shim eliminates repetitive stacking, trial‑and‑error repairs, and expensive component replacements.
  • Maintain serviceability: Precision parts hold tolerances under load, reducing rework and warranty claims.

Types of special orders and when to use them

  • Single‑piece custom shims for high‑compressive or high‑precision locations where stacked plates creep or crush.
  • Tapered and wedge shims to restore caster, camber, or steering axis tilt when flat shims cannot achieve the angle.
  • Machined spacer blocks with locating features for repaired or modified frames and welded alterations.
  • Material‑specific shims (stainless, hardened steel, coated alloys) for corrosive or high‑temperature environments.
  • Hybrid shims with load spreaders built in to protect thin sections from point loads.

How to specify a custom shim — technician workflow

  1. Document baseline: photograph seating surfaces with a ruler inset, record measured stack thickness, alignment numbers, bearing preload, and gear contact patterns.
  2. Define the requirement: specify exact outer/inner diameters, locating holes, slot geometry, taper degree (if wedge), and tolerance on thickness to the hundredth of a millimeter.
  3. Select material and finish: choose corrosion‑resistant or hardened alloys and specify plating or coating if exposure demands it.
  4. Request prototype: order a single prototype for fit, torque, and run‑in verification before full production.
  5. Verify and document: torque to spec, re‑measure preload/angles, road‑test under representative load, photograph final stack with ruler inset, and save part drawing and measured outcomes to the vehicle record.

Shop best practices to maximize value

  • One‑variable‑change rule: change only one shim or dimension between measurements and re‑record results immediately.
  • Standardize spec sheets: keep a templated custom‑order form with required drawing fields, material options, and finish choices to speed orders and avoid errors.
  • Stock common custom part numbers: for repeat fleet customers, pre‑order or stock frequently used custom shim part numbers to cut lead time.
  • Use load‑spreading designs: where thin shims face concentrated loads, always specify integrated spreaders or add plates to prevent crushing.
  • Document everything: store ruler‑inset photos, before/after measurements, prototype notes, and final part drawings in the vehicle file for future service and warranty defense.
  • Measure ROI: track reduced rework, extended bearing and tire life, and lowered downtime to justify custom part decisions to fleet managers.

Treat special orders and custom shims as engineering solutions, not luxury options. Precise specification, prototyping, and disciplined verification convert a small part into a long‑term reliability gain and clear cost savings for fleets and shops.

]]>
https://mandmmanufacturing.com/special-orders-custom-shims-and-the-importance-of-precision-engineering/feed/ 0
Why Custom Shim Orders Save You Costly Repairs Down the Road https://mandmmanufacturing.com/why-custom-shim-orders-save-you-costly-repairs-down-the-road/ https://mandmmanufacturing.com/why-custom-shim-orders-save-you-costly-repairs-down-the-road/#respond Tue, 28 Oct 2025 19:30:33 +0000 https://mandmmanufacturing.com/?p=930

Custom shims are precision components that fix tolerance gaps, restore alignment, and prevent progressive wear in suspension, driveline, and bearing assemblies. Investing in the right shim design and material up front often prevents repeated adjustments, component failures, and expensive downstream repairs.

Measurable cost benefits for fleets and shops

  • Lower part replacement costs: Custom shims eliminate the need to replace large components by compensating for wear or manufacturing tolerances with an exact fit.
  • Reduced labor and rework: A correct custom shim reduces iterative disassembly and trial‑and‑error stacking, saving technician hours and shop bay time.
  • Extended service intervals: Precisely sized, properly specified shims maintain preload and geometry longer, reducing unscheduled downtime and warranty claims.

When custom shims are the right call

  • Nonstandard repairs: After welding, frame repairs, or aftermarket modifications where OEM stacks no longer seat correctly.
  • Repeated failures: When the same bearing, seal, or alignment issue returns after standard shimming.
  • Critical load points: High‑compressive or high‑dynamic locations where standard thin plates crush or creep without a load‑spreading design.
  • Tight tolerance assemblies: Precision gearsets, pinion depth setups, and valve trains where a fraction of a millimeter changes contact patterns and life.

How to specify a custom shim (technician workflow)

  1. Measure and document baseline: record existing stack thickness, bearing preload, gear contact pattern, ride height, and take ruler‑inset photos of the seating surfaces.
  2. Define the requirement: state exact thickness, outer diameter, locating hole geometry, taper degree (if wedge), and material finish needed for corrosion or wear resistance.
  3. Select material and finish: choose alloys or coatings that resist compression, creep, and corrosion in the application environment; specify load‑spreading plates where necessary.
  4. Prototype and verify: fit the first custom shim, torque to spec, re‑measure preload/angles, and validate under representative load or road test.
  5. Document for reuse: save the final shim drawing or part number with the vehicle record and include ruler‑inset photos and measured before/after values.

Quality assurance checklist and failure modes to avoid

  • QA checklist
    • Visual: flat, clean seating faces with no burrs; check for corrosion.
    • Measurement: caliper‑checked thickness and dial indicator confirmation of preload or angle.
    • Hardware: confirm lock hardware and load spreaders are specified and installed.
    • Documentation: photo evidence and recorded shim part number in service history.
  • Common failure modes
    • Crushing under point loads when thin shims are used without spreaders; prevent with plates or thicker custom sections.
    • Material creep or corrosion from incorrect alloy choice; prevent by specifying corrosion‑resistant materials and finishes.
    • Stacking errors when techs mix multiple off‑the‑shelf shims without a documented conversion chart; prevent with a custom single‑piece shim or clear stack instructions.

Quick ROI example and shop best practices

  • ROI example: a repeated wheel‑end bearing failure that costs $1,200 in parts and labor per occurrence can often be fixed with a $30–$150 custom shim and one reliable install, delivering immediate savings and fewer comebacks.
  • Best practices
    • Standardize spec sheets for custom shim orders with exact geometry, material, and finish.
    • Keep a short conversion chart at alignment stations and require ruler‑inset photos on every shim change.
    • Stock common custom part numbers for repeat fleet models to shave lead time and get the upfront benefit faster.

Treat custom shims as precision repairs, not stopgap hardware: the right specification, material, and installation discipline pay back quickly through fewer failures, less labor, and lower total cost of ownership.

]]>
https://mandmmanufacturing.com/why-custom-shim-orders-save-you-costly-repairs-down-the-road/feed/ 0
Kenworth AirGlide Shims: The Ultimate Guide to Smooth, Balanced Rides https://mandmmanufacturing.com/kenworth-airglide-shims-the-ultimate-guide-to-smooth-balanced-rides/ https://mandmmanufacturing.com/kenworth-airglide-shims-the-ultimate-guide-to-smooth-balanced-rides/#respond Tue, 28 Oct 2025 19:28:59 +0000 https://mandmmanufacturing.com/?p=928

Kenworth AirGlide shims are precision parts that restore ride height, balance load distribution, and return steering geometry to spec for smoother, safer operation and longer component life.

Why AirGlide shims matter

  • Restore designed ride height to maintain proper air spring preload and prevent bottoming or overextension.
  • Balance axle loads so bearings, tires, and suspension components share forces evenly.
  • Correct caster and toe drift when small height or seat variations shift steering geometry.
  • Avoid costly replacements by correcting tolerance and wear issues without swapping heavy components.

Common AirGlide shim types and where they’re used

  • Flat spacer shims used between spring seats and axle or beam to change ride height in fine increments.
  • Wedge and tapered shims used at control arm or knuckle seats to adjust caster and steering axis inclination.
  • Torque arm and centering shims used at torque rod mounts to eliminate lateral offset and thrust angle.
  • Load‑spreader plates and washers used under thin shims to prevent crushing at concentrated load points.

Technician installation workflow

  1. Document baseline: record ride height, alignment numbers, and take ruler‑inset photos of tire wear and shim seats.
  2. Inspect seating surfaces and shims: replace any shims with burrs, corrosion, or deformation; ensure seats are clean and flat.
  3. Measure target movement: determine required thickness change from spec or conversion chart before selecting shims.
  4. Install one change at a time: fit the chosen shim or stack, use load spreaders where needed, torque fasteners to OEM values, and re‑measure.
  5. Validate under load: road test with representative payload, then re‑measure ride height and alignment; document final shim stack with ruler photo.

QA checklist and common failure modes

  • QA checklist
    • Visual: shim faces flat; no rust, nicks, or burrs.
    • Measurement: caliper‑checked shim thickness and alignment numbers within spec.
    • Torque: fasteners to OEM torque and rechecked after run‑in.
    • Documentation: ruler‑inset photos and recorded shim stacks in vehicle history.
  • Failure modes
    • Crushed shims from point loads when no spreader plate is used.
    • Creep and corrosion from wrong alloy selection or exposed environments.
    • Stacking errors when multiple shim changes are made without intermediate measurements.
    • Shifted shims from reused, stretched hardware or incorrect torque sequence.

Shop best practices and quick wins

  • Stock labeled AirGlide shim kits by thickness and common stack combos for Kenworth models.
  • Keep a simple conversion chart at each alignment station showing shim thickness vs ride‑height or angle change.
  • Enforce the one‑variable‑change rule: change only one shim stack between measurements.
  • Require ruler‑inset photos for shim seats and final stacks on every job for QA and warranty defense.
  • Use load spreaders and replace locking hardware when shims are exposed to high compressive loads.

Treat AirGlide shims as precision alignment components and follow disciplined measurement, installation, and documentation practices to deliver smoother rides, longer tire and bearing life, and fewer comebacks.

]]>
https://mandmmanufacturing.com/kenworth-airglide-shims-the-ultimate-guide-to-smooth-balanced-rides/feed/ 0