Erreur "Impossible d’enregistrer la classe dans le répertoire de code"

Cet article décrit comment résoudre le problème en raison duquel la manière dont vous avez spécifié les dépendances empêche la génération automatique des classes à la volée et vous obtenez le message d’erreur "Class can be save in the generated/code directory" (La classe ne peut pas être enregistrée dans le répertoire généré/code").

Produits et versions concernés

  • Adobe Commerce sur l’infrastructure cloud 2.2.0 ou version ultérieure

Problème

Étapes à reproduire

  1. Dans votre environnement local, écrivez une classe personnalisée avec une dépendance sur la classe générée automatiquement.
  2. Exécutez le scénario, où votre classe personnalisée est déclenchée, et vérifiez qu’elle fonctionne correctement.
  3. Validez et envoyez vos modifications à l’environnement d’intégration. Cela déclencherait le processus de déploiement. Le déploiement a réussi.
  4. Dans l' environnement d'intégration, exécutez le scénario où votre classe personnalisée est déclenchée.

Résultat attendu

Tout fonctionne correctement, de la même manière que dans votre environnement local.

Résultat réel

Échec avec le message d’erreur indiquant que votre classe ne peut pas être enregistrée dans le répertoire generated/code.

Cause

La cause du problème est que la classe sur laquelle vous avez une dépendance, n’est pas générée pendant le déploiement et ne peut pas être générée ultérieurement à la volée lorsque la classe est déclenchée, car le répertoire generated/code n’est pas disponible pour écriture une fois le déploiement terminé.

Deux raisons principales peuvent expliquer cette situation :

  • Cas 1 : la classe avec des dépendances sur les classes générées automatiquement se trouve dans le point d’entrée (comme index.php ), qui n’est pas analysé pour les dépendances lors du déploiement.
  • Cas 2 : la dépendance à la classe générée automatiquement est spécifiée directement (par rapport à l’utilisation recommandée du constructeur pour déclarer la dépendance).

Solution

Une solution courante pour les deux cas serait de créer une véritable usine au lieu de la classe générée automatiquement.

Ou il existe une solution particulière pour chaque cas.

Solution spécifique au cas 1

Déplacez le code de classe du point d’entrée vers un module distinct, puis utilisez-le dans le point d’entrée.

Exemple

Code d’origine dans, par exemple, 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

Vous devez effectuer les étapes suivantes :

  1. Déplacez la définition de classe vers app/code/YourVendor/YourModule :

    code language-php
       <?php
        namespace YourVendor\YourModule;
        use YourVendor\YourModule\Model\GeneratedFactory;
        class YourClass
        {
            private $generatedFactory;
    
            public function __construct(GeneratedFactory $generatedFactory)
            {
                $this->generatedFactory = $generatedFactory;
            }
        // Some code here...
        }
    
  2. Modifiez le point d’entrée my_api/index.php de sorte qu’il ressemble à ce qui suit :

    code language-php
      <?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
    

Solution spécifique à Cas 2

Déplacez la déclaration de dépendance vers le constructeur.

Exemple

Déclaration de classe d’origine :

<?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...
}

Vous devez modifier son constructeur comme suit :

<?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...
}

Lecture connexe

recommendation-more-help
8bd06ef0-b3d5-4137-b74e-d7b00485808a