<p>I think you have direct access to the purchasable already via a simple</p>

<p><code>$lineItem-&gt;purchasable</code></p>

<p>E.g. I do things like this</p>

<pre><code>foreach ($event-&gt;params['order']-&gt;lineItems as $item) {
    BusinessLogicPlugin::log($item-&gt;purchasable-&gt;title);
}
</code></pre>

<p>You should really just be able to access the fields directly on the purchasable via</p>

<p><code>$lineItem-&gt;purchasable-&gt;field</code></p>

<p>So I don't  think you need to use the snapshot side of things at all as long as you're doing this at this stage anyway - the snapshot is something you use if you're dealing with an order when the product data may have since changed etc. as I understand it.</p>

CC BY-SA 3.0
2016-05-02T01:11:02.110Z
Who would have thought. Me over-complicating things...again. Thanks Brad!
Damon
CC BY-SA 3.0
2016-05-02T01:18:39.150Z
Look at that he fixes a typo and gets all the credit ;)
Jeremy Daalder
CC BY-SA 3.0
2016-05-02T03:11:16.403Z
lol - that one is all @JeremyDaalder!
Brad Bell
CC BY-SA 3.0
2016-05-01T23:56:46.767Z
2016-05-02T00:03:01.843Z
2016-05-02T00:03:01.843Z
Jeremy Daalder
<p>I am able to inspect my cart using <code>commerce_orders.onOrderComplete</code>.</p>

<p>Next I loop through each line item &amp; check for a specific product type. I need to be able to get the specific product, as there are attributes (values) within that product that I am saving to my plugin's records.</p>

<p>For example, if a user purchases "My Product", "My Product" has attributes that include things like "Follow-Up Meetings Qty" Where the admin is allowed to choose the number of meetings are included with "My Product".  </p>

<p>Here is what I have that is close, I am stumbling getting the correct criteria model back. I know I'm not working with an entry, so I need to use the purchasable element type.</p>

<pre><code>craft()-&gt;on('commerce_orders.onOrderComplete', function (Event $event) {
    user = $event-&gt;params['order']-&gt;getCustomer()-&gt;getUser();
    $orderNumber = $event-&gt;params['order']-&gt;number;

    foreach ($event-&gt;params['order']-&gt;lineItems as $item) {
        if ($item-&gt;snapshot['product']['typeId'] == 123) {
             $productId = $item-&gt;snapshot['id'];

            // Get order details.
            switch ($productId) {
                case 456:
                    error_log('---- My Product Was Purchased ----');
                    error_log('user id: ' . $user-&gt;id);
                    error_log('order number: ' . $orderNumber);
                    error_log('product id: ' . $productId);

                    // Get the specific product that was purchased.
                    $criteria = craft()-&gt;commerce_purchasables-&gt;getCriteria(ElementType::Purchasable);
                    $criteria-&gt;limit = 1;

                    ...

                    $products = $criteria-&gt;find();

                    if ($products) {
                        foreach ($products as $product) {
                          // Access the products' attributes
                          // $product-&gt;meetings_qty  (3)
                          // $product-&gt;foo_qty  (2)
                          // $product-&gt;bar_qty

                          ...

                          // Save the values to my plugin record.
                        }
                    } else {
                        error_log('no products found that match criteria!');
                    }

                break;
                ...
            }
        }
    }
});
</code></pre>

<p>Thank you for any suggestions!</p>

<p><strong>EDIT</strong></p>

<p>Thank you Brad!</p>

<p>Here is what the solution looks like after I removed the over-complication "stuff". Hope this helps anyone who comes across this thread.</p>

