11

I'm trying to make the status of a review be approved instead of pending when the user posts it in the frontend in Magento 2.
And I took this approach. Create a before plugin, available only in the frontend area, for the method setStatusId for the Magento\Review\Model\Review that looks like this

public function beforeSetStatusId(\Magento\Review\Model\Review $review, $status)
{
    return [\Magento\Review\Model\Review::STATUS_APPROVED];
}

It seamed to me like a good idea. And it should work since I'm returning the approved status. The actual method should then pick this up as a parameter.
but to my surprise it didn't work.
Then I dug up and found that the method setStatusId does not exist in the review model. It is magically called and it actually runs setData('status_id', $status).
I took a look then in the generated interceptor, and indeed there is not setStatusId method.

How can I pluginize the magic getters/setters in magento 2? Is that even possible?

Note: I don't need a solution for making the reviews auto-approved. I know I can take other approaches, like the save_before events. This is not important for now.

0

2 Answers 2

20

Is that even possible?

Yes.

How can I pluginize the magic getters/setters in magento 2?

In the same way as a other public method. You need to declare plugin in di.xml configuration and add you custom code in plugin.

public function before__call(\Magento\Review\Model\Review $review, $method, $args)
{
    if ($method == 'setStatusId') {
        if (isset($args[0])) {
            $args[0] = \Magento\Review\Model\Review::STATUS_APPROVED;
            return [$method, $args];
        }
    }
    //leave everything unchanged
    return null;
}

But pluginization of DTO classes is not good idea. Try to customize appropriate controllers/services for modify application behaviour and do not add plugins on DTO object. This customization will destroy application layers. I understand, that you are use most quick and easy way, but in some case it is wrong strategy.

4
  • I agree with you on customization. This was just a proof of concept.
    – Marius
    Commented Feb 7, 2017 at 11:41
  • @Marius yeah, cool
    – Max
    Commented Feb 7, 2017 at 11:44
  • I took this approach, but this is going to fail when/if the review module gets refactored to use service contracts. It's ok for now. Thanks.
    – Marius
    Commented Feb 7, 2017 at 12:10
  • yes, sure, but your question was "How can I pluginize the magic getters/setters in magento 2? Is that even possible?". Best option would be use plugins only for public api methods and services, but in some magento modules there are no any APIs or it is poor.
    – Max
    Commented Feb 7, 2017 at 12:19
5

I once had a similar problem. I ended up with pluginize the setData()-method, although in my opinion that generates a tremendous waste of resources... :-(

4
  • Ok. this is a working approach. +1. But I am hoping for cleaner option (provided that there is one).
    – Marius
    Commented Feb 7, 2017 at 10:22
  • I hope the same. I still cry myself to sleep every night because this fix looks so dirty. I think that the whole reason there still are magic methods is because of the legacy code of Magento 1. I think that as long as the review model is not yet refactored to a data model you're out of luck for this one. Commented Feb 7, 2017 at 10:33
  • I realized myself that is because of the legacy code. And I learned a good lesson from this. Don't rely on magic for custom CRUD modules.
    – Marius
    Commented Feb 7, 2017 at 10:36
  • I took the approach explained by Max in here mainly because my plugin will get called only when a magic setter is invoked and not for all setData calls. It's not perfect but it's a bit better than using setData. Maybe you can change your approach also and sleep a little better at night. :)
    – Marius
    Commented Feb 7, 2017 at 12:12

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.