Question

I am trying to overriding vendor/magento/module-tax/Model/Calculation.php class in custom module by using preference and pass the class \Magento\Checkout\Model\Cart in __construct function.

I have tried it by below code:

<?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\Tax\Model\Calculation" type="Vendor\Customtax\Model\Calculation" />
</config>

and below is my Calculation.php file

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Vendorname\CustomTax\Model;

 class Calculation extends \Magento\Tax\Model\Calculation

{
 
   
 public function getRateRequest(
        $shippingAddress = null,
        $billingAddress = null,
        $customerTaxClass = null,
        $store = null,
        $customerId = null
    ) {
        

          --- here is my Logic----

}

Now I want to pass the class \Magento\Checkout\Model\Cart $cart in construct method.

Please suggest me how to override construct method.When Trying To override Function it is not working well and throw the error.

Was it helpful?

Solution

First of all I want to say that your approach might not be the best one. I don't have all the facts and I don't know what your requirement is, but I have a feeling that making the tax calculator depend on your cart class may not be the best idea. Maybe your should explain the problem you are trying to solve instead of how you are trying to solve it. Maybe there is another way to do it instead of rewriting the class and adding a new dependency to it.
But in case you want to go on with this approach, here is how you can add the Cart class as a new dependency to your class.

add this member to your class

/**
 * @var \Magento\Checkout\Model\Cart
 */
protected $cart;

Make your class constructor look like this

public function __construct(
    \Magento\Framework\Model\Context $context,
    \Magento\Framework\Registry $registry,
    \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
    \Magento\Tax\Model\Config $taxConfig,
    \Magento\Store\Model\StoreManagerInterface $storeManager,
    \Magento\Customer\Model\Session $customerSession,
    \Magento\Customer\Model\CustomerFactory $customerFactory,
    \Magento\Tax\Model\ResourceModel\TaxClass\CollectionFactory $classesFactory,
    \Magento\Tax\Model\ResourceModel\Calculation $resource,
    \Magento\Customer\Api\AccountManagementInterface $customerAccountManagement,
    \Magento\Customer\Api\GroupManagementInterface $customerGroupManagement,
    \Magento\Customer\Api\GroupRepositoryInterface $customerGroupRepository,
    \Magento\Customer\Api\CustomerRepositoryInterface $customerRepository,
    \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency,
    \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder,
    \Magento\Framework\Api\FilterBuilder $filterBuilder,
    \Magento\Tax\Api\TaxClassRepositoryInterface $taxClassRepository,
    \Magento\Checkout\Model\Cart $cart,
    \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
    array $data = []
) {
     $this->cart = $cart;
     parent::__construct(
         $context,
         $registry,
         $scopeConfig,
         $taxConfig,
         $storeManager,
         $customerSession,
         $customerFactory,
         $classesFactory,
         $resource,
         $customerAccountManagement,
         $customerGroupManagement,
         $customerGroupRepository,
         $customerRepository,
         $priceCurrency,
         $searchCriteriaBuilder,
         $filterBuilder,
         $taxClassRepository,
         $resourceCollection,
         $data
     );
}

Now you can use $this->cart everywhere in your class.

Some explanation of what the code above means.
Your new class constructor has the same parameters as the parent class constructor with one addition \Magento\Checkout\Model\Cart $cart.
You can add this new parameter anywhere in the list, the order is not important, but it has to be above the optional parameters. I added it right between the required parent method parameters and the optional parameters. I find it easier to keep track of them (there was also at one point a static code test that complained if you do it differently, but this does not affect the proper functioning of your code).

When your class gets instantiated, the factory that does this (object manager) reads the signature of your constructor method, and gets the required dependencies from the DIC (dependency injection container) if they exist, if not it instantiates them and passes them as parameters to your constructor.
calling parent::__construct with the original class parameters will ensure that the original dependencies are attached to your class also.

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top