Автономная библиотека PHP для создания шаблона компоновщика из класса.
Используя композитор в вашем проекте или глобально
composer require natitech/builder-generator
composer global require natitech/builder-generator
Вы можете использовать двоичный файл для создания построителя рядом с классом:
/path/to/vendor/bin/generate-builder /path/to/class
ИЛИ вы можете использовать его внутри другого PHP-скрипта:
Nati BuilderGenerator FileBuilderGenerator:: create ()-> generateFrom ( ' /path/to/class ' );
Это создаст класс строителя помимо построенного класса.
Пример :
//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 ());
}
Классу компоновщика может потребоваться получение обновлений о стиле кода, использовании мошенников, выведенных типах, пространстве имен и т. д. Кроме того, чтобы избежать создания неиспользуемого кода, для свойств компоновщика отсутствуют установщики. Ваша IDE должна легко все это исправить.
Генератор попытается обнаружить типы свойств (типы php, типы phpdoc, атрибуты или аннотации доктрины orm) и попытается обнаружить соответствующий метод-фальсификатор на основе типа и имени свойств.
Вы можете использовать опцию --faker, чтобы попытаться установить наиболее подходящие значения. В этом случае Faker будет использоваться как зависимость класса строителя.
Существует множество стратегий создания класса: общедоступные свойства, сеттер (свободный или нет), конструктор. Краткое объяснение каждой стратегии приведено ниже, но вы можете предпочесть прочитать модульные тесты, чтобы полностью понять их.
По умолчанию генератор попытается обнаружить наиболее используемую стратегию внутри построенного класса и будет использовать ее для всего класса строителя. Если вы используете установщики для всех свойств, кроме одного, генератор будет использовать установщики для свойств, которые его поддерживают, и игнорировать свойство, которое не поддерживает.
Но вы также можете явно передать стратегию, используя опцию --strategy.
Когда свойства являются общедоступными. См. пример выше.
Когда свойства защищены/частны и установлены внутри метода __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
);
}
}
Когда свойства защищены/частны, но могут быть установлены с помощью общедоступных установщиков. Сеттеры могут свободно говорить или нет.
//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 );
}
}
Это менее традиционный способ создания класса. В этом случае свойства являются защищенными/частными и устанавливаются общедоступными методами. Таким образом, не существует простого способа установить построенный класс в определенное состояние. Если в целях тестирования вы хотите иметь возможность быстро устанавливать состояние свойств этого объекта по свойствам, решением является добавление статического метода build() во встроенный класс.
//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
);
}
}
Чтобы создать собственную стратегию:
NatiBuilderGeneratorPropertyPropertyBuildStrategy
и добавить его в NatiBuilderGeneratorPropertyPropertyBuildStrategyCollection
. Это решит, КАК построена недвижимость.NatiBuilderGeneratorAnalyzerBuildableClassAnalyzer::getWriteStrategies()
. Это решит, КОГДА недвижимость может быть построена с использованием этой стратегии. Вы можете использовать этот инструмент как внешний инструмент в вашей IDE.
Для пользователя PHPStorm см. https://www.jetbrains.com/help/phpstorm/configuring- Third-party-tools.html. Пример конфигурации: