PHP kódminőség fenntartás
php, qa, static code checking, phpunit, phpcs, phpmd, phpstan, churn, phpdd, psalm, phplint, phan
2024-10-17
Failed: bson encoding error: BSON element key cannot contain null bytes
mongo, mongodb, bson, null, key
2024-08-24
Nem bízol a kollégáidban? Akkor valamit rosszul csinálsz!
bizalom vezetokent
2023-05-03
Dolgok, amikről a programozók azt hiszik, hogy tudják, de tévednek
programozoi-tevhitek-falsehoods
2023-04-08
A programozóktól meg kell szabadulni
chatgpt no-code low-code
2023-01-22
Miért fontosak a személyes adatok egyáltalán?
privacyaware, privacy
2023-01-07
Egy tanmese a szerény, de tehetséges informatikusról, akit én csak Gézának hívok
privacyaware, privacy
2023-01-02
Beskatulyáznád magad egy termékkel? Gondold át még egyszer!
learning, vendorlockin, risky
2022-12-11
Rekrúterekről és állásajánlatokról
bérsáv, recruiter, relevancia
2022-10-30
"A hídon akkor kell átmenni, amikor odaérünk."​ - YAGNI
yagni, pagni
2022-10-17
"A lényeg, hogy a munka készen legyen!"
agile, estimation, becsles, scrum, home office
2022-08-20
Munka vs. hivatás, a klasszikus dilemma
hr, hobbi, munka, egyensuly, hivatas
2022-07-18
Miért nem fogok nálatok technikai interjún részt venni?
technikai interju, hr, recruit, leet code, coding challenge, take home challenge
2022-07-04
"Hogyan építsek kapcsolati tőkét, ha karriert szeretnék váltani?"
linkedin, tippek, trukkok
2022-06-10
Junior/Medior/Senior, hogyan mérjük?
junior, medior, senior, hr, grade, level, experience
2022-05-09
11 tipp frontendeseknek, hogyan tegyék hatékonyabbá a munkájukat
frondend, vscode, angular
2021-10-31
Motion zoom - mozgás alapú képrekonstrukció
#52het
2021-06-01
Gesture Launcher
#52het
2021-05-31
CellEvent, első Android alkalmazásom
#52het
2021-05-19
Notebookcheck, azaz hogyan válasszuk ki a legjobb ár-érték arányú eszközt
#52het
2021-05-18
Torrent multiplexer
#52het
2021-05-17
Process watcher, logger
#52het
2021-05-05
Lazy loading material dialog content
lazy loading, angular, material, dialog
2020-12-28
Runtime configuration loading in Angular
angular, runtime, configuration, settings, environment, production
2020-03-29
How to start an Angular project?
angular
2020-03-11
Az 52 hét projekt
#52het
2020-01-01
Akkutöltöttség-jelző
#52het
2020-01-01
NetClub - Kollégiumi internetszolgáltató
#52het
2019-12-31
DeeJayy - Lost Terminal
#52het
2019-12-31
Counter Strike monitor
#52het
2019-12-31
Kollégiumi CS bajnokság 2005
#52het
2019-12-31
Mozgásérzékelős képrögzítő, Camera Capture
#52het
2019-12-30
Többszörös host pingelő
#52het
2019-12-30
Sávszélesség mérő, tesztelő
#52het
2019-12-30
Generáljunk hamis adatokat
#52het
2019-12-30
SQL lekérdezések parancssorból, odbc-vel
#52het
2019-12-30
Nonogram generátor (aka. "Fesse feketére")
#52het
2019-12-30
Egyedi chat alkalmazás, kliens és szerver
#52het
2019-12-29
FontSelector - betűtípusválasztó / font preview
#52het
2019-12-28
Saját hálózati kommunikációs segédszoftver - sox
#52het
2019-12-28
Csoportos e-mail küldő szoftver Delphiben
#52het
2019-12-28
Universal Api caller module for Angular 7-9 With NGRX state management
Ngrx, API, Effects, HttpClient
2019-07-02
A leghosszabb projekt
#52het
2019-04-19
Legelső kioszk projektem: Stari Sör Jukebox
#52het
2019-02-28
BPM számláló
#52het
2018-11-01
Assembly féléves beadandók
#52het
2018-11-01
Chatbot before it was cool
#52het
2018-10-30
StartX - Cseréljük ki a windows tálcáját és a Start menüt
#52het
2018-10-28
What? - fájltípus azonosító
#52het
2018-10-27
Transport Tycoon DirectX
#52het
2018-10-26
Diff - fájlösszehasonlító
#52het
2018-10-26
De Facto - Szoftverfelügyelet
#52het
2018-10-25
CD és DVD katalogizáló
#52het
2018-09-24
MP3 segédeszközök
#52het
2018-09-24
Keylogger - azaz billentyűleütés-figyelő és naplózó alkalmazás
#52het
2018-08-29
Az örök projekt: személyes weboldal és blog
#52het
2018-08-14
Szógyakorló nyelvtanuláshoz
#52het
2018-08-13
Warzone 2100 mentett játék szerkesztő
#52het
2018-08-13
Rejtett Windows-beállításokat konfiguráló program: TweakMaster
#52het
2018-08-13
A DrótPostaGalamb levelezőprogram adatfájljainak dekódolása
#52het
2018-08-13
Privacy jegyzet
2018-07-30
Egy éve ilyenkor
2018-07-25
The Matrix - konzol szimuláció
#52het
2018-07-13
Kakaóreceptkönyv
kakaó
2018-06-29
Crackelés!
#52het
2018-06-22
A K.I.T.T. challenge
#52het
2018-06-18
Doom 2 botokkal
#52het
2018-06-16
Römi játék Delphiben
#52het
2018-06-09
MeetsCow & DeeJayy - Intro
#52het
2018-06-09
Direct viewer - bitmap megjelenítő
#52het
2018-06-09
bazMAG
#52het
2018-06-09
Console Vision - Konzolos ablakkezelő Delphiben
#52het
2018-05-01
Quake 2 egy floppyn
#52het
2018-04-20
Játék-kitömörítők
#52het
2018-04-12
Tetszőleges program elrejtése Windows tálcáról
#52het
2018-04-05
Személyre szabás
#52het
2018-03-28
A year with Angular 5, 6 - Angular 2018
#angular5 #angular #resources #articles
2018-03-16
Az ikon evolúciója
#52het
2018-03-14
Betűtípusok
#52het
2018-03-04
Billentyűzet-gyakorló
#52het
2018-02-28
Zenél is a DeeJayy?
#52het
2018-02-22
Térképrajzoló az Ascii 3D labirintushoz
#52het
2018-02-19
Ascii 3D labyrinth
#52het
2018-02-14
52 hét - 52 projekt, avagy #eletem
#52het
2018-02-14
Dockerezzünk virtualizált környezetben!
docker, xen, ubuntu
2017-11-12
A cloud-initramfs-copymods hatásai paravirtualizált környezetben
ubuntu, xen, copymods, docker, docker-ce, docker.io
2017-11-11
Virtualizáljunk Xen 4.6-tal Ubuntu 16-on (Xenial)
ubuntu, xen, virtualizálás, hypervisor, debootstrap
2017-11-04
Álláskeresésem története
álláskeresés, it, fejvadászok, linkedin, job
2017-10-24
FAR Manager competitors
far manager, file managers
2010-01-01
Blog
blog
2001-01-02

