Skip to content

代码规范:全局强类型 #43

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
shaunthegeek opened this issue Jan 5, 2022 · 4 comments
Closed

代码规范:全局强类型 #43

shaunthegeek opened this issue Jan 5, 2022 · 4 comments
Assignees

Comments

@shaunthegeek
Copy link
Member

PHP 7 就支持强类型了,本项目有的地方写了类型,有的地方没写,需要 lint 强制检查。

https://www.php.net/manual/zh/migration70.new-features.php

@shaunthegeek shaunthegeek self-assigned this Jan 5, 2022
@shaunthegeek
Copy link
Member Author

查了下资料,这个开源规范包实现「强类型」:

https://github.com/slevomat/coding-standard#installation

而且还增加很多规则,需要研究一下

@shaunthegeek
Copy link
Member Author

发现一个有意思的问题,在 phpcs.xml 中配置了 PSR 12 + slevomat 规范,结果 fix 时自动加入了:

declare(strict_types=1);

然后再 lint,报错:

Expected strict_types = 1, found strict_types=1.

乍一看,以为是 slevomat 的 bug,打算提 PR,搜一下发现有人提问 slevomat/coding-standard#1304

看了下 slevomat 代码,发现里面声明了空格,不会出现这种错误。

再去查 PSR,发现是两个规范冲突了:

Declare statements MUST contain no spaces

https://www.php-fig.org/psr/psr-12/

解决方案:声明 DeclareStrictTypes,和 PSR 12 保持一致。

<?xml version="1.0"?>
<ruleset name="PSR12-Slevomat">
  <exclude-pattern>/vendor/</exclude-pattern>
  <arg name="extensions" value="php" />

  <!-- Include the whole PSR12 standard -->
  <rule ref="PSR12" />


  <config name="installed_paths" value="../../slevomat/coding-standard" />
  <rule ref="SlevomatCodingStandard.TypeHints.DeclareStrictTypes">
    <properties>
      <property name="declareOnFirstLine" value="false" />
      <property name="linesCountBeforeDeclare" value="1" />
      <property name="linesCountAfterDeclare" value="1" />
      <property name="spacesCountAroundEqualsSign" value="0" />
    </properties>
  </rule>
</ruleset>

需要注意:Slevomat 无法像 phpmd 规范那样引入整个规范,然后覆盖掉其中一条。slevomat/coding-standard#1325

@shaunthegeek
Copy link
Member Author

引入参数类型检查、返回类型检查,发现 array 有问题:

<?php

declare(strict_types=1);

namespace foo;

class User
{
    public function get(array $params): array
    {
        return [
            'params' => $params,
        ];
    }
}
<?xml version="1.0"?>
<ruleset name="PSR12-Slevomat">
  <exclude-pattern>/vendor/</exclude-pattern>
  <arg name="extensions" value="php" />

  <!-- Include the whole PSR12 standard -->
  <rule ref="PSR12" />

  <config name="installed_paths" value="../../slevomat/coding-standard" />
  <rule ref="SlevomatCodingStandard.TypeHints.ParameterTypeHint" />
  <rule ref="SlevomatCodingStandard.ControlStructures.DisallowYodaComparison" />
  <rule ref="SlevomatCodingStandard.TypeHints.DeclareStrictTypes">
    <properties>
      <property name="declareOnFirstLine" value="false" />
      <property name="linesCountBeforeDeclare" value="1" />
      <property name="linesCountAfterDeclare" value="1" />
      <property name="spacesCountAroundEqualsSign" value="0" />
    </properties>
  </rule>
  <rule ref="SlevomatCodingStandard.TypeHints.ReturnTypeHint" />
</ruleset>
./vendor/bin/phpcs --standard=phpcs.xml foo.php

ERROR | Method \foo\User::get() does not have @param annotation for its traversable parameter $params.
ERROR | Method \foo\User::get() does not have @return annotation for its traversable return value.

查了下,作者说:array 是无效的。slevomat/coding-standard#553

仔细想想,array 其实就是一种「弱类型」,无法约束里面是什么,或者说不知道里面是什么,而 Go 语言是不允许的,调用 api 返回 json,必须先声明 json 是哪个数据对象,那才是强类型。

@shaunthegeek
Copy link
Member Author

shaunthegeek commented Jan 5, 2022

都改成 mixed 没有意义,除非全部改成 数据对象,那就是 Go 了,所以决定放弃。
不过也没有白费,发现这个包里有一些有用的规则。

shaunthegeek added a commit that referenced this issue Jan 5, 2022
shaunthegeek added a commit that referenced this issue Jan 6, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant