This site is running Voxel Theme Version: 1.5.5.1 | Elementor Plugin Version: 3.28.4

Join the Voxel Guide Community!

Get Involved

Custom Voxel Dynamic Data Modifier: Get Address Parts

Description/Instructions

** Updated for Voxel 1.5 **

This is an alternative and updated version of Morten Lindorf’s snippet, “Control Which Parts Of A Location String Is Shown.”

It’s use case specific – I needed to reliably show the “city, state” or “city, province” for USA and Canadian locations without using any type of manual intervention from the user. I also wanted to strip off post codes for a cleaner presentation.

Find the github repository here.

Instructions

Here’s how to use this custom tool in the Voxel editor:

Purpose: This modifier lets you extract specific parts (like just the City and State, or only the ZIP code) from a full address field. It's useful for displaying addresses consistently in different formats across the site.

How to Apply:

Find the dynamic tag for your address field (it usually looks like @post(location.long_address) or similar, where location is your field key). Click the dynamic tag to open its options. Click "Apply modifier". Search for and select "Get Address Parts by Name (custom)". Configure the Arguments (Input Fields): You will see two input boxes:

Which parts? (e.g., city,state or street,zip):

This is where you tell the modifier which address components you want to display. Enter the names of the parts you need, separated by a comma, using lowercase letters. Available Part Names: street (The street number and name) city state (State or Province abbreviation/name) zip (ZIP or Postal Code) country (Either "United States" or "Canada") Examples: To show City and State: city, state To show only the ZIP code: zip To show Street, City, and State: street, city, state To show only the Country: country Output Delimiter (optional):

This controls what character(s) go between the address parts you selected.

If you leave this blank, it defaults to a comma and a space (,).

Example Voxel Tags:

Display City, State: @post(location.long_address).get_address_parts(city\, state) (Output: Anytown, AR)

Display ZIP Code Only: @post(location.long_address).get_address_parts(zip) (Output: 72076)

Display Street Address Only: @post(location.long_address).get_address_parts(street) (Output: 123 Main St)

Display City, State, and ZIP with spaces in between: @post(location.long_address).get_address_parts(city\, state\, zip," ") (Output: Anytown, AR 72076)

Important Notes:

This tool works best with standard US and Canadian addresses provided by Google. The accuracy depends on how Google formats the address initially. Sometimes parsing might miss a part if the address is very unusual. If the output looks wrong, double-check that you spelled the component names (city, state, etc.) correctly (all lowercase) and separated them with commas (and escaped the commas) in the first input box.

<?php
/**
 * Custom Voxel Dynamic Data Modifier: Get Address Parts
 *
 * Extracts specific parts from a Google Location field value (e.g., City, State/Province).
 * Designed to work with the format provided by Voxel's Address field type (long address).
 * Removes "United States" or "Canada" country names from the end.
 * Removes common US ZIP code (##### or #####-####) or Canadian Postal Code (A#A #A#) formats
 * *from the end of any individual address part* before selection.
 *
 * Example Usage in Voxel Editor:
 * Apply modifier 'Get address parts (custom)' to an address field dynamic tag.
 * Enter indices in the argument field, e.g., "-2,-1" to get the last two parts
 * (typically City, State/Province after country and postal code cleaning).
 *
 * Place this code in your active child theme's functions.php file.
 */
