Why does the "wc_get_product_id_by_sku()" function return the same id in the loop?

Viewed 688

I have an XML similar to the following:

<?xml version="1.0" encoding="utf-8"?>
<Products exportdate="01-04-2021 11:30">
    <Product>
        <Productnumber>10203</Productnumber>
        <EAN>87196XXXXX</EAN>
        <Stock>1</Stock>
        <Price>1079,00</Price>
    </Product>
    <Product>
        <Productnumber>10370</Productnumber>
        <EAN>87197XXXXX</EAN>
        <Stock>1</Stock>
        <Price>1000,00</Price>
    </Product>
</Products>

When I run the following code, I expect to get the corresponding post ID from the SKU provided:

    foreach ($xml->children() as $row) {
    $stock = $row->Stock;
    $sku = $row->Productnumber;
    $p_id = wc_get_product_id_by_sku( $sku );
    echo $sku. " (PID: " .$p_id. ") -> Stock: " .(int)$stock."<br>";
}

However, I seem to be getting the first post ID in the list back every time. Is this a database issue? Am I using the function incorrectly?

10203 (PID: 59049) -> Stock: 1
10370 (PID: 59049) -> Stock: 1
10212 (PID: 59049) -> Stock: 0
11503 (PID: 59049) -> Stock: 12
11504 (PID: 59049) -> Stock: 3
12015 (PID: 59049) -> Stock: 0
12016 (PID: 59049) -> Stock: 0
12030 (PID: 59049) -> Stock: 0
12031 (PID: 59049) -> Stock: 0
12032 (PID: 59049) -> Stock: 0
12522 (PID: 59049) -> Stock: 0
12523 (PID: 59049) -> Stock: 70
12524 (PID: 59049) -> Stock: 109

The same happens when I use this instead:

$p_id = $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key='_sku' AND meta_value='%s' LIMIT 1", $sku ) );

The SKUs do actually correspond to the SKUs in my product database: SKU

I am quite stumped as to what the cause might be.

1 Answers

If you are using the PHP simplexml_load_file function I have the solution for you.

You're getting the SKU like this:

$sku = $row->Productnumber;

But the value of the $sku variable is not a string but the SimpleXMLElement object with the value of the XML node. If you run var_dump($sku); you will get this (in my case):

object(SimpleXMLElement)#2217 (1) { [0]=> string(5) "10203" }

Also you should get a notice in the log file because you are passing an object and not a string to the wc_get_product_id_by_sku function, similar to this:

Notice: wpdb::prepare was called incorrectly. Unsupported value type (object).

SOLUTION

You can solve the problem by forcing the conversion to string.
Then replace:

$sku = $row->Productnumber;

with:

$sku = (string) $row->Productnumber;

and you will see the correct product IDs. I have tested the code and it works.

Related