0
votes

In my WooCommerce shop customers can only buy one product. They can add this single product multiple times to the cart, but with different custom meta values. Customers are able to edit their products from the cart (WooCommerce default functionality) and change the meta they initially filled in.

In my functions.php I have the following code:

function add_names_on_tshirt_field() {   
    global $post;
    $name_one_on_tshirt = "";
    $name_two_on_tshirt = "";
    $name_three_on_tshirt = "";

    foreach ( WC()->cart->cart_contents as $key => $value ) {
        if( $value["product_id"] == $post->ID && isset( $value["name_one_on_tshirt"] ) ) {
            $name_one_on_tshirt = $value["name_one_on_tshirt"];
        }
        if( $value["product_id"] == $post->ID && isset( $value["name_two_on_tshirt"] ) ) {
            $name_two_on_tshirt = $value["name_two_on_tshirt"];
        }
        if( $value["product_id"] == $post->ID && isset( $value["name_three_on_tshirt"] ) ) {
            $name_three_on_tshirt = $value["name_three_on_tshirt"];
        }
    }

    echo '<table class="variations" cellspacing="0">
      <tbody>
          <tr>
            <td class="label"><label for="color">Name 1 on T-Shirt</label></td>
            <td class="value">
                <input type="text" name="name-one-on-tshirt" value="'. esc_attr( $name_one_on_tshirt ) .'" />
            </td>
        </tr>
        <tr>
            <td class="label"><label for="color">Name 2 on T-Shirt</label></td>
            <td class="value">
                <input type="text" name="name-two-on-tshirt" value="'. esc_attr( $name_two_on_tshirt ) .'" />
            </td>
        </tr>
        <tr>
            <td class="label"><label for="color">Name 3 on T-Shirt</label></td>
            <td class="value">
                <input type="text" name="name-three-on-tshirt" value="'. esc_attr( $name_three_on_tshirt ) .'" />
            </td>
        </tr>
      </tbody>
    </table>';
}
add_action( 'woocommerce_before_add_to_cart_button', 'add_names_on_tshirt_field' );

The problem lies in when my customers try to edit a product from the cart. Because all products have the same ID (I only have one product), the meta from the last product added to the cart is loaded into the text fields. I currently retrieve the meta in my foreach using the product id, but the ID is the same as all other products in my cart. Is there another way to retrieve the meta without using the product_id/$post->ID, like the cart_item_key or using sessions?

1

1 Answers

1
votes

Here is the idea how you can achieve that

you will have to edit your your-theme/woocommerce/cart.php ( especially product-thumbnail TD and product-name TD )

<?php

$query_str = "";

if( isset( $cart_item["name_one_on_tshirt"] ) ) {
    $query_str .= "?name_one_on_tshirt=" . $cart_item["name_one_on_tshirt"];
}

if( isset( $cart_item["name_two_on_tshirt"] ) ) {
    if( $query_str == "" ) {
        $query_str .= "?name_two_on_tshirt=" . $cart_item["name_two_on_tshirt"];
    } else {
        $query_str .= "&name_two_on_tshirt=" . $cart_item["name_two_on_tshirt"];
    }
}

if( isset( $cart_item["name_three_on_tshirt"] ) ) {
    if( $query_str == "" ) {
        $query_str .= "?name_three_on_tshirt=" . $cart_item["name_three_on_tshirt"];
    } else {
        $query_str .= "&name_three_on_tshirt=" . $cart_item["name_three_on_tshirt"];
    }
}
?>

<td class="product-thumbnail">
<?php
$thumbnail = apply_filters( 'woocommerce_cart_item_thumbnail', $_product->get_image(), $cart_item, $cart_item_key );

if ( ! $_product->is_visible() ) {
    echo $thumbnail;
} else {    
    printf( '<a href="%s">%s</a>', esc_url( $_product->get_permalink( $cart_item ) . $query_str ), $thumbnail );    
}
?>
</td>

<td class="product-name" data-title="<?php _e( 'Product', 'woocommerce' ); ?>">
    <?php
        if ( ! $_product->is_visible() ) {
            echo apply_filters( 'woocommerce_cart_item_name', $_product->get_title(), $cart_item, $cart_item_key ) . ' ';
        } else {         
            echo apply_filters( 'woocommerce_cart_item_name', sprintf( '<a href="%s">%s</a>', esc_url( $_product->get_permalink( $cart_item ) . $query_str ), $_product->get_title() ), $cart_item, $cart_item_key );                                        
        } 
        // Meta data
        echo WC()->cart->get_item_data( $cart_item );

            // Backorder notification
        if ( $_product->backorders_require_notification() && $_product->is_on_backorder( $cart_item['quantity'] ) ) {
            echo '<p class="backorder_notification">' . esc_html__( 'Available on backorder', 'woocommerce' ) . '</p>';
        }
    ?>
</td>

and then update your add_name_on_tshirt_field function like this

function add_names_on_tshirt_field() {
    global $post;
    $name_one_on_tshirt = "";
    $name_two_on_tshirt = "";
    $name_three_on_tshirt = "";

    if( isset( $_GET["name_one_on_tshirt"] ) ) {
        $name_one_on_tshirt = $_GET["name_one_on_tshirt"];
    }

    if( isset( $_GET["name_two_on_tshirt"] ) ) {
        $name_two_on_tshirt = $_GET["name_two_on_tshirt"];
    }

    if( isset( $_GET["name_three_on_tshirt"] ) ) {
        $name_three_on_tshirt = $_GET["name_three_on_tshirt"];
    }

    echo '<table class="variations" cellspacing="0">
      <tbody>
          <tr>
            <td class="label"><label for="color">Name 1 on T-Shirt</label></td>
            <td class="value">
                <input type="text" name="name-one-on-tshirt" value="'. esc_attr( $name_one_on_tshirt ) .'" />
            </td>
        </tr>
        <tr>
            <td class="label"><label for="color">Name 2 on T-Shirt</label></td>
            <td class="value">
                <input type="text" name="name-two-on-tshirt" value="'. esc_attr( $name_two_on_tshirt ) .'" />
            </td>
        </tr>
        <tr>
            <td class="label"><label for="color">Name 3 on T-Shirt</label></td>
            <td class="value">
                <input type="text" name="name-three-on-tshirt" value="'. esc_attr( $name_three_on_tshirt ) .'" />
            </td>
        </tr>
      </tbody>
    </table>';
}
add_action( 'woocommerce_before_add_to_cart_button', 'add_names_on_tshirt_field' );

So basically what I did is, I added them as query variable at cart.php and in add_name_on_tshirt_field I am check for the corresponding query var, if I find one then we can fill that fields value attribute.