How to override model in magento2?
All other answers tell you how to rewrite the model, exactly what is asked. But Magento 2 offers another solution to your problem: Plugins. With plugins you can change the outcome of just about any public method in Magento 2. You stated you want to change the result of this function:
if (!$this->zeroTotalValidator->isApplicable($payment->getMethodInstance(), $quote)) {
throw new InvalidTransitionException(__('The requested Payment Method is not available.'));
}
You can do this by adding a plugin on the \Magento\Payment\Model\Checks\ZeroTotal
class. Add this to your etc/di.xml
file:
<type name="Magento\Payment\Model\Checks\ZeroTotal">
<plugin name="your_unique_name_for_this_plugin" type="Vendor\Module\Plugin\ZeroTotal" />
</type>
Then create the class:
<VendorName>\<ModuleName>\Plugin\ZeroTotal
namespace Vendor\Module\Plugin;
class ZeroTotal
{
public function afterIsApplicable($subject, $result)
{
return true;
}
}
This will make sure the function always returns true. If you want a more granular approach you can change the function to this:
public function aroundIsApplicable($subject, callable $proceed, ...$args)
{
if ($this->meetsMyCustomRequirement()) {
// This will call the original function and return it's results.
return $proceed(...$args);
}
return false;
}
If the $proceed
function isn't called then the original function is also never called.
Steps to Follow :
- Override di.xml
- Override PaymentMethodManagement.php
- Launch SSH and Run Commands
Override di.xml
app/code/Namespace/Modulename/etc
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="Magento\Quote\Model\PaymentMethodManagement" type="Namespace\Modulename\PaymentMethodManagement" />
</config>
Override PaymentMethodManagement.php
/**
* {@inheritdoc}
*/
public function set($cartId, \Magento\Quote\Api\Data\PaymentInterface $method)
{
/** @var \Magento\Quote\Model\Quote $quote */
$quote = $this->quoteRepository->get($cartId);
$method->setChecks([
\Magento\Payment\Model\Method\AbstractMethod::CHECK_USE_CHECKOUT,
\Magento\Payment\Model\Method\AbstractMethod::CHECK_USE_FOR_COUNTRY,
\Magento\Payment\Model\Method\AbstractMethod::CHECK_USE_FOR_CURRENCY,
\Magento\Payment\Model\Method\AbstractMethod::CHECK_ORDER_TOTAL_MIN_MAX,
]);
$payment = $quote->getPayment();
$data = $method->getData();
$payment->importData($data);
if ($quote->isVirtual()) {
$quote->getBillingAddress()->setPaymentMethod($payment->getMethod());
} else {
// check if shipping address is set
if ($quote->getShippingAddress()->getCountryId() === null) {
throw new InvalidTransitionException(__('Shipping address is not set'));
}
$quote->getShippingAddress()->setPaymentMethod($payment->getMethod());
}
if (!$quote->isVirtual() && $quote->getShippingAddress()) {
$quote->getShippingAddress()->setCollectShippingRates(true);
}
/*** Do stuff with this code ***/
if (!$this->zeroTotalValidator->isApplicable($payment->getMethodInstance(), $quote)) {
throw new InvalidTransitionException(__(''));
}
/*** Do stuff with this code ***/
$quote->setTotalsCollectedFlag(false)->collectTotals()->save();
return $quote->getPayment()->getId();
}
Launch SSH and Run Commands
php bin/magento setup:di:compile
php bin/magento cache:clean
php bin/magento cache:flush
I hope it helps!
in you etc/di.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="Magento\Quote\Model\PaymentMethodManagement" type="Vendor\Module\Model\Rewrite\Quote\PaymentMethodManagement" />
</config>
in your Model file
<?php
namespace Vendor\Module\Model\Rewrite\Quote;
class PaymentMethodManagement extends \Magento\Quote\Model\PaymentMethodManagement
{
public function set($cartId, \Magento\Quote\Api\Data\PaymentInterface $method)
{
/** @var \Magento\Quote\Model\Quote $quote */
$quote = $this->quoteRepository->get($cartId);
$method->setChecks([
\Magento\Payment\Model\Method\AbstractMethod::CHECK_USE_CHECKOUT,
\Magento\Payment\Model\Method\AbstractMethod::CHECK_USE_FOR_COUNTRY,
\Magento\Payment\Model\Method\AbstractMethod::CHECK_USE_FOR_CURRENCY,
\Magento\Payment\Model\Method\AbstractMethod::CHECK_ORDER_TOTAL_MIN_MAX,
]);
$payment = $quote->getPayment();
$data = $method->getData();
$payment->importData($data);
if ($quote->isVirtual()) {
$quote->getBillingAddress()->setPaymentMethod($payment->getMethod());
} else {
// check if shipping address is set
if ($quote->getShippingAddress()->getCountryId() === null) {
throw new InvalidTransitionException(__('Shipping address is not set'));
}
$quote->getShippingAddress()->setPaymentMethod($payment->getMethod());
}
if (!$quote->isVirtual() && $quote->getShippingAddress()) {
$quote->getShippingAddress()->setCollectShippingRates(true);
}
/*** Do stuff with this code ***/
if (!$this->zeroTotalValidator->isApplicable($payment->getMethodInstance(), $quote)) {
throw new InvalidTransitionException(__(''));
}
/*** Do stuff with this code ***/
$quote->setTotalsCollectedFlag(false)->collectTotals()->save();
return $quote->getPayment()->getId();
}
}