0

I'm looking for clarification on using a model variable within a plugin. I can't seem to find a concrete answer on how this is done, or if it's even possible.

A little background so we're on the same page. I have an integration with a local piece of software that sends product data to Magento 2 using the REST API. The module takes the information sent from the local software then translates the data so it creates and updates products, makes custom attributes and assigns values, along with sanitizing some data. That comes up as a JSON request.

What I'm looking to do is take the special price, price from/to dates and new from/to dates then work with them to extend what is done with those data points as they come in via plugin with beforeSave.

Is it easy enough to include a use statement that points to my model file? or is there more to it? The methods are public so it should be able to work with them I would think.

3
  • added an answer. Might need a little more info to give you more specific details that might help. Let me know!
    – sdaugherty
    Commented Aug 5, 2020 at 0:36
  • I am actually using a module-specific Model that does data processing. I need to yank the data from it and modify it so I can manipulate special price data and new from/to data before finishing its tasks.
    – Marisa
    Commented Aug 5, 2020 at 14:56
  • oh okay. If I'm understanding correctly, you have a separate Model class you want to inject into the plugin class so you can pass the product to it for additional processing?
    – sdaugherty
    Commented Aug 7, 2020 at 2:38

1 Answer 1

0

Are you saying you want to do some additional processing with data on the Product model inside your plugin?

A before plugin/interceptor should allow you to access the parameters being passed to the original method. In your case I'm guessing the plugin is on Magento\Catalog\Api\ProductRepositoryInterface::save(\Magento\Catalog\Api\Data\ProductInterface $product, $saveOptions = false) method.

In which case, you should be able to access data off of the $product parameter.

$product->getName()

$product->getPrice()

etc...

Example Plugin

<?php

namespace MyCompany\CustomModule\Plugin;

class BeforeSavePlugin
{
    public function beforeSave(
        \Magento\Catalog\Api\ProductRepositoryInterface $subject,
        \Magento\Catalog\Api\Data\ProductInterface $product,
        $saveOptions = false
    ) {
        // TODO: this would throw exception for a new product. Need to catch new product scenario.
        $oldProduct = $subject->get($product->getSku());
        $oldPrice = $oldProduct->getPrice();
        $newPrice = $product->getPrice();

        // Business logic to alter product before being saved
        // ... $product->setPrice()

        return [$product, $saveOptions];
    }
}

Update 1

Let's say your custom Service class is called \MyCompany\CustomModule\Service\ProductService.

How To Use Custom Service In Other Classes

  1. Add a use statement pointing to your Model/Service
  2. Add your Service to the constructor of the class that needs it (This is Dependency Injection / DI)
  3. In the body of the class constructor, set the new dependency as a property of the class it's being used in
  4. Use your Service by referencing the new property you set

See code below for example.

Why the Factory?

Ideally, your model/service class is stateless, which is to say, it doesn't remember anything about what its done whenever you call it. If this is the case, then you don't need to use the Factory.

If there is a chance that whenever your service gets called it will hold on to some information about the product or anything else during processing, you need to create a new instance of it via a Factory to guarantee it doesn't remember anything from the last time it was called.

The Plugin (With Factory):

<?php

namespace MyCompany\CustomModule\Plugin;

// STEP 1
use MyCompany\CustomModule\Service\ProductService;
use MyCompany\CustomModule\Service\ProductServiceFactory;

class BeforeSavePlugin
{
    // STEP 3
    protected $productServiceFactory;

    // STEP 2
    public function __construct(
        ProductServiceFactory $productServiceFactory
    ) {
        // STEP 3
        $this->productServiceFactory = $productServiceFactory;
    }

    public function beforeSave(
        \Magento\Catalog\Api\ProductRepositoryInterface $subject,
        \Magento\Catalog\Api\Data\ProductInterface $product,
        $saveOptions = false
    ) {
        // STEP 4
        /** @var ProductService $productService */
        $productService = $this->productServiceFactory->create();
        $productService->process($product);

        return [$product, $saveOptions];
    }
}

The Plugin (Without Factory):

<?php

namespace MyCompany\CustomModule\Plugin;

// STEP 1
use MyCompany\CustomModule\Service\ProductService;

class BeforeSavePlugin
{
    // STEP 3
    protected $productService;

    // STEP 2
    public function __construct(
        ProductService $productService
    ) {
        // STEP 3
        $this->productService = $productService;
    }

    public function beforeSave(
        \Magento\Catalog\Api\ProductRepositoryInterface $subject,
        \Magento\Catalog\Api\Data\ProductInterface $product,
        $saveOptions = false
    ) {
        // STEP 4
        $this->productService->process($product);

        return [$product, $saveOptions];
    }
}
2
  • Let me know what you need specifically and I'll update my question with it.
    – Marisa
    Commented Aug 5, 2020 at 14:56
  • I've made some updates in "Update 1" section of answer based on some assumptions. If you could update your question with an example of some of your code, that would help. Specifically the Model you are talking about and the basic structure of your Module.
    – sdaugherty
    Commented Aug 7, 2020 at 3:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.