add_filter( 'voxel/dynamic-data/modifiers', function( $modifiers ) {

// Ensure the Voxel base modifier class exists before proceeding.
if ( ! class_exists( '\Voxel\Dynamic_Data\Modifiers\Base_Modifier' ) ) {
// Optional: Log an error if the base class isn't found.
// error_log('Voxel Base_Modifier class not found for Get_Address_Parts.');
return $modifiers; // Return unmodified list if Voxel structure isn't ready.
}

class Get_Address_Parts extends \Voxel\Dynamic_Data\Modifiers\Base_Modifier {

/**
* Get the display label for the modifier in the Voxel editor.
*/
public function get_label(): string {
// Added "(custom)" to easily distinguish from potential future built-in modifiers.
return 'Get address parts (custom)';
}

/**
* Get the unique key used to identify this modifier internally.
*/
public function get_key(): string {
return 'get_address_parts';
}

/**
* Define the arguments (input fields) for this modifier in the Voxel editor.
* Uses the new define_args() method.
*/
protected function define_args(): void {
$this->define_arg( [
'key'   => 'parts_indices', // A key for the argument (optional but good practice).
'type'  => 'text',          // Use the simple 'text' type specifier.
'label' => _x( 'Enter parts (e.g., -2,-1 for City, State/Province)', 'modifiers', 'voxel-backend' ),
'placeholder' => '-2,-1',   // Example placeholder text.
] );
}

/**
* Apply the modifier logic to the input value.
* Uses the new apply( $value ) signature and accesses args via $this->get_arg().
*
* @param mixed $value The dynamic value passed to the modifier (should be the address string).
* @return string The processed address string with selected parts.
*/
public function apply( $value ): string {
// 1. Ensure the input value is a non-empty string.
if ( ! is_string( $value ) || empty( trim( $value ) ) ) {
return ''; // Return empty if input is not a usable string.
}

// 2. Get the requested part indices from the modifier argument.
$requested_indices_str = (string) ( $this->get_arg( 0 ) ?? '' ); // Use index 0 for the first defined arg.
$requested_indices = array_filter( array_map( 'intval', explode( ',', $requested_indices_str ) ) );
if ( empty( $requested_indices ) ) {
return ''; // Return empty if no valid indices were provided.
}

// 3. Split the address string into parts.
$parts = explode( ', ', $value );
$parts = array_map( 'trim', $parts ); // Trim whitespace from each part.
$parts = array_filter( $parts );      // Remove any empty parts initially.
if ( empty( $parts ) ) {
return ''; // Return empty if splitting results in no parts.
}
$parts = array_values( $parts ); // Re-index the array.

// 4. Remove country name ("United States" or "Canada") if it's the last part.
$last_part_index = count( $parts ) - 1;
if ( isset( $parts[ $last_part_index ] ) ) {
$last_part = $parts[ $last_part_index ];
if ( $last_part === 'United States' || $last_part === 'Canada' ) {
unset( $parts[ $last_part_index ] );
$parts = array_values( $parts ); // Re-index after removal.
}
}

// 5. UPDATED LOGIC: Clean postal codes from the *end* of *each remaining* part.
// This handles cases like "City ZIP" or "State ZIP".
$cleaned_parts = [];
// Regex for Canadian Postal Code at the end of the string, preceded by space/comma+space
// Allows for A1A 1A1 or A1A1A1 format. Case Insensitive. Needs preceding space.
$canadian_postal_pattern = '/\s+[A-Z]\d[A-Z]\s?\d[A-Z]\d$/i';
// Regex for US ZIP Code at the end of the string, preceded by space/comma+space
// Allows for 12345 or 12345-6789. Needs preceding space.
$us_zip_pattern = '/\s+\d{5}(-\d{4})?$/';

foreach ( $parts as $part ) {
$part_to_clean = $part;

// Apply replacements to remove postal code found at the end of the string
$cleaned_part = preg_replace( $canadian_postal_pattern, '', $part_to_clean );
// Apply US ZIP removal *after* Canadian (less likely to conflict)
$cleaned_part = preg_replace( $us_zip_pattern, '', $cleaned_part );

// Add the potentially cleaned part (trimmed) to the new array
$cleaned_parts[] = trim( $cleaned_part );
}
// Replace the original parts array with the cleaned one
$parts = $cleaned_parts;

// 6. Filter out any potentially empty parts resulting from cleaning and re-index.
$parts = array_filter( $parts, function( $part ) {
return !empty( trim( $part ) );
} );
$parts = array_values( $parts ); // Re-index again after filtering.

 

// 7. Select the requested parts based on the indices from the *cleaned* array.
$result_parts = [];
$parts_count = count( $parts );
foreach ( $requested_indices as $index ) {
$actual_index = null;
if ( $index < 0 ) {
// Negative index: Count from the end (-1 is last, -2 is second last, etc.)
$actual_index = $parts_count + $index;
} elseif ( $index > 0 ) {
// Positive index: 1-based index from the start (1 is first, 2 is second, etc.)
$actual_index = $index - 1;
}
// Ignore index 0 if provided.

if ( $actual_index !== null && isset( $parts[ $actual_index ] ) ) {
// Ensure final selected parts are trimmed too
$result_parts[] = trim( $parts[ $actual_index ] );
}
}

// 8. Join the selected parts back into a string.
return join( ', ', array_filter( $result_parts ) ); // Filter again in case any selected part was empty.
}
}

// Register the custom modifier class with Voxel.
$modifiers['get_address_parts'] = \Get_Address_Parts::class;

return $modifiers;
} );

  • PHP
Copy Code

Let's Chat About this Snippet

Chat Toggle
Voxel Guide AI
Voxel Guide AI
Voxel Guide AI
Voxel Guide AI
Ask me anything about Voxel!
Send
Powered by AI24