Answers.Body: <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>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-05-02T01:11:02.110Z
Answers.Text: Who would have thought. Me over-complicating things...again. Thanks Brad!
Answers.UserDisplayName: Damon
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-05-02T01:18:39.150Z
Answers.Text: Look at that he fixes a typo and gets all the credit ;)
Answers.UserDisplayName: Jeremy Daalder
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-05-02T03:11:16.403Z
Answers.Text: lol - that one is all @JeremyDaalder!
Answers.UserDisplayName: Brad Bell
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-05-01T23:56:46.767Z
Answers.LastActivityDate: 2016-05-02T00:03:01.843Z
Answers.LastEditDate: 2016-05-02T00:03:01.843Z
Answers.UserDisplayName: Jeremy Daalder
Body: <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>
  
Tags: <plugin-development><plugin-craftcommerce>
Title: How can I get a specific product via plugin?
ThreadText: # 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 username_2!
  
  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 username_2!  
  > **username_1**: Look at that he fixes a typo and gets all the credit ;)  
  > **username_2**: lol - that one is all @username_1!  
  
  ---
  
  