Symfony 3 - Автоматическое создание BOOLEAN-приемников и сеттеров - isActive vs getActive

Автогенераторы BOOLEAN-приемники и сеттеры - разный выход

Symfony3.2.0: php bin/console vs PhpStorm 2016.3

Кажется, что в сгенерированном коде существует разница, если я использую командную строку doctrine:generate:entities или использую функцию PhpStorm Generate - Getters and Setters по значению BOOLEAN в классе Entity.

Пример: Я установил эту приватную переменную, ниже приведены 3 примера для генерации Getters/Setters, которые дают несколько отличный результат.

/**
 * @var boolean
 * @ORM\Column(name="active", type="boolean")
 */
private $active;

# Generated 'getter' from command line = getActive()
# Generated 'getter' from PhpStorm = isActive()

Консольная команда: php bin/console doctrine:generate:entities MyBundle:MyEntity (обратите внимание: getActive, return boolean)

/**
 * Set active
 *
 * @param boolean $active
 *
 * @return MyEntity
 */
public function setActive($active)
{
    $this->active = $active;

    return $this;
}

/**
 * Get active
 *
 * @return boolean
 */
public function getActive()
{
    return $this->active;
}

Внутри PhpStorm - Код > Сгенерировать (Alt + Insert) > Getters and Setters (с флажком "Свободные сеттеры" включен) (примечание: isActive, return BOOL)

/**
 * @return bool
 */
public function isActive()
{
    return $this->active;
}

/**
 * @param bool $active
 * @return MyEntity
 */
public function setActive($active)
{
    $this->active = $active;
    return $this;
}

и еще один: PhpStorm - код > Создать (Alt + Insert) > Getters and Setters (с флажком "Свободные сеттеры" отключено) (примечание: isActive, return bool и setActive не возвращает $this)

/**
 * @return bool
 */
public function isActive()
{
    return $this->active;
}

/**
 * @param bool $active
 */
public function setActive($active)
{
    $this->active = $active;
}

Мои вопросы:

  • Может ли инструмент командной строки doctrine:generate:entities каким-то образом настроиться на генерации для булевых значений автоматически как is... вместо "получить..."? (так что всегда генерирует логические методы getter как: isActive(), isEnabled() и т.д.)

  • Я видел несколько примеров/учебников, в которых метод setActive() не возвращал $this, поэтому никакая цепочка не могла использоваться. Лучше ли возвращать $this? Каким будет предпочтительный способ? (Есть ли недостаток, когда вы возвращаете $this, возможно, производительность?)

  • Влияет ли незначительное различие типа возврата в разделе комментариев на приложение (миграция базы данных с командной строкой или что-то еще)? Или типы bool и boolean обрабатываются одинаково везде в Symfony?

(3. Пример)

@return bool (Generated by command line)
vs
@return boolean (Generated by PhpStorm)

Ответ 1

Я немного играл с кодом и, к сожалению, нет способа генерировать его по-разному с существующей настройкой. Все классы жестко закодированы, и нет возможности переопределить его с помощью команд или настроек Symfony.

Итак, я немного расширил классы генераторов и создал расширенную команду, которая принимает генератор в качестве параметра. Я также создал генератор выборок, который создал методы "is..." для установки булевых элементов.

К сожалению, существует некоторая копия-вставка из существующих классов, потому что ее невозможно расширить.

Отвечая на второй вопрос, я думаю, что это более личное предпочтение, используя свободный интерфейс. Я старый школьный разработчик, и я не привык к свободному интерфейсу в PHP. Я не вижу существенного влияния на производительность.

Для третьего вопроса. Разница между bool и boolean заключается в том, что bool является объявление скалярного типа, а boolean - тип переменной. См. "Предупреждение" в документации. Это объясняет многое.

<?php
// src/AppBundle/Command/GenerateDoctrineEntityExtendedCommand.php
namespace AppBundle\Command;

use Sensio\Bundle\GeneratorBundle\Command\GenerateDoctrineEntityCommand;
use Sensio\Bundle\GeneratorBundle\Generator\Generator;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

class GenerateDoctrineEntityExtendedCommand extends GenerateDoctrineEntityCommand
{
    /** @var Generator */
    private $generator;

    protected function configure()
    {
        parent::configure();
        $this->setName('doctrine:generate:entity:extended');
        $this->setDescription($this->getDescription() . " Allows specifying generator class.");
        $this->addOption('generator', null, InputOption::VALUE_REQUIRED, "The generator class to create entity.", 'Sensio\Bundle\GeneratorBundle\Generator\DoctrineEntityGenerator');
    }

    protected function initialize(InputInterface $input, OutputInterface $output)
    {
        parent::initialize($input, $output);
        if ($class = $input->getOption('generator')) {
            if (!class_exists($class)) {
                throw new \Exception('Class ' . $class . 'does not exist.');
            }
            $this->generator = new $class($this->getContainer()->get('filesystem'), $this->getContainer()->get('doctrine'));
        }
    }

