PhpStorm - 设置 setter 和 getter

PhpStorm - setting setters and getters

PhpStorm 在快速创建 setter 和 getter 时有一个有用的功能:

Code -> generate -> select the items to generate 

这非常适合设置基本 setters/getters。

然而,有时我想设置的不仅仅是 setter 和 getter。例如,我可能想为一对多或多对多关系创建 setter 和 getter。

多对多

/**
 * {@inheritDoc}
 */
public function getOwner()
{
    return $this->owner->toArray();
}

/**
 * Set the list of user
 * @param Collection $owner
 */
public function setOwner( Collection $owner )
{
    $this->registeredUsers->clear();

    foreach ( $owner as $item ) {
        $this->owner[] = $item;
    }
}

/**
 * Add merchant to the collection
 * @param Collection $owner
 */
public function addOwner( Collection $owner )
{
    foreach( $owner as $item ) {
        $this->owner->add( $item );
    }
}

/**
 * @param Collection $owner
 */
public function removeOwner( Collection $owner )
{
    foreach( $owner as $item ) {
        $this->owner->removeElement( $item );
    }
}

有没有办法通过相同的代码生成过程来做到这一点?

很遗憾,ATM PhpStorm 不支持此类功能。

https://youtrack.jetbrains.com/issue/WI-25003 -- 观看这张票 (star/vote/comment) 以获得任何进展的通知(到目前为止,它还没有计划用于任何特定的未来版本 -- 可能是因为投票数非常低 - - 有点像:没有投票 = 没有兴趣 = 现在不需要投入资源)。

相关:https://youtrack.jetbrains.com/issue/WI-19891


我现在能想到的唯一选择(将使用该代码生成功能).. 是修改 Getter/Setter 的模板,使其包含多个方法 (example) .这样你就可以一次性生成 setXXX/addXXXgetXXX/removeXXX 方法。

显然,它适用于所有情况,因此如果您只需要 get/set,那么您需要手动删除 add/remove 方法——这是这种方法的缺点。

请注意,文件和代码模板可以是 IDE 范围的(Default 架构)或特定于项目的(Project 架构).. 所以您可以使用这样的组合 getters/setters 仅在某些项目中。

https://www.jetbrains.com/help/phpstorm/2016.1/file-and-code-templates-2.html


唯一的其他选择是 半手动 并要求您使用 Live Templates.

  • 制作实际的实时模板(一次性工作)
  • 您需要手动找到您要放置此代码的位置
  • 调用实时模板扩展(以便插入代码模板)
  • 填写所有实时模板变量以完成代码。

使用您的 addXXX/removeXXX 代码示例,您 可能 最终只填充 1 或 2 个模板变量(只是对我的内容的快速估计看;同一个变量可以多次使用,因此将同时填充在几个地方;输入的文本可以转换(有限的转换集),因此可以自动在另一个变量中重复使用(例如,您正在输入 owner 并且在另一个地方它被自动用作 Owner).

看看这个:

#set ($array = $TYPE_HINT.split('\|'));
#set ($IS_COLLECTION = false);
#set ($FIXED_RETURN_TYPE = $RETURN_TYPE);
#set ($NAME_LENGTH = $FIELD_NAME.length());
#set ($NAME_BEFORE_LAST = $FIELD_NAME.length() - 1);
#set ($LAST_CHARACTER = $FIELD_NAME.substring($NAME_BEFORE_LAST, $NAME_LENGTH));
#set ($METHOD_NAME_BEFORE_LAST = $NAME.length() - 1);

#if (${LAST_CHARACTER} == 's')
    #set ($FIXED_PROPERTY_NAME = $FIELD_NAME.substring(0, $NAME_BEFORE_LAST));
    #set ($FIXED_METHOD_NAMING_PART = $NAME.substring(0, $METHOD_NAME_BEFORE_LAST));
#else
    #set ($FIXED_PROPERTY_NAME = $FIELD_NAME);
    #set ($FIXED_METHOD_NAMING_PART = $NAME);
#end

#foreach($hint in $array)
    #if ($hint.toString().contains('[]'))
        #set ($ENTRY_HINT = $hint.toString().replace('[]', ''));
        #set ($HAS_ENTRY_HINT = true);
    #end
#end

#foreach($hint in $array)
    #if ($hint == 'Collection')
        #set ($IS_COLLECTION = true)
        #set ($FIXED_RETURN_TYPE = 'Collection')
        #break
    #elseif ($hint == 'ArrayCollection')
        #set ($IS_COLLECTION = true)
        #set ($FIXED_RETURN_TYPE = 'Collection')
        #break
    #elseif ($hint == 'array')
        #set ($IS_COLLECTION = true)
        #set ($FIXED_RETURN_TYPE = 'array')
    #elseif ($hint.toString().contains('[]'))
        #set ($IS_COLLECTION = true)
        #set ($FIXED_RETURN_TYPE = 'array')
    #end
#end

#if ($IS_COLLECTION)
/**
 * @param ${ENTRY_HINT} $${FIXED_PROPERTY_NAME}
 *
 * @return ${CLASS_NAME}
 */
public function add${FIXED_METHOD_NAMING_PART}(#if (${HAS_ENTRY_HINT})${ENTRY_HINT} #else#end$${FIXED_PROPERTY_NAME})#if(${RETURN_TYPE}): ${CLASS_NAME}#else#end
{
#if ($FIXED_RETURN_TYPE == 'Collection')
    if(false === $this->${FIELD_NAME}->contains($${FIXED_PROPERTY_NAME})) {
        $this->${FIELD_NAME}->add($${FIXED_PROPERTY_NAME});
    }
#else
    if(false === in_array($${FIXED_PROPERTY_NAME}, $this->${FIELD_NAME}, true)) {
        $this->${FIELD_NAME}[] = $${FIXED_PROPERTY_NAME};
    }
#end

    return $this;
}

/**
 * @param ${ENTRY_HINT} $${FIXED_PROPERTY_NAME}
 *
 * @return ${CLASS_NAME}
 */
public function remove${FIXED_METHOD_NAMING_PART}(#if (${HAS_ENTRY_HINT})${ENTRY_HINT} #else#end$${FIXED_PROPERTY_NAME})#if(${RETURN_TYPE}): ${CLASS_NAME}#else#end
{
#if ($FIXED_RETURN_TYPE == 'Collection')
    if(true === $this->${FIELD_NAME}->contains($${FIXED_PROPERTY_NAME})) {
        $this->${FIELD_NAME}->removeElement($${FIXED_PROPERTY_NAME});
    }
#else
    if(true === in_array($${FIXED_PROPERTY_NAME}, $this->${FIELD_NAME}, true)) {
        $index = array_search($${FIXED_PROPERTY_NAME}, $this->${FIELD_NAME});
        array_splice($this->${FIELD_NAME}, $index, 1);
    }
#end

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

我已经设法创建了类似的东西,请随意根据您的需要进行修改。这是流畅的setter实时模板。

它适用于 Doctrine 的 Collection/ArrayCollection 数组。扩展此功能就像创建新的 #elseif 语句一样简单。

/**
 * @var array|string[]
 */
protected $oneField;

/**
 * @var ArrayCollection|Collection|Another[]
 *
 * @ORM\OneToMany(targetEntity="Acme\DemoBundle\Entity\Another")
 */
protected $anotherField;