8

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.

12

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.

  • I agree with you on customization. This was just a proof of concept. – Marius Feb 7 '17 at 11:41
  • @Marius yeah, cool – Max Feb 7 '17 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 Feb 7 '17 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 Feb 7 '17 at 12:19
3

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... :-(

  • Ok. this is a working approach. +1. But I am hoping for cleaner option (provided that there is one). – Marius Feb 7 '17 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. – Giel Berkers Feb 7 '17 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 Feb 7 '17 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 Feb 7 '17 at 12:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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