Private API is used on the project level

Edit on GitHub

Modules have public and private APIs. While public API updates always support backward compatibility, private API updates can break backward compatibility. So, backward compatibility is not guaranteed in the private API. For example, if you use a core method on the project level, and it is updated or removed with an update, it can cause unexpected issues.

For more information about module APIs, see Definition of Module API.

Example of code that causes an upgradability error

CustomerFacade uses createCustomerReader and getCustomerCollection from a private API.

namespace Pyz\Zed\Customer\Business;

use Spryker\Zed\Customer\Business\CustomerFacade as SprykerCustomerFacade;

/**
 * @method \Pyz\Zed\Customer\Business\CustomerBusinessFactory getFactory()
 */
class CustomerFacade extends SprykerCustomerFacade implements CustomerFacadeInterface
{
   /**
     * ...
     */
    public function getCustomerCollection(...): ...
    {
        return $this->getFactory()
            ->createCustomerReader()
            ->getCustomerCollection(...);
    }
}
------------------------------------------------------------------------------------------------------------------------
PrivateApi:Facade "Please avoid Spryker dependency: Spryker\...\CustomerReader::getCustomerCollection(...) in Pyz\Zed\Customer\Business\CustomerFacade"
************************************************************************************************************************

Resolving the error

To resolve the error provided in the example, try the following in the provided order:

  1. Recommended: Extend the functionality using the Configuration strategy.
  2. Recommended: Extend the functionality using the Plug and Play strategy.
  3. Recommended: Extend the functionality using the Project Modules strategy.
  4. Not recommended: Copy the functionality from the core to the project level:
    1. Register the missing extension point in Spryker Ideas, so we add it in future.
    2. Copy private API core entities to the project level and give them unique names. For an example, see Example of resolving the error by copying and renaming the entities.
    3. As soon as the extension point in core is released, refactor the code added in step 4.2 using the strategies in steps 1-3. While it’s not refactored, auto-upgrades are not supported, and the effort to update the project may be bigger and require more manual work.

Example of resolving the error by renaming private API entities

  1. Give the method a unique name and copy it to the factory to fetch the business models. In the example, we add Pyz to its name, but you can use any other strategy. For example, you can prefix them with your project name.
namespace Pyz\Zed\Customer\Business;

use Spryker\Zed\Customer\Business\CustomerFacade as SprykerCustomerFacade;

/**
 * @method \Pyz\Zed\Customer\Business\CustomerBusinessFactory getFactory()
 */
class CustomerFacade extends SprykerCustomerFacade implements CustomerFacadeInterface
{
   /**
     * ...
     */
    public function getCustomerCollection(...): ...
    {
        return $this->getFactory()
            ->createPyzCustomerReader()
            ->getPyzCustomerCollection(...);
    }
}
namespace Pyz\Zed\Customer\Business;

use Pyz\Zed\Customer\Business\Customer\CustomerReader;
use Spryker\Zed\Customer\Business\CustomerBusinessFactory as SprykerCustomerBusinessFactory;

class CustomerBusinessFactory extends SprykerCustomerBusinessFactory
{
    /**
     * @return \Pyz\Zed\Customer\Business\Customer\CustomerReaderInterface
     */
    public function createPyzCustomerReader(): CustomerReaderInterface
    {
        return new CustomerReader(...);
    }
}
  1. Copy the method to the business model.
namespace Pyz\Zed\Customer\Business\Customer;

use Spryker\Zed\Customer\Business\Customer\CustomerReader as SprykerCustomerReader;

class CustomerReader extends SprykerCustomerReader implements CustomerReaderInterface
{
    /**
     * ...
     */
    public function getPyzCustomerCollection(...)
    {
        ...
    }
}

After the fix re-evaluate the code. The same error shouldn’t be returned.