<pre><code>craft()-&gt;on('commerce_orders.onOrderComplete', function (Event $event) {
        $user = $event-&gt;params['order']-&gt;getCustomer()-&gt;getUser();
        $orderNumber = $event-&gt;params['order']-&gt;number;

        foreach ($event-&gt;params['order']-&gt;lineItems as $item) {
            error_log('User id: ' . $user-&gt;id);
            error_log('Order number: ' . $orderNumber);
            error_log('Product title: ' . $item-&gt;purchasable-&gt;title);
            error_log('Product id: ' . $item-&gt;purchasable-&gt;id);
            error_log('Meetings qty: ' . $item-&gt;purchasable-&gt;product-&gt;myFieldHandle);

            ...
            do some other stuff...
            ...
            Save the record.
        }
});
</code></pre>

<plugin-development><plugin-craftcommerce>
How can I get a specific product via plugin?
# How can I get a specific product via plugin?

(Asked by: username_0 on 2016-05-01)

I am able to inspect my cart using commerce_orders.onOrderComplete.
Next I loop through each line item & check for a specific product type. I need to be able to get the specific product, as there are attributes (values) within that product that I am saving to my plugin's records.
For example, if a user purchases "My Product", "My Product" has attributes that include things like "Follow-Up Meetings Qty" Where the admin is allowed to choose the number of meetings are included with "My Product".  
Here is what I have that is close, I am stumbling getting the correct criteria model back. I know I'm not working with an entry, so I need to use the purchasable element type.
craft()->on('commerce_orders.onOrderComplete', function (Event $event) {
    user = $event->params['order']->getCustomer()->getUser();
    $orderNumber = $event->params['order']->number;

    foreach ($event->params['order']->lineItems as $item) {
        if ($item->snapshot['product']['typeId'] == 123) {
             $productId = $item->snapshot['id'];

            // Get order details.
            switch ($productId) {
                case 456:
                    error_log('---- My Product Was Purchased ----');
                    error_log('user id: ' . $user->id);
                    error_log('order number: ' . $orderNumber);
                    error_log('product id: ' . $productId);

                    // Get the specific product that was purchased.
                    $criteria = craft()->commerce_purchasables->getCriteria(ElementType::Purchasable);
                    $criteria->limit = 1;

                    ...

                    $products = $criteria->find();

                    if ($products) {
                        foreach ($products as $product) {
                          // Access the products' attributes
                          // $product->meetings_qty  (3)
                          // $product->foo_qty  (2)
                          // $product->bar_qty

                          ...

                          // Save the values to my plugin record.
                        }
                    } else {
                        error_log('no products found that match criteria!');
                    }

                break;
                ...
            }
        }
    }
});

Thank you for any suggestions!
EDIT
Thank you Brad!
Here is what the solution looks like after I removed the over-complication "stuff". Hope this helps anyone who comes across this thread.
craft()->on('commerce_orders.onOrderComplete', function (Event $event) {
        $user = $event->params['order']->getCustomer()->getUser();
        $orderNumber = $event->params['order']->number;

        foreach ($event->params['order']->lineItems as $item) {
            error_log('User id: ' . $user->id);
            error_log('Order number: ' . $orderNumber);
            error_log('Product title: ' . $item->purchasable->title);
            error_log('Product id: ' . $item->purchasable->id);
            error_log('Meetings qty: ' . $item->purchasable->product->myFieldHandle);

            ...
            do some other stuff...
            ...
            Save the record.
        }
});

**Tags:** plugin-development, plugin-craftcommerce

---

## 1 answers

### Answer by username_1 on 2016-05-01. Score: 3 | Accepted answer

I think you have direct access to the purchasable already via a simple
$lineItem->purchasable
E.g. I do things like this
foreach ($event->params['order']->lineItems as $item) {
    BusinessLogicPlugin::log($item->purchasable->title);
}

You should really just be able to access the fields directly on the purchasable via
$lineItem->purchasable->field
So I don't  think you need to use the snapshot side of things at all as long as you're doing this at this stage anyway - the snapshot is something you use if you're dealing with an order when the product data may have since changed etc. as I understand it.

> **Comments:**
> **username_0**: Who would have thought. Me over-complicating things...again. Thanks Brad!  
> **username_1**: Look at that he fixes a typo and gets all the credit ;)  
> **username_2**: lol - that one is all @JeremyDaalder!  

---

