This article describes how to fix the issue where the way you specified dependencies prevents classes from being auto-generated on the fly, and you get the “Class cannot be saved in the generated/code directory” error message.
Steps to reproduce
Expected result
Everything works correctly, the same way as in your local environment.
Actual result
Failure with the error message saying that your class cannot be saved in the generated/code
directory.
The cause of the problem is that the class on which you have dependency, does not get generated during the deployment, and cannot be generated later on the fly when the class is triggered, because the generated/code
directory is unavailable for writing after deployment is completed.
There are two main reasons why this could happen:
index.php
), which is not scanned for dependencies during deployment.One common solution for both cases would be creating a real factory instead of the auto-generated class.
Or there is a particular solution for each case.
Move your class code from the entry point to a separate module and then use it in the entry point.
Example
Original code in, for example, index2.php
:
<?php
use YourVendor\SomeModule\Model\GeneratedFactory;
require realpath(__DIR__) . '/../app/bootstrap.php';
$bootstrap = \Magento\Framework\App\Bootstrap::create(BP, $_SERVER);
class SomeClass
{
private $generatedFactory;
public function __construct(GeneratedFactory $generatedFactory)
{
$this->generatedFactory = $generatedFactory;
}
// Some code here...
}
$someObject = $bootstrap->getObjectManager()->create(SomeClass::class);
// There is some code that uses $someObject
You need to take the following steps:
Move the class definition to app/code/YourVendor/YourModule
:
<?php
namespace YourVendor\YourModule;
use YourVendor\YourModule\Model\GeneratedFactory;
class YourClass
{
private $generatedFactory;
public function __construct(GeneratedFactory $generatedFactory)
{
$this->generatedFactory = $generatedFactory;
}
// Some code here...
}
Edit the entry point my_api/index.php
so that it looks like following:
<?php
use YourVendor\YourModule\YourClass;
require realpath(__DIR__) . '/../app/bootstrap.php';
$bootstrap = \Magento\Framework\App\Bootstrap::create(BP, $_SERVER);
$someObject = $bootstrap->getObjectManager()->create(YourClass::class);
// Some code using $someObject
Move dependency declaration to the constructor.
Example
Original class declaration:
<?php
namespace YourVendor\YourModule;
use YourVendor\SomeModule\Model\GeneratedFactory;
use Magento\Framework\App\ObjectManager;
class YourClass
{
private $generatedFactory;
private $someParam;
public function __construct($someParam)
{
$this--->someParam = $someParam;
$this->generatedFactory = ObjectManager::getInstance()->get(GeneratedFactory::class);
}
// Some code here...
}
You need to change its constructor as following:
<?php
namespace YourVendor\YourModule;
use YourVendor\YourModule\Model\GeneratedFactory;
use Magento\Framework\App\ObjectManager;
class YourClass
{
private $generatedFactory;
private $someParam;
public function __construct($someParam, GeneratedFactory $generatedFactory = null)
{
$this->someParam = $someParam;
$this->generatedFactory = $generatedFactory ?: ObjectManager::getInstance()->get(GeneratedFactory::class);
}
// Some code here...
}