PHP kódminőség fenntartás

Néha rámtör az "ezúttal mindent jól csinálok" érzés, ilyenkor megpróbálom az említett téma aspektusait a legmélyebb részletig kidolgozni. Két ilyen roham között általában van két verziónyi eltérés az eszközök között, így mindig van egy kis izgalom is, hogy éppen mi hogyan működik.

A felsorolt - többségében statikus kódelemző - szoftverek abban segítenek, hogy bizonyos közmegállapodás vagy egyénre/projektre szabott szabályok mentén megvizsgálja a gyártott PHP kódot és felhívja a figyelmet az eltérésekre. Mindegyik valahogy máshogy áll hozzá, máshogy kell konfigurálni, használni, más tartalmú és formájú lesz az eredmény. Egyesek jól támogatják a CI/CD integrációt, mások olyan kimenetet tudnak gyártani, amit aztán fejlettebb, aggregálási- és riportolási célú eszközökbe lehet betölteni.

Az én felhasználási módom nagyon egyszerű: egyszemélyes, egyedi kód, kis projekt, egy dev és egy éles rendszer, közötte pedig FTP kapcsolat ("Vér István EV" mód).

Részletezett eszközök:

PHPUnit

A PHP de-facto unit-tesztelő eszköze, aktív fejlesztés alatt, számomra elég full-fledged-nek tűnik a mai napig. Nagyon gyorsan tesztel (másodpercenként 100-200 assertion), informatív lefedettség-riportokat csinál HTML-ben.

Honlap: https://phpunit.de/index.html
Doksi: https://phpunit.de/getting-started/phpunit-11.html
Letöltés (PHAR): https://phar.phpunit.de/phpunit-11.phar

Használat:

php phpunit.phar --configuration phpunit.xml projektkonyvtar

A phpunit.xml tartalma (értelemszerűen testreszabandó, főleg a megadott könyvtárak):

<?xml version="1.0" encoding="UTF-8"?>
<phpunit
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/11.3/phpunit.xsd"
  backupGlobals="false"
  backupStaticProperties="false"
  cacheDirectory="../work/.phpunit.cache"
  cacheResult="true"
  colors="true"
  columns="200"
  requireCoverageMetadata="false"
  processIsolation="false"
  stopOnError="false"
  stopOnFailure="false"
  stopOnIncomplete="false"
  stopOnRisky="false"
  stopOnSkipped="false"
  stopOnWarning="false"
  stopOnDefect="false"
  failOnEmptyTestSuite="true"
  failOnIncomplete="true"
  failOnRisky="true"
  failOnSkipped="false"
  failOnWarning="true"
  beStrictAboutChangesToGlobalState="true"
  beStrictAboutOutputDuringTests="true"
  beStrictAboutTestsThatDoNotTestAnything="true"
  beStrictAboutCoverageMetadata="true"
  enforceTimeLimit="false"
  defaultTimeLimit="0"
  timeoutForSmallTests="1"
  timeoutForMediumTests="10"
  timeoutForLargeTests="60"
  stderr="false"
  reverseDefectList="false"
  executionOrder="depends,defects"
  resolveDependencies="true"
  testdox="false"
  displayDetailsOnIncompleteTests="true"
  displayDetailsOnSkippedTests="true"
  displayDetailsOnTestsThatTriggerDeprecations="true"
  displayDetailsOnTestsThatTriggerErrors="true"
  displayDetailsOnTestsThatTriggerNotices="true"
  displayDetailsOnTestsThatTriggerWarnings="true"
  shortenArraysForExportThreshold="10"
  displayDetailsOnPhpunitDeprecations="true"
  failOnPhpunitDeprecation="true"
>
  <testsuites>
    <testsuite name="default">
      <directory>tests</directory>
    </testsuite>
  </testsuites>

  <source
    ignoreIndirectDeprecations="false"
    restrictNotices="false"
    restrictWarnings="false"
  >
    <include>
      <directory suffix=".php">../src</directory>
    </include>
  </source>

  <coverage
    includeUncoveredFiles="true"
    pathCoverage="true"
    ignoreDeprecatedCodeUnits="false"
    disableCodeCoverageIgnore="false"
  >
    <report>
      <html outputDirectory="../work/coverage" lowUpperBound="50" highLowerBound="90" />
    </report>
  </coverage>
</phpunit>

Fontos: a coverage riporthoz szükség van az xdebug extension bekapcsolására (php.ini-ben):

zend_extension=xdebug-3.3.2-8.2-vs16-nts-x86_64
xdebug.mode=coverage

Példariport:

PHP CodeSniffer (phpcs) és PHP Code Beautifier and Fixer (phpcbf)

A marketing szerint tiszta kód és konzisztencia elősegítő eszköz. A phpcs csak kiírja a szabálysértéseket, a phpcbf képes ezekből néhányat automatikusan javítani (pl. kódformázással kapcsolatosakat).

Honlap: https://github.com/PHPCSStandards/PHP_CodeSniffer/
Doksi: https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki
Letöltés (PHAR): https://github.com/PHPCSStandards/PHP_CodeSniffer/releases

Használat:

php phpcs.phar -s --standard=phpcs.xml -l projektkonyvtar

Van néhány előre összeállított szabálykészlet, amiket lehet használni, ezeket amúgy ki lehet iratni a phpcs -i paranccsal, amiről két dolgot kell tudni:

  1. nem listázza a "Generic" készletet
  2. még benne van a listában a "MySource" szabálykészlet, ami a következő verziótól deprecated lesz

A phpcs.xml tartalma (a könyvtárakat és a kihagyott elemeket érdemes elsősorban testreszabni, de akár a szabályokat is, törekedtem azért egy elég szigorú eredményt összerakni):

<?xml version="1.0"?>
<ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Custom rules" xsi:noNamespaceSchemaLocation="phpcs.xsd">
    <description>The coding standard MVC Framework</description>

    <file>src</file>

    <exclude-pattern>*/tests</exclude-pattern>

    <arg name="basepath" value="../src"/>
    <arg name="colors"/>
    <arg name="parallel" value="16"/>

    <rule ref="PEAR"></rule>
    <rule ref="PSR1"></rule>
    <rule ref="PSR2"></rule>
    <rule ref="PSR12"></rule>
    <rule ref="Squiz"></rule>
    <rule ref="Zend"></rule>

    <rule ref="Generic">
        <exclude name="Generic.Arrays.DisallowShortArraySyntax.Found" />
        <exclude name="Generic.Classes.OpeningBraceSameLine.BraceOnNewLine" />
        <exclude name="Generic.Files.EndFileNoNewline.Found" />
        <exclude name="Generic.Formatting.MultipleStatementAlignment.NotSame" />
        <exclude name="Generic.Formatting.SpaceAfterNot.Incorrect" />
        <exclude name="Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine" />
        <exclude name="Generic.PHP.ClosingPHPTag" />
        <exclude name="Generic.PHP.UpperCaseConstant.Found" />
        <exclude name="Generic.WhiteSpace.DisallowSpaceIndent.SpacesUsed" />
        <exclude name="PEAR.Commenting.ClassComment.MissingAuthorTag" />
        <exclude name="PEAR.Commenting.ClassComment.MissingCategoryTag" />
        <exclude name="PEAR.Commenting.ClassComment.MissingLicenseTag" />
        <exclude name="PEAR.Commenting.ClassComment.MissingLicenseTag" />
        <exclude name="PEAR.Commenting.ClassComment.MissingLinkTag" />
        <exclude name="PEAR.Commenting.ClassComment.MissingPackageTag" />
        <exclude name="PEAR.NamingConventions.ValidFunctionName.PrivateNoUnderscore" />
        <exclude name="PEAR.NamingConventions.ValidVariableName.PrivateNoUnderscore" />
        <exclude name="Squiz.Arrays.ArrayDeclaration.DoubleArrowNotAligned" />
        <exclude name="Squiz.Arrays.ArrayDeclaration.SingleLineNotAllowed" />
        <exclude name="Squiz.Classes.ClassFileName.NoMatch" />
        <exclude name="Squiz.Commenting.ClosingDeclarationComment.Missing" />
        <exclude name="Squiz.Commenting.FileComment.AuthorTagOrder" />
        <exclude name="Squiz.Commenting.FileComment.CopyrightTagOrder" />
        <exclude name="Squiz.Commenting.FileComment.IncorrectAuthor" />
        <exclude name="Squiz.Commenting.FileComment.IncorrectCopyright" />
        <exclude name="Squiz.Commenting.FileComment.PackageTagOrder" />
        <exclude name="Squiz.Commenting.FileComment.SpacingAfterOpen" />
        <exclude name="Squiz.Commenting.FileComment.SubpackageTagOrder" />
        <exclude name="Squiz.Commenting.FunctionComment.InvalidReturn" />
        <exclude name="Squiz.Commenting.LongConditionClosingComment.Missing" />
        <exclude name="Squiz.ControlStructures.ElseIfDeclaration.NotAllowed" />
        <exclude name="Squiz.ControlStructures.InlineIfDeclaration.NoBrackets" />
        <exclude name="Squiz.Files.FileExtension.ClassFound" />
        <exclude name="Squiz.Formatting.OperatorBracket.MissingBrackets" />
        <exclude name="Squiz.Functions.GlobalFunction.Found" />
        <exclude name="Squiz.PHP.DisallowBooleanStatement.Found" />
        <exclude name="Squiz.PHP.DisallowComparisonAssignment.AssignedComparison" />
        <exclude name="Squiz.PHP.DisallowInlineIf.Found" />
        <exclude name="Squiz.Strings.ConcatenationSpacing.PaddingFound" />
        <exclude name="Squiz.Strings.DoubleQuoteUsage.ContainsVar" />
        <exclude name="Squiz.WhiteSpace.FunctionClosingBraceSpace.SpacingBeforeClose" />
        <exclude name="Squiz.WhiteSpace.FunctionSpacing.AfterLast" />
        <exclude name="Squiz.WhiteSpace.FunctionSpacing.BeforeFirst" />
        <exclude name="Squiz.WhiteSpace.MemberVarSpacing.FirstIncorrect" />
        <exclude name="Zend.NamingConventions.ValidVariableName.PrivateNoUnderscore" />
        <exclude name="Generic.Formatting.NoSpaceAfterCast.SpaceFound" />
        <exclude name="Squiz.ControlStructures.InlineIfDeclaration.NotSingleLine" />
        <exclude name="Squiz.WhiteSpace.OperatorSpacing.SpacingBefore" />
    </rule>

    <rule ref="Generic.Files.LineLength">
        <properties>
            <property name="lineLimit" value="140"/>
            <property name="absoluteLineLimit" value="140"/>
        </properties>
    </rule>

    <rule ref="Squiz.WhiteSpace.FunctionSpacing">
        <properties>
            <property name="spacing" value="1"/>
        </properties>
    </rule>
</ruleset>

Példa kimenet:

PHP Mess Detector (régen: PHP Depend)

A phpmd azt tűzte ki célul, hogy felhívja a figyelmet azokra a kódrészletekre, amik nem követik a best practice-eket, fölöslegesen bonyolultak, esetleg nem használt részletek/változók vannak benne.

Honlap: https://phpmd.org/
Doksi: https://phpmd.org/documentation/index.html
Letöltés (PHAR): https://phpmd.org/static/latest/phpmd.phar

Használat:

php phpmd.phar projektkonyvtar text phpmd.xml

A phpmd.xml tartalma:

<?xml version="1.0"?>
<ruleset
    name="The coding standard MVC Framework"
    xmlns="https://phpmd.org/xml/ruleset/1.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="https://phpmd.org/xml/ruleset/1.0.0 http://phpmd.org/xml/ruleset_xml_schema_1.0.0.xsd"
    xsi:noNamespaceSchemaLocation="http://phpmd.org/xml/ruleset_xml_schema_1.0.0.xsd"
>
    <description>The coding standard MVC Framework</description>

    <rule ref="rulesets/codesize.xml">
        <exclude name="TooManyPublicMethods" />
    </rule>

    <rule ref="rulesets/cleancode.xml">
        <exclude name="ElseExpression" />
        <exclude name="MissingImport" />
    </rule>
    <rule ref="rulesets/controversial.xml" />
    <rule ref="rulesets/design.xml" />
    <rule ref="rulesets/naming.xml" />
    <rule ref="rulesets/unusedcode.xml" />
</ruleset>

Példakimenet:

PHPStan

A PHP jelenlegi statikus típus-támogatása hagy maga után kívánnivalót. A phpstan célja, hogy a következő szintre emelje ezt, hozzáadva olyan dolgokat, amik még nem a nyelv szerves részei (pl. generikus típusok) és magával hozza annak összes előnyét (karbantarthatóság, csapatmunka, jövőállóság, stb).

Honlap: https://phpstan.org/
Doksi: https://phpstan.org/user-guide/getting-started
Letöltés (PHAR): https://github.com/phpstan/phpstan/releases

Használat:

php phpstan.phar analyse -c phpstan.neon %%projektkonyvtar

A phpstan.neon tartalma:

parameters:
    level: max
    featureToggles:
        bleedingEdge: true
        skipCheckGenericClasses!: []
        explicitMixedInUnknownGenericNew: true
        explicitMixedForGlobalVariables: true
        explicitMixedViaIsArray: true
        arrayFilter: true
        arrayUnpacking: true
        nodeConnectingVisitorCompatibility: false
        nodeConnectingVisitorRule: true
        disableCheckMissingIterableValueType: true
        strictUnnecessaryNullsafePropertyFetch: true
        looseComparison: true
        consistentConstructor: true
        checkUnresolvableParameterTypes: true
        readOnlyByPhpDoc: true
        phpDocParserRequireWhitespaceBeforeDescription: true
        runtimeReflectionRules: true
        notAnalysedTrait: true
        curlSetOptTypes: true
        listType: true
        missingMagicSerializationRule: true
        nullContextForVoidReturningFunctions: true
        unescapeStrings: true
        duplicateStubs: true
        invarianceComposition: true
        alwaysTrueAlwaysReported: true
        disableUnreachableBranchesRules: true
        varTagType: true
        closureDefaultParameterTypeRule: true
        newRuleLevelHelper: true
        instanceofType: true
        paramOutVariance: true
        allInvalidPhpDocs: true
        strictStaticMethodTemplateTypeVariance: true
        propertyVariance: true
        genericPrototypeMessage: true
        stricterFunctionMap: true
    excludePaths:
        - ../tests/*

Churn-php

A churn-php segít megállapítani, hogy mit érdemes refaktorálni. Ezt egy varázsképlettel számolja ki, ami figyelembe veszi a fájl változásának ütemét (git logból) illetve a komplexitását. Ezekből előállít egy számot, ami indikátora lehet annak, hogy mihez érdemes nyúlni. Összehasonlítva azzal, ha pl. a kód keveset változik vagy egyszerű, akkor fölösleges lenne a refaktoráláson gondolkodni.

Honlap: https://github.com/bmitch/churn-php
Doksi: https://github.com/bmitch/churn-php
Letöltés (PHAR): https://github.com/bmitch/churn-php/releases

Használat:

php churn.phar run --configuration=php-churn.yml projektkonyvtar

A php-churn.xml tartalma:

filesToShow: 100
minScoreToShow: null
maxScoreThreshold: null
parallelJobs: 16
commitsSince: '2000-01-01'
fileExtensions:
 - php
directoriesToScan:
 - projektkonyvtar
vcs: git
cachePath: .churn.cache

Példakimenet:

PhpDeprecationDetector

Ahogy a neve állítja: kiszúrja azokat a dolgokat, amik elavultak, kivezetésre kerültek vagy fognak kerülni, röviden: ami eltörik, ha az app újabb PHP-vel fut.

Honlap: https://wapmorgan.github.io/PhpDeprecationDetector/
Doksi: https://wapmorgan.github.io/PhpDeprecationDetector/
Letöltés (PHAR): https://github.com/wapmorgan/PhpDeprecationDetector/releases

Használat:

php phpdd-2.0.33.phar scan projektkonyvtar

Példakimenet:

Psalm - PHP Static Analysis Tool

A psalm-et a vimeo tartja karban, statikus kódelemzést csinál, ahogyan a többi említett eszköz is. Ez is figyelmet fordít a típusokra illetve "hibás kódot keres". A doksijában le van pontosan írva az összes elérhető szabály, a lenti konfiggal pedig a legszigorúbb ellenőrzést kaphatjuk.

Honlap: https://psalm.dev/
Doksi: https://psalm.dev/docs/
Letöltés (PHAR): https://github.com/vimeo/psalm/releases

Használat:

php psalm.phar --config=psalm.xml projektkonyvtar

A psalm.xml fájl tartalma:

<?xml version="1.0"?>
<psalm errorLevel="1" resolveFromConfigFile="true" useDocblockTypes="false" findUnusedBaselineEntry="false" findUnusedCode="false">
    <projectFiles>
        <directory name="../src" />
    </projectFiles>
</psalm>

Példakimenet:

PHPLint

Általános linter eszköz PHP-hez.

Honlap: https://github.com/overtrue/phplint
Doksi: https://github.com/overtrue/phplint/blob/main/docs/usage/console.md
Letöltés (PHAR): https://github.com/overtrue/phplint/releases

Használat:

php D:\usr\prg\php\pear\phplint.phar -c qa/phplint.yml

A phplint.yml tartalma:

path: ./src
jobs: 16
extensions:
  - php
exclude:
  - tests
warning: true
memory-limit: -1
cache: ./work/phplint.cache

Példakimenet:

Phan - PHP Analyzer

A phan célja nem a helyesség ellenőrzése, hanem a hibák kimutatása. Rengeteg pluginje van, a típushibáktól a clean kód aspektusaiig elég sokmindent felölel. Van pl. olyan pluginje, ami azt ellenőrzi, hogy egy modernebb PHP verzióhoz készült kód hol törhet el, ha régebbi értelmezővel futtatjuk.

Honlap: https://github.com/phan/phan
Doksi: https://github.com/phan/phan/wiki
Letöltés (PHAR): https://github.com/phan/phan/releases

Fontos, hogy szükséges hozzá a php_ast extension a php-hez, amit innen lehet beszerezni: https://downloads.php.net/~windows/pecl/releases/ast/.

A php.ini-be pedig csak ennyi kell utána:

extension=ast

Használat:

php phan.phar -k phan.php -C -m verbose

A phan.php tartalma:

<?php
declare(strict_types=1);

use Phan\Issue;

return [
    'target_php_version' => null,
    'pretend_newer_core_functions_exist' => true,
    'allow_missing_properties' => false,
    'null_casts_as_any_type' => false,
    'null_casts_as_array' => false,
    'array_casts_as_null' => false,
    'strict_method_checking' => true,
    'strict_param_checking' => true,
    'strict_property_checking' => true,
    'strict_return_checking' => true,
    'scalar_implicit_cast' => false,
    'scalar_array_key_cast' => false,
    'scalar_implicit_partial' => [],
    'ignore_undeclared_variables_in_global_scope' => false,
    'backward_compatibility_checks' => false,
    'check_docblock_signature_return_type_match' => true,
    'check_docblock_signature_param_type_match' => true,
    'prefer_narrowed_phpdoc_param_type' => true,
    'prefer_narrowed_phpdoc_return_type' => true,
    'analyze_signature_compatibility' => true,
    'allow_method_param_type_widening' => false,
    'guess_unknown_parameter_type_using_default' => false,
    'phpdoc_type_mapping' => [],
    'dead_code_detection' => false,
    'unused_variable_detection' => true,
    'force_tracking_references' => false,
    'warn_about_redundant_use_namespaced_class' => true,
    'quick_mode' => false,
    'simplify_ast' => true,
    'enable_class_alias_support' => false,
    'generic_types_enabled' => true,
    'warn_about_undocumented_throw_statements' => true,
    'warn_about_undocumented_exceptions_thrown_by_invoked_functions' => true,
    'exception_classes_with_optional_throws_phpdoc' => [],
    'max_literal_string_type_length' => 1000,
    'consistent_hashing_file_order' => false,
    'globals_type_map' => [],
    'minimum_severity' => Issue::SEVERITY_LOW,
    'suppress_issue_types' => [],
    'whitelist_issue_types' => [],
    'file_list' => [],
    'exclude_file_regex' => '#tests/.*#',
    'enable_include_path_checks' => true,
    'include_paths' => ['.'],
    'warn_about_relative_include_statement' => true,
    'exclude_file_list' => [],
    'processes' => 1,
    'directory_list' => ['src'],
    'analyzed_file_extensions' => ['php'],
    'exclude_analysis_directory_list' => ['vendor/'],
    'skip_slow_php_options_warning' => true,
    'autoload_internal_extension_signatures' => [],
    'ignore_undeclared_functions_with_known_signatures' => false,
    'plugin_config' => ['php_native_syntax_check_max_processes' => 16],
    'plugins' => [
        'AddNeverReturnTypePlugin',
        'AlwaysReturnPlugin',
        'AvoidableGetterPlugin',
        'ConstantVariablePlugin',
        'DemoPlugin',
        'DeprecateAliasPlugin',
        'DollarDollarPlugin',
        'DuplicateArrayKeyPlugin',
        'DuplicateConstantPlugin',
        'DuplicateExpressionPlugin',
        'EmptyMethodAndFunctionPlugin',
        'EmptyStatementListPlugin',
        'FFIAnalysisPlugin',
        'HasPHPDocPlugin',
        'InlineHTMLPlugin',
        'InvalidVariableIssetPlugin',
        'InvokePHPNativeSyntaxCheckPlugin',
        'LoopVariableReusePlugin',
        'MoreSpecificElementTypePlugin',
        'NoAssertPlugin',
        'NonBoolBranchPlugin',
        'NonBoolInLogicalArithPlugin',
        'NotFullyQualifiedUsagePlugin',
        'NumericalComparisonPlugin',
        'PhanSelfCheckPlugin',
        'PHPDocInWrongCommentPlugin',
        'PHPDocRedundantPlugin',
        'PHPDocToRealTypesPlugin',
        'PHPUnitAssertionPlugin',
        'PHPUnitNotDeadCodePlugin',
        'PossiblyStaticMethodPlugin',
        'PreferNamespaceUsePlugin',
        'PregRegexCheckerPlugin',
        'PrintfCheckerPlugin',
        'RedundantAssignmentPlugin',
        'RemoveDebugStatementPlugin',
        'SimplifyExpressionPlugin',
        'SleepCheckerPlugin',
        'StaticVariableMisusePlugin',
        'StrictComparisonPlugin',
        'StrictLiteralComparisonPlugin',
        'SuspiciousParamOrderPlugin',
        'UnknownClassElementAccessPlugin',
        'UnknownElementTypePlugin',
        'UnreachableCodePlugin',
        'UnsafeCodePlugin',
        'UnusedSuppressionPlugin',
        'UseReturnValuePlugin',
        'WhitespacePlugin',
    ],
];

Példakimenet:

PHP Copy/Paste Detector (PHPCPD)

Ahogy a neve mondja: megkeresi azokat a kódrészleteket, amik többszörözve vannak. A projekt elvileg már nem aktív.

Honlap: https://github.com/sebastianbergmann/phpcpd
Doksi: https://github.com/sebastianbergmann/phpcpd
Letöltés (PHAR): https://phar.phpunit.de/phpcpd.phar

Használat:

php phpcpd.phar --fuzzy projektkonyvtar

Példakimenet:

Bónusz

A fenti eszközök futtatása akár kézi, akár automatizált, igénybe vesz egy kis időt. Viszont, ha hasonló funkcionalitást szeretnénk, mint pl. a jest-nél a "watch mode" (az egyik JavaScript unit-testing eszköz), akkor igénybe vehetjük a "nodemon", vagyis a node monitor nevű toolt.

Telepítés:

npm install -g nodemon

Ezzel elérhetővé válik a nodemon parancs, amit változatos módon felparaméterezhetünk, mint például:

nodemon --watch src --watch tests --ext php --exec "php phpunit.phar --no-coverage --configuration qa/phpunit.xml tests || exit 0"
nodemon --watch src --watch qa --ext php,xml --exec "php D:\usr\prg\php\pear\phpcs.phar -s --standard=qa/phpcs.xml src | head -n 30"
nodemon --watch src --watch qa --ext php,xml --exec "php D:\usr\prg\php\pear\phpmd.phar src text qa/phpmd.xml || exit 0"

Ezzel a módszerrel a megadott könyvtárakban lévő szintén megadott kiterjesztésű fájlokat figyeli, és amint bármelyik változik, újraindítja az --exec kapcsolóban adott parancsot. Azaz, minden mentés után automatikusan lefuttatja azt az eszközt, ami alapján éppen kódot csiszolunk.

Egyéb hasznos eszközök