    protected function createGenerator()
    {
        return $this->generator;
    }
}

Замена DoctrineEntityGenerator:

<?php
// src/AppBundle/Generator/IsDoctrineEntityGenerator.php
namespace AppBundle\Generator;

use Sensio\Bundle\GeneratorBundle\Generator\DoctrineEntityGenerator;

class IsDoctrineEntityGenerator extends DoctrineEntityGenerator
{
    protected function getEntityGenerator()
    {
        // This is the place where customized entity generator is instantiated instead of default
        $entityGenerator = new IsEntityGenerator();
        $entityGenerator->setGenerateAnnotations(false);
        $entityGenerator->setGenerateStubMethods(true);
        $entityGenerator->setRegenerateEntityIfExists(false);
        $entityGenerator->setUpdateEntityIfExists(true);
        $entityGenerator->setNumSpaces(4);
        $entityGenerator->setAnnotationPrefix('ORM\\');

        return $entityGenerator;
    }
}

Замена EntityGenerator:

<?php
// src/AppBundle/Generator/IsEntityGenerator.php
namespace AppBundle\Generator;

use Doctrine\Common\Inflector\Inflector;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Doctrine\ORM\Tools\EntityGenerator;
use Doctrine\DBAL\Types\Type;

class IsEntityGenerator extends EntityGenerator
{
    protected function generateEntityStubMethod(ClassMetadataInfo $metadata, $type, $fieldName, $typeHint = null, $defaultValue = null)
    {
        //
        // This is the only line I've added compared to the original method
        //
        $methodPrefix = ($type == 'get' && $typeHint == 'boolean') ? 'is' : $type;
        $methodName = $methodPrefix . Inflector::classify($fieldName);

        $variableName = Inflector::camelize($fieldName);
        if (in_array($type, array("add", "remove"))) {
            $methodName = Inflector::singularize($methodName);
            $variableName = Inflector::singularize($variableName);
        }

        if ($this->hasMethod($methodName, $metadata)) {
            return '';
        }
        $this->staticReflection[$metadata->name]['methods'][] = strtolower($methodName);

        $var = sprintf('%sMethodTemplate', $type);
        $template = static::$$var;

        $methodTypeHint = null;
        $types = Type::getTypesMap();
        $variableType = $typeHint ? $this->getType($typeHint) : null;

        if ($typeHint && !isset($types[$typeHint])) {
            $variableType = '\\' . ltrim($variableType, '\\');
            $methodTypeHint = '\\' . $typeHint . ' ';
        }

        $replacements = array(
            '<description>' => ucfirst($type) . ' ' . $variableName,
            '<methodTypeHint>' => $methodTypeHint,
            '<variableType>' => $variableType,
            '<variableName>' => $variableName,
            '<methodName>' => $methodName,
            '<fieldName>' => $fieldName,
            '<variableDefault>' => ($defaultValue !== null) ? (' = ' . $defaultValue) : '',
            '<entity>' => $this->getClassName($metadata)
        );

        $method = str_replace(
            array_keys($replacements),
            array_values($replacements),
            $template
        );

        return $this->prefixCodeWithSpaces($method);
    }
}

Так что я боюсь единственного варианта того, что вы хотите до сих пор.

Ответ 2

Степашка правильно ответил.

Но я думаю, что есть лучший, упрощенный и более обычный способ помочь вам использовать PhpStorm автоматически генерировать методы Getters и Setters с Symfony.

Вы можете настроить методы генерации генерации PhpStorm Getters и Setters!

Вам просто нужно пойти: Предпочтения/Редактор/Шаблоны файлов и кодов/Код

Затем для Getter, чтобы изменить isActive на getActive, вы должны изменить "Метод PHP Getter" на:

/*
 * @return ${TYPE_HINT}
 */
public ${STATIC} function get${NAME}()#if(${RETURN_TYPE}): ${RETURN_TYPE}#else#end
{
#if (${STATIC} == "static")
    return self::$${FIELD_NAME};
#else
    return $this->${FIELD_NAME};
#end
}

для Setter, чтобы добавить "return $this", вам нужно изменить "PHP Setter Method" на:

/*
 * @param ${TYPE_HINT} $${PARAM_NAME}
 * @return ${CLASS_NAME}
 */
public ${STATIC} function set${NAME}(#if (${SCALAR_TYPE_HINT})(${SCALAR_TYPE_HINT} #else#end$${PARAM_NAME})
{
#if (${STATIC} == "static")
    self::$${FIELD_NAME} = $${PARAM_NAME};
#else
    $this->${FIELD_NAME} = $${PARAM_NAME};
#end
    return $this;
}

Наконец, не забудьте применить изменения.