Bibliothèque autonome PHP pour générer un modèle de constructeur à partir d'une classe.
En utilisant composer sur votre projet ou globalement
composer require natitech/builder-generator
composer global require natitech/builder-generator
Vous pouvez utiliser le binaire pour générer un builder à proximité d'une classe :
/path/to/vendor/bin/generate-builder /path/to/class
OU vous pouvez l'utiliser dans un autre script PHP :
Nati BuilderGenerator FileBuilderGenerator:: create ()-> generateFrom ( ' /path/to/class ' );
Cela générera une classe de constructeur en dehors de la classe construite.
Exemple :
//From /path/to/MyClass.php file = the built class
class MyClass {
public int $ id ;
public string $ label ;
}
//This new file /path/to/MyClassBuilder.php will be generated = the builder class
class MyClassBuilder {
private int $ id ;
private string $ label ;
public function __construct ( Faker $ faker )
{
$ this -> id = $ faker -> number ();
$ this -> label = $ faker -> word ;
}
public function build (): MyClass
{
$ myClass = new MyClass ();
$ myClass -> id = $ this -> id ;
$ myClass -> label = $ this -> label ;
return $ myClass ;
}
//this will have to be generated by your IDE
public function withLabel ( string $ label ): self
{
$ this -> label = $ label ;
return $ this ;
}
}
//The ultimate goal is to use this in tests
/** @test */
public function canTestSomething ()
{
$ this -> assertEquals (
' test ' ,
$ this -> service -> something ( $ this -> myClass ()-> withLabel ( ' used in test ' )-> build ())
);
}
private function myClass (): MyClassBuilder
{
return new MyClassBuilder ( Faker Factory:: create ());
}
La classe de générateur peut avoir besoin de recevoir des mises à jour sur le style de code, les utilisations frauduleuses, les types déduits, l'espace de noms, etc. De plus, pour éviter de produire du code inutilisé, il n'existe aucun paramètre pour les propriétés du générateur. Votre IDE devrait être capable de résoudre facilement tout cela.
Le générateur tentera de détecter les types de propriétés (types php, types phpdoc, attributs ou annotations de doctrine ou de formulaire) et tentera de détecter la méthode de falsification appropriée en fonction du type et du nom des propriétés.
Vous pouvez utiliser l'option --faker pour essayer de définir les valeurs les plus pertinentes. Dans ce cas, Faker sera utilisé comme dépendance de la classe builder.
Il existe de nombreuses stratégies pour construire une classe : propriétés publiques, setter (courant ou non), constructeur. Une brève explication de chaque stratégie est donnée ci-dessous, mais vous préférerez peut-être lire les tests unitaires pour bien les comprendre.
Par défaut, le générateur tentera de détecter la stratégie la plus utilisée à l'intérieur de la classe construite et l'utilisera pour l'ensemble de la classe constructeur. Si vous utilisez des setters sur toutes les propriétés sauf une, le générateur utilisera des setters sur les propriétés qui le prennent en charge et ignorera la propriété qui ne le prend pas en charge.
Mais vous pouvez également transmettre explicitement une stratégie en utilisant l'option '--strategy'.
Lorsque les propriétés sont publiques. Voir exemple ci-dessus.
Lorsque les propriétés sont protégées/privées et définies dans la méthode __construct.
//Built class
class MyClass {
private int $ id ;
public function __construct ( int $ id , private string $ label )
{
$ this -> id = $ id ;
}
}
//Builder class
class MyClassBuilder {
private int $ id ;
private string $ label ;
public function __construct ( Faker $ faker )
{
$ this -> id = $ faker -> number ();
$ this -> label = $ faker -> word ;
}
public function build (): MyClass
{
return new MyClass (
$ this -> id ,
$ this -> label
);
}
}
Lorsque les propriétés sont protégées/privées mais peuvent être définies à l'aide de paramètres publics. Les passeurs peuvent parler couramment ou non.
//Built class
class MyClass {
protected int $ id ;
protected string $ label ;
public function setId ( int $ id )
{
$ this -> id = $ id ;
return $ this ;
}
public function setLabel ( string $ label )
{
$ this -> label = $ label ;
return $ this ;
}
}
//Builder class
class MyClassBuilder {
private int $ id ;
private string $ label ;
public function __construct ( Faker $ faker )
{
$ this -> id = $ faker -> number ();
$ this -> label = $ faker -> word ;
}
public function build (): MyClass
{
return ( new MyClass ())
-> setId ( $ this -> id )
-> setLabel ( $ this -> label );
}
}
C'est une manière moins conventionnelle de créer une classe. Dans ce cas, les propriétés sont protégées/privées et définies par des méthodes du domaine public. Il n’existe donc pas de moyen simple de définir la classe construite dans un certain état. Si, à des fins de test, vous souhaitez pouvoir définir rapidement l'état des propriétés de cet objet par propriétés, une solution consiste à ajouter une méthode build() statique dans la classe construite.
//Built class
class MyClass {
private int $ id ;
private ? string $ label = null ;
public static function create ( int $ id ): self
{
$ myClass = new self ();
$ myClass -> id = $ id ;
return $ myClass ;
}
public function updateLabel ( string $ label ): self
{
$ this -> label = $ label ;
return $ this ;
}
//This method will have to be generated by you IDE from the builder class
//It allows you to hack the state of this object without relying on its public interface
public static function build ( int $ id , string $ label ): self
{
$ myClass = new self ();
$ myClass -> id = $ this -> id ;
$ myClass -> label = $ this -> label ;
return $ myClass ;
}
}
//Builder class
class MyClassBuilder {
private int $ id ;
private string $ label ;
public function __construct ( Faker $ faker )
{
$ this -> id = $ faker -> number ();
$ this -> label = $ faker -> word ;
}
public function build (): MyClass
{
return MyClass:: build (
$ this -> id ,
$ this -> label
);
}
}
Pour créer une stratégie personnalisée :
NatiBuilderGeneratorPropertyPropertyBuildStrategy
et l'ajouter à NatiBuilderGeneratorPropertyPropertyBuildStrategyCollection
. Cela décidera COMMENT les propriétés sont construites.NatiBuilderGeneratorAnalyzerBuildableClassAnalyzer::getWriteStrategies()
. Cela décidera QUAND les propriétés pourraient être construites avec cette stratégie. Vous pouvez utiliser cet outil comme outil externe dans votre IDE.
Pour les utilisateurs de PHPStorm, consultez https://www.jetbrains.com/help/phpstorm/configuring-third-party-tools.html. Exemple de